1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use IO::Async::Test;
7
8use Test::More;
9use Test::Refcount;
10
11use lib ".";
12use t::TimeAbout;
13
14use Time::HiRes qw( time );
15
16use IO::Async::Timer::Absolute;
17
18use IO::Async::Loop;
19
20use constant AUT => $ENV{TEST_QUICK_TIMERS} ? 0.1 : 1;
21
22my $loop = IO::Async::Loop->new_builtin;
23
24testing_loop( $loop );
25
26{
27   my $expired;
28   my @eargs;
29
30   my $timer = IO::Async::Timer::Absolute->new(
31      time => time + 2 * AUT,
32
33      on_expire => sub { @eargs = @_; $expired = 1 },
34   );
35
36   ok( defined $timer, '$timer defined' );
37   isa_ok( $timer, "IO::Async::Timer", '$timer isa IO::Async::Timer' );
38
39   is_oneref( $timer, '$timer has refcount 1 initially' );
40
41   $loop->add( $timer );
42
43   is_refcount( $timer, 2, '$timer has refcount 2 after adding to Loop' );
44
45   ok( $timer->is_running, 'Started Timer is running' );
46
47   time_about( sub { wait_for { $expired } }, 2, 'Timer works' );
48   is_deeply( \@eargs, [ $timer ], 'on_expire args' );
49
50   ok( !$timer->is_running, 'Expired Timer is no longer running' );
51
52   undef @eargs;
53
54   is_refcount( $timer, 2, '$timer has refcount 2 before removing from Loop' );
55
56   $loop->remove( $timer );
57
58   is_oneref( $timer, '$timer has refcount 1 after removing from Loop' );
59}
60
61{
62   my $expired;
63
64   my $timer = IO::Async::Timer::Absolute->new(
65      time => time + 2 * AUT,
66      on_expire => sub { $expired++ },
67   );
68
69   $loop->add( $timer );
70   $loop->remove( $timer );
71
72   $loop->loop_once( 3 * AUT );
73
74   ok( !$expired, "Removed Timer does not expire" );
75}
76
77{
78   my $expired;
79
80   my $timer = IO::Async::Timer::Absolute->new(
81      time => time + 5 * AUT,
82      on_expire => sub { $expired++ },
83   );
84
85   $loop->add( $timer );
86
87   $timer->configure( time => time + 1 * AUT );
88
89   time_about( sub { wait_for { $expired } }, 1, 'Reconfigured timer works' );
90
91   $loop->remove( $timer );
92}
93
94{
95   my $timer = IO::Async::Timer::Absolute->new(
96      time => time + 1 * AUT,
97      on_expire => sub { die "Test failed to replace expiry handler" },
98   );
99
100   $loop->add( $timer );
101
102   my $new_expired;
103   $timer->configure( on_expire => sub { $new_expired = 1 } );
104
105   time_about( sub { wait_for { $new_expired } }, 1, 'Reconfigured timer on_expire works' );
106
107   $loop->remove( $timer );
108}
109
110## Subclass
111
112my $sub_expired;
113{
114   my $timer = TestTimer->new(
115      time => time + 2 * AUT,
116   );
117
118   ok( defined $timer, 'subclass $timer defined' );
119   isa_ok( $timer, "IO::Async::Timer", 'subclass $timer isa IO::Async::Timer' );
120
121   is_oneref( $timer, 'subclass $timer has refcount 1 initially' );
122
123   $loop->add( $timer );
124
125   is_refcount( $timer, 2, 'subclass $timer has refcount 2 after adding to Loop' );
126
127   ok( $timer->is_running, 'Started subclass Timer is running' );
128
129   time_about( sub { wait_for { $sub_expired } }, 2, 'subclass Timer works' );
130
131   ok( !$timer->is_running, 'Expired subclass Timer is no longer running' );
132
133   is_refcount( $timer, 2, 'subclass $timer has refcount 2 before removing from Loop' );
134
135   $loop->remove( $timer );
136
137   is_oneref( $timer, 'subclass $timer has refcount 1 after removing from Loop' );
138}
139
140done_testing;
141
142package TestTimer;
143use base qw( IO::Async::Timer::Absolute );
144
145sub on_expire { $sub_expired = 1 }
146