init commit
[urisagit/Stem.git] / t / event / event_test.pl
1 #!/usr/local/bin/perl -w
2
3 BEGIN {
4         $Stem::Vars::Env{ 'event_loop' } = shift ;
5
6         unless ( eval { require Time::HiRes } ) {
7
8                 Time::HiRes->import( qw( time ) ) ;
9         }
10 }
11
12 use strict ;
13
14 #use Test::More tests => 29 ;
15 use Test::More tests => 24 ;
16
17 use Symbol ;
18
19 use Stem::Event ;
20 use Stem::Class ;
21
22 my $self = bless {} ;
23
24 test_events() ;
25
26 exit ;
27
28 sub test_events {
29
30 #       test_null_events() ;
31 #       test_plain_events () ;
32 #       test_signal_events () ;
33         test_hard_timer_events () ;
34         test_soft_timer_events () ;
35         test_io_events () ;
36 }
37
38 sub test_null_events {
39
40         local $SIG{__WARN__} = sub{} if
41                         $Stem::Vars::Env{ 'event_loop' } eq 'event' ;
42
43         Stem::Event::start_loop() ;
44
45         ok( 1, 'null - event loop exit' ) ;
46 }
47
48 sub test_plain_events {
49
50         my $event = Stem::Event::Plain->new(
51                 'object' => $self
52         ) ;
53
54         ok( ref $event, 'plain event created' ) ;
55
56         Stem::Event::start_loop() ;
57
58         ok( 1, 'plain - event loop exit' ) ;
59 }
60
61 # callback method for plain
62
63 sub triggered {
64
65         my( $self ) = @_ ;
66
67         ok( 1, 'plain event triggered' ) ;
68 }
69
70 sub test_signal_events {
71
72         SKIP: {
73                 if ( $^O =~ /win32/i ) {
74
75                         skip( "signals not supported on windows", 3 ) ;
76                         return ;
77                 }
78
79                 my $event = Stem::Event::Signal->new(
80                         'object'        => $self,
81                         'signal'        => 'INT',
82                 ) ;
83
84                 ok( ref $event, 'signal event created' ) ;
85
86                 $self->{'sig_event'} = $event ;
87
88                 kill 'INT', $$ ;
89
90 #print "kill INT\n" ;
91
92                 Stem::Event::start_loop() ;
93
94                 ok( 1, 'signal - event loop exit' ) ;
95         }
96 }
97
98 # callback method for signal
99
100 sub sig_int_handler {
101
102         my( $self ) = @_ ;
103
104         ok( 1, 'signal event triggered' ) ;
105
106         $self->{'sig_event'}->cancel() ;
107         Stem::Event::stop_loop() ;
108 }
109
110
111 use constant INTERVAL   => 4 ;
112 use constant SLEEP      => 2 ;
113 use constant TIMER_CNT  => 2 ;
114
115 # hard timeouts are timed from the beginning of the callback. so accumulated
116 # time in the callback doesn't affect the next callback.
117
118 sub test_hard_timer_events {
119
120         my $event = Stem::Event::Timer->new(
121                 'object'        => $self,
122                 'method'        => 'hard_timeout',
123                 'interval'      => INTERVAL,
124                 'delay'         => INTERVAL,    # REMOVE - only for .10
125                 'repeat'        => 1,
126                 'hard'          => 1,
127         ) ;
128
129         ok( ref $event, 'hard timer event created' ) ;
130         print "$event\n" unless ref $event ;
131
132         $self->{'hard_timer_event'} = $event ;
133         $self->{'hard_timer_count'} = TIMER_CNT ;
134         $self->{'hard_timer_start_time'} = time ;
135
136         Stem::Event::start_loop() ;
137
138         ok( 1, 'hard timer - event loop exit' ) ;
139 }
140
141 sub hard_timeout {
142
143         my( $self ) = @_ ;
144
145         ok( 1, 'hard timer event triggered' ) ;
146
147         if ( --$self->{'hard_timer_count'} > 0 ) {
148
149                 my $time = time ;
150                 my $delta = $time - $self->{'hard_timer_start_time'} ;
151                 $self->{'hard_timer_start_time'} = $time ;
152
153                 ok( $delta >= INTERVAL, 'hard delta' ) ;
154
155                 hard_sleep( SLEEP ) ;
156
157                 return ;
158         }
159
160         
161         my $time = time ;
162         my $delta = $time - $self->{'hard_timer_start_time'} ;
163
164 #print "O $self->{'hard_timer_start_time'} T $time D $delta I ", INTERVAL, "\n" ;
165
166         ok( $delta >= INTERVAL, 'hard delta 2' ) ;
167         ok( $delta <= INTERVAL + SLEEP, 'hard delta sleep' ) ;
168
169         $self->{'hard_timer_event'}->cancel() ;
170
171         Stem::Event::stop_loop() ;
172 }
173
174
175 # Soft timeouts are timed from the end of the callback. so accumulated
176 # time in the callback delays the next callback.
177
178 sub test_soft_timer_events {
179
180         my $event = Stem::Event::Timer->new(
181                 'object'        => $self,
182                 'method'        => 'soft_timeout',
183                 'interval'      => INTERVAL,
184                 'delay'         => INTERVAL,    # REMOVE  - only for .10
185                 'repeat'        => 1,
186         ) ;
187
188         ok( ref $event, 'soft timer event created' ) ;
189 #       print "$event\n" unless ref $event ;
190
191         $self->{'soft_timer_event'} = $event ;
192         $self->{'soft_timer_count'} = TIMER_CNT ;
193         $self->{'soft_timer_start_time'} = time ;
194
195 #print "OTIME $self->{'soft_timer_start_time'}\n" ;
196
197         Stem::Event::start_loop() ;
198
199         ok( 1, 'soft timer - event loop exit' ) ;
200 }
201
202 sub soft_timeout {
203
204         my( $self ) = @_ ;
205
206         ok( 1, 'soft timer event triggered' ) ;
207
208         if ( --$self->{'soft_timer_count'} > 0 ) {
209
210                 my $time = time ;
211                 my $delta = $time - $self->{'soft_timer_start_time'} ;
212
213 #print "T $time D $delta I ", INTERVAL, "\n" ;
214
215                 ok( $delta >= INTERVAL, 'soft delta' ) ;
216
217                 hard_sleep( SLEEP ) ;
218
219 #my $curr_time = time() ;
220 #print "DONE $curr_time\n" ;
221
222                 return ;
223         }
224
225         my $time = time ;
226         my $delta = $time - $self->{'soft_timer_start_time'} ;
227
228 #print "TIME2 $time OTIME $self->{'soft_timer_start_time'} DEL $delta INTERVAL ", INTERVAL, "\n" ;
229
230 #       ok( $delta >= INTERVAL, 'soft delta 2' ) ;
231         ok( $delta >= INTERVAL + SLEEP, 'soft delta 3' ) ;
232
233         $self->{'soft_timer_event'}->cancel() ;
234
235         Stem::Event::stop_loop() ;
236 }
237
238 sub test_io_events {
239
240         Stem::Event::init_loop() ;
241
242         my $read_fh = gensym ;
243         my $write_fh = gensym ;
244
245 # get a pipe to read/write through.
246
247         use Socket;
248         socketpair( $read_fh, $write_fh, AF_UNIX, SOCK_STREAM, PF_UNSPEC ) ;
249
250         $self->{read_fh} = $read_fh ;
251         $self->{write_fh} = $write_fh ;
252         $self->{message} = 'Stem Read/Write Event' ;
253
254         # create the read and write events
255
256         my $read_event = Stem::Event::Read->new(
257                                 'object'        =>      $self,
258                                 'fh'            =>      $read_fh,
259                                 'timeout'       =>      3,
260         ) ;
261
262         ok( ref $read_event, 'read event created' ) ;
263         $self->{'read_event'} = $read_event ;
264
265         my $write_event = Stem::Event::Write->new(
266                                 'object'        =>      $self,
267                                 'fh'            =>      $write_fh,
268         ) ;
269
270         ok( ref $write_event, 'write event created' ) ;
271         $self->{'write_event'} = $write_event ;
272
273         Stem::Event::start_loop() ;
274
275         ok( 1, 'io - event loop exit' ) ;
276 }
277
278 sub read_timeout {
279
280         my( $self ) = @_ ;
281
282         ok( 1, 'read event timed out' ) ;
283
284         $self->{'write_event'}->start() ;
285 }
286
287
288 sub writeable {
289
290         my( $self ) = @_ ;
291
292         ok( 1, 'write event triggered' ) ;
293
294         syswrite( $self->{'write_fh'}, $self->{'message'} ) ;
295
296         $self->{'write_event'}->cancel() ;
297 }
298
299 sub readable {
300
301         my( $self ) = @_ ;
302
303         ok(1, 'read event triggered' ) ;
304
305         my( $read_buf ) ;
306
307         my $bytes_read = sysread( $self->{'read_fh'}, $read_buf, 1000 ) ;
308
309         ok( $bytes_read, 'read byte count' ) ;
310
311         is( $read_buf, $self->{'message'}, 'read event compare' ) ;
312
313         $self->{'read_event'}->cancel() ;
314
315         Stem::Event::stop_loop() ;
316 }
317
318 # do a real hard sleep without alarm signal as that can screw up the tests
319 # sleep time is in (float) seconds
320
321 sub hard_sleep {
322
323         my( $sleep_time ) = @_ ;
324
325 #print "BEFORE TIME $sleep_time\n" ;
326         while( $sleep_time > 0 ) {
327
328                 my $curr_time = time() ;
329                 select( undef, undef, undef, $sleep_time ) ;
330
331                 $sleep_time -= time() - $curr_time ;
332
333 #print "AFTER TIME $sleep_time\n" ;
334         }
335 }
336
337 1 ;