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