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