line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Mock::Time; |
2
|
8
|
|
|
8
|
|
476584
|
use 5.008001; |
|
8
|
|
|
|
|
103
|
|
3
|
8
|
|
|
8
|
|
36
|
use warnings; |
|
8
|
|
|
|
|
11
|
|
|
8
|
|
|
|
|
175
|
|
4
|
8
|
|
|
8
|
|
35
|
use strict; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
141
|
|
5
|
8
|
|
|
8
|
|
1041
|
use utf8; |
|
8
|
|
|
|
|
41
|
|
|
8
|
|
|
|
|
51
|
|
6
|
8
|
|
|
8
|
|
190
|
use Carp; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
547
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = 'v0.2.0'; |
9
|
|
|
|
|
|
|
|
10
|
8
|
|
|
8
|
|
3173
|
use Export::Attrs; |
|
8
|
|
|
|
|
58019
|
|
|
8
|
|
|
|
|
43
|
|
11
|
8
|
|
|
8
|
|
589
|
use List::Util qw( any ); |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
779
|
|
12
|
8
|
|
|
8
|
|
56
|
use Scalar::Util qw( weaken ); |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
348
|
|
13
|
8
|
|
|
8
|
|
3297
|
use Test::MockModule; |
|
8
|
|
|
|
|
35295
|
|
|
8
|
|
|
|
|
59
|
|
14
|
|
|
|
|
|
|
|
15
|
8
|
|
|
8
|
|
304
|
use constant TIME_HIRES_CLOCK_NOT_SUPPORTED => -1; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
617
|
|
16
|
8
|
|
|
8
|
|
44
|
use constant MICROSECONDS => 1_000_000; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
308
|
|
17
|
8
|
|
|
8
|
|
35
|
use constant NANOSECONDS => 1_000_000_000; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
359
|
|
18
|
|
|
|
|
|
|
|
19
|
8
|
|
|
8
|
|
44
|
use constant DEFAULT_WAIT_ONE_TICK => 0.05; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
3792
|
|
20
|
|
|
|
|
|
|
our $WAIT_ONE_TICK = DEFAULT_WAIT_ONE_TICK; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $Absolute = time; # usual time starts at current actual time |
23
|
|
|
|
|
|
|
my $Monotonic = 0; # monotonic time starts at 0 if not available |
24
|
|
|
|
|
|
|
my $Relative = 0; # how many deterministic time passed since start |
25
|
|
|
|
|
|
|
my @Timers; # active timers |
26
|
|
|
|
|
|
|
my @Timers_ns; # inactive timers |
27
|
|
|
|
|
|
|
my %Module; # keep module mocks |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
_mock_core_global(); |
31
|
|
|
|
|
|
|
## no critic (RequireCheckingReturnValueOfEval) |
32
|
|
|
|
|
|
|
eval { |
33
|
|
|
|
|
|
|
require Time::HiRes; |
34
|
|
|
|
|
|
|
Time::HiRes->import(qw( CLOCK_REALTIME CLOCK_MONOTONIC )); |
35
|
|
|
|
|
|
|
_mock_time_hires(); |
36
|
|
|
|
|
|
|
}; |
37
|
|
|
|
|
|
|
eval { |
38
|
|
|
|
|
|
|
require EV; |
39
|
|
|
|
|
|
|
_mock_ev(); |
40
|
|
|
|
|
|
|
}; |
41
|
|
|
|
|
|
|
eval { |
42
|
|
|
|
|
|
|
require Mojolicious; |
43
|
|
|
|
|
|
|
Mojolicious->VERSION('6'); # may be compatible with older ones, needs testing |
44
|
|
|
|
|
|
|
require Mojo::Reactor::Poll; |
45
|
|
|
|
|
|
|
_mock_mojolicious(); |
46
|
|
|
|
|
|
|
}; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# FIXME make ff() reentrant |
50
|
|
|
|
|
|
|
sub ff :Export(:DEFAULT) { |
51
|
51
|
|
|
51
|
1
|
572
|
my ($dur) = @_; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
@Timers = sort { |
54
|
51
|
|
|
|
|
142
|
$a->{start}+$a->{after} <=> $b->{start}+$b->{after} or |
55
|
|
|
|
|
|
|
$a->{id} cmp $b->{id} # preserve order to simplify tests |
56
|
0
|
0
|
|
|
|
0
|
} @Timers; |
57
|
51
|
100
|
|
|
|
228
|
my $next_at = @Timers ? $Timers[0]{start}+$Timers[0]{after} : 0; |
58
|
51
|
|
|
|
|
387
|
$next_at = sprintf '%.6f', $next_at; |
59
|
|
|
|
|
|
|
|
60
|
51
|
100
|
|
|
|
153
|
if (!defined $dur) { |
61
|
23
|
50
|
|
|
|
152
|
$dur = $next_at > $Relative ? $next_at - $Relative : 0; |
62
|
23
|
|
|
|
|
93
|
$dur = sprintf '%.6f', $dur; |
63
|
|
|
|
|
|
|
} |
64
|
51
|
50
|
|
|
|
157
|
croak "ff($dur): negative time not invented yet" if $dur < 0; |
65
|
|
|
|
|
|
|
|
66
|
51
|
100
|
100
|
|
|
251
|
if ($next_at == 0 || $next_at > $Relative+$dur) { |
67
|
28
|
|
|
|
|
67
|
$Relative += $dur; |
68
|
28
|
|
|
|
|
104
|
$Relative = sprintf '%.6f', $Relative; |
69
|
28
|
|
|
|
|
86
|
return; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
23
|
50
|
|
|
|
72
|
if ($next_at > $Relative) { |
73
|
23
|
|
|
|
|
43
|
$dur -= $next_at - $Relative; |
74
|
23
|
|
|
|
|
113
|
$dur = sprintf '%.6f', $dur; |
75
|
23
|
|
|
|
|
47
|
$Relative = $next_at; |
76
|
|
|
|
|
|
|
} |
77
|
23
|
|
|
|
|
59
|
my $cb = $Timers[0]{cb}; |
78
|
23
|
100
|
|
|
|
98
|
if ($Timers[0]{repeat} == 0) { |
79
|
7
|
100
|
|
|
|
20
|
if ($Timers[0]{watcher}) { |
80
|
3
|
|
|
|
|
12
|
_stop_timer($Timers[0]{watcher}); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
else { |
83
|
4
|
|
|
|
|
6
|
shift @Timers; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
else { |
87
|
16
|
|
|
|
|
42
|
$Timers[0]{after} = $Timers[0]{repeat}; |
88
|
16
|
|
|
|
|
45
|
$Timers[0]{start} = $Relative; |
89
|
|
|
|
|
|
|
} |
90
|
23
|
|
|
|
|
107
|
$cb->(); |
91
|
23
|
|
|
|
|
308
|
@_ = ($dur); |
92
|
23
|
|
|
|
|
128
|
goto &ff; |
93
|
8
|
|
|
8
|
|
56
|
} |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
77
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
{ |
96
|
|
|
|
|
|
|
my $next_id = 0; |
97
|
|
|
|
|
|
|
sub _add_timer { |
98
|
20
|
|
|
20
|
|
56
|
my ($loop, $after, $repeat, $cb, $watcher) = @_; |
99
|
20
|
|
|
|
|
78
|
my $id = sprintf 'fake_%05d', $next_id++; |
100
|
20
|
50
|
|
|
|
283
|
push @Timers, { |
|
|
50
|
|
|
|
|
|
101
|
|
|
|
|
|
|
id => $id, |
102
|
|
|
|
|
|
|
start => $Relative, |
103
|
|
|
|
|
|
|
loop => $loop, |
104
|
|
|
|
|
|
|
after => sprintf('%.6f', $after < 0 ? 0 : $after), |
105
|
|
|
|
|
|
|
repeat => sprintf('%.6f', $repeat < 0 ? 0 : $repeat), |
106
|
|
|
|
|
|
|
cb => $cb, |
107
|
|
|
|
|
|
|
watcher => $watcher, |
108
|
|
|
|
|
|
|
}; |
109
|
20
|
100
|
|
|
|
82
|
if ($watcher) { |
110
|
13
|
|
|
|
|
44
|
weaken($Timers[-1]{watcher}); |
111
|
|
|
|
|
|
|
} |
112
|
20
|
|
|
|
|
46
|
return $id; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub _start_timer { |
117
|
2
|
|
|
2
|
|
6
|
my ($watcher) = @_; |
118
|
2
|
50
|
|
|
|
5
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $watcher } @Timers_ns; |
|
4
|
|
|
|
|
17
|
|
119
|
2
|
50
|
|
|
|
6
|
if ($timer) { |
120
|
2
|
50
|
|
|
|
4
|
@Timers_ns = grep { !$_->{watcher} || $_->{watcher} ne $watcher } @Timers_ns; |
|
4
|
|
|
|
|
19
|
|
121
|
2
|
|
|
|
|
4
|
push @Timers, $timer; |
122
|
|
|
|
|
|
|
} |
123
|
2
|
|
|
|
|
4
|
return; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _stop_timer { |
127
|
13
|
|
|
13
|
|
27
|
my ($watcher) = @_; |
128
|
13
|
50
|
|
|
|
32
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $watcher } @Timers; |
|
6
|
|
|
|
|
49
|
|
129
|
13
|
100
|
|
|
|
34
|
if ($timer) { |
130
|
6
|
50
|
|
|
|
13
|
@Timers = grep { !$_->{watcher} || $_->{watcher} ne $watcher } @Timers; |
|
6
|
|
|
|
|
96
|
|
131
|
6
|
|
|
|
|
15
|
push @Timers_ns, $timer; |
132
|
|
|
|
|
|
|
} |
133
|
13
|
|
|
|
|
45
|
return; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _mock_core_global { |
137
|
8
|
|
|
8
|
|
70
|
$Module{'CORE::GLOBAL'} = Test::MockModule->new('CORE::GLOBAL', no_auto=>1); |
138
|
|
|
|
|
|
|
$Module{'CORE::GLOBAL'}->mock(time => sub () { |
139
|
46
|
|
|
46
|
|
709
|
return int($Absolute + $Relative); |
140
|
8
|
|
|
|
|
385
|
}); |
141
|
|
|
|
|
|
|
$Module{'CORE::GLOBAL'}->mock(localtime => sub (;$) { |
142
|
12
|
50
|
|
12
|
|
2589579
|
my $time = defined $_[0] ? $_[0] : int($Absolute + $Relative); |
143
|
12
|
|
|
|
|
475
|
return CORE::localtime($time); |
144
|
8
|
|
|
|
|
1063
|
}); |
145
|
|
|
|
|
|
|
$Module{'CORE::GLOBAL'}->mock(gmtime => sub (;$) { |
146
|
13
|
100
|
|
13
|
|
853
|
my $time = defined $_[0] ? $_[0] : int($Absolute + $Relative); |
147
|
13
|
|
|
|
|
112
|
return CORE::gmtime($time); |
148
|
8
|
|
|
|
|
699
|
}); |
149
|
|
|
|
|
|
|
$Module{'CORE::GLOBAL'}->mock(sleep => sub ($) { |
150
|
16
|
|
|
16
|
|
173
|
my $dur = int $_[0]; |
151
|
16
|
100
|
|
|
|
65
|
croak 'sleep with negative value is not supported' if $dur < 0; |
152
|
14
|
|
|
|
|
28
|
$Relative += $dur; |
153
|
14
|
|
|
|
|
66
|
$Relative = sprintf '%.6f', $Relative; |
154
|
14
|
|
|
|
|
41
|
return $dur; |
155
|
8
|
|
|
|
|
649
|
}); |
156
|
8
|
|
|
|
|
606
|
return; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub _mock_time_hires { |
160
|
|
|
|
|
|
|
# Do not improve precision of current actual time to simplify tests. |
161
|
|
|
|
|
|
|
#$Absolute = Time::HiRes::time(); |
162
|
|
|
|
|
|
|
# Use current actual monotonic time. |
163
|
8
|
|
|
8
|
|
111
|
$Monotonic = Time::HiRes::clock_gettime(CLOCK_MONOTONIC()); |
164
|
|
|
|
|
|
|
|
165
|
8
|
|
|
|
|
356
|
$Module{'Time::HiRes'} = Test::MockModule->new('Time::HiRes'); |
166
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(time => sub () { |
167
|
8
|
|
|
8
|
|
1102586
|
return 0+sprintf '%.6f', $Absolute + $Relative; |
168
|
8
|
|
|
|
|
296
|
}); |
169
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(gettimeofday => sub () { |
170
|
4
|
|
|
4
|
|
455
|
my $t = sprintf '%.6f', $Absolute + $Relative; |
171
|
4
|
100
|
|
|
|
31
|
return wantarray ? (map {0+$_} split qr/[.]/ms, $t) : 0+$t; |
|
4
|
|
|
|
|
21
|
|
172
|
8
|
|
|
|
|
768
|
}); |
173
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(clock_gettime => sub (;$) { |
174
|
51
|
|
|
51
|
|
1008959
|
my ($which) = @_; |
175
|
51
|
100
|
|
|
|
158
|
if ($which == CLOCK_REALTIME()) { |
|
|
100
|
|
|
|
|
|
176
|
1
|
|
|
|
|
18
|
return 0+sprintf '%.6f', $Absolute + $Relative; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
elsif ($which == CLOCK_MONOTONIC()) { |
179
|
49
|
|
|
|
|
2158
|
return 0+sprintf '%.6f', $Monotonic + $Relative; |
180
|
|
|
|
|
|
|
} |
181
|
1
|
|
|
|
|
9
|
return TIME_HIRES_CLOCK_NOT_SUPPORTED; |
182
|
8
|
|
|
|
|
713
|
}); |
183
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(clock_getres => sub (;$) { |
184
|
3
|
|
|
3
|
|
1376
|
my ($which) = @_; |
185
|
3
|
100
|
100
|
|
|
9
|
if ($which == CLOCK_REALTIME() || $which == CLOCK_MONOTONIC()) { |
186
|
2
|
|
|
|
|
25
|
return $Module{'Time::HiRes'}->original('clock_getres')->(@_); |
187
|
|
|
|
|
|
|
} |
188
|
1
|
|
|
|
|
9
|
return TIME_HIRES_CLOCK_NOT_SUPPORTED; |
189
|
8
|
|
|
|
|
660
|
}); |
190
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(sleep => sub (;@) { |
191
|
3
|
|
|
3
|
|
125
|
my ($seconds) = @_; |
192
|
3
|
100
|
|
|
|
16
|
croak 'sleep without arg is not supported' if !@_; |
193
|
2
|
100
|
|
|
|
27
|
croak "Time::HiRes::sleep($seconds): negative time not invented yet" if $seconds < 0; |
194
|
1
|
|
|
|
|
1
|
$Relative += $seconds; |
195
|
1
|
|
|
|
|
7
|
$Relative = sprintf '%.6f', $Relative; |
196
|
1
|
|
|
|
|
3
|
return $seconds; |
197
|
8
|
|
|
|
|
667
|
}); |
198
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(usleep => sub ($) { |
199
|
10
|
|
|
10
|
|
114
|
my ($useconds) = @_; |
200
|
10
|
100
|
|
|
|
35
|
croak "Time::HiRes::usleep($useconds): negative time not invented yet" if $useconds < 0; |
201
|
9
|
|
|
|
|
17
|
$Relative += $useconds / MICROSECONDS; |
202
|
9
|
|
|
|
|
33
|
$Relative = sprintf '%.6f', $Relative; |
203
|
9
|
|
|
|
|
16
|
return $useconds; |
204
|
8
|
|
|
|
|
718
|
}); |
205
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(nanosleep => sub ($) { |
206
|
2
|
|
|
2
|
|
47
|
my ($nanoseconds) = @_; |
207
|
2
|
100
|
|
|
|
15
|
croak "Time::HiRes::nanosleep($nanoseconds): negative time not invented yet" if $nanoseconds < 0; |
208
|
1
|
|
|
|
|
3
|
$Relative += $nanoseconds / NANOSECONDS; |
209
|
1
|
|
|
|
|
7
|
$Relative = sprintf '%.6f', $Relative; |
210
|
1
|
|
|
|
|
3
|
return $nanoseconds; |
211
|
8
|
|
|
|
|
685
|
}); |
212
|
|
|
|
|
|
|
$Module{'Time::HiRes'}->mock(clock_nanosleep => sub ($$;$) { |
213
|
5
|
|
|
5
|
|
140
|
my ($which, $nanoseconds, $flags) = @_; |
214
|
5
|
100
|
|
|
|
20
|
croak "Time::HiRes::clock_nanosleep(..., $nanoseconds): negative time not invented yet" if $nanoseconds < 0; |
215
|
4
|
100
|
100
|
|
|
11
|
croak 'only CLOCK_REALTIME and CLOCK_MONOTONIC are supported' if $which != CLOCK_REALTIME() && $which != CLOCK_MONOTONIC(); |
216
|
3
|
100
|
|
|
|
24
|
croak 'only flags=0 is supported' if $flags; |
217
|
2
|
|
|
|
|
4
|
$Relative += $nanoseconds / NANOSECONDS; |
218
|
2
|
|
|
|
|
10
|
$Relative = sprintf '%.6f', $Relative; |
219
|
2
|
|
|
|
|
5
|
return $nanoseconds; |
220
|
8
|
|
|
|
|
636
|
}); |
221
|
8
|
|
|
|
|
660
|
return; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# TODO Distinguish timers set on different event loops / Mojo reactor |
225
|
|
|
|
|
|
|
# objects while one_tick? |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub _mock_ev { ## no critic (ProhibitExcessComplexity) |
228
|
8
|
|
|
8
|
|
65
|
$Module{'EV'} = Test::MockModule->new('EV'); |
229
|
8
|
|
|
|
|
288
|
$Module{'EV::Watcher'} = Test::MockModule->new('EV::Watcher', no_auto=>1); |
230
|
8
|
|
|
|
|
187
|
$Module{'EV::Timer'} = Test::MockModule->new('EV::Timer', no_auto=>1); |
231
|
8
|
|
|
|
|
164
|
$Module{'EV::Periodic'} = Test::MockModule->new('EV::Periodic', no_auto=>1); |
232
|
|
|
|
|
|
|
$Module{'EV'}->mock(time => sub () { |
233
|
7
|
|
|
7
|
|
83
|
return 0+sprintf '%.6f', $Absolute + $Relative; |
234
|
8
|
|
|
|
|
196
|
}); |
235
|
|
|
|
|
|
|
$Module{'EV'}->mock(now => sub () { |
236
|
21
|
|
|
21
|
|
459
|
return 0+sprintf '%.6f', $Absolute + $Relative; |
237
|
8
|
|
|
|
|
807
|
}); |
238
|
|
|
|
|
|
|
$Module{'EV'}->mock(sleep => sub ($) { |
239
|
4
|
|
|
4
|
|
10
|
my ($seconds) = @_; |
240
|
4
|
100
|
|
|
|
12
|
if ($seconds < 0) { |
241
|
1
|
|
|
|
|
3
|
$seconds = 0; |
242
|
|
|
|
|
|
|
} |
243
|
4
|
|
|
|
|
7
|
$Relative += $seconds; |
244
|
4
|
|
|
|
|
24
|
$Relative = sprintf '%.6f', $Relative; |
245
|
4
|
|
|
|
|
6
|
return; |
246
|
8
|
|
|
|
|
649
|
}); |
247
|
|
|
|
|
|
|
$Module{'EV'}->mock(run => sub (;$) { |
248
|
23
|
|
|
23
|
|
422
|
my ($flags) = @_; |
249
|
23
|
|
|
|
|
38
|
my $tick = 0; |
250
|
23
|
|
|
|
|
40
|
my $w; |
251
|
23
|
100
|
|
|
|
68
|
if (@Timers) { |
252
|
|
|
|
|
|
|
$w = $Module{'EV'}->original('timer')->( |
253
|
|
|
|
|
|
|
$WAIT_ONE_TICK, $WAIT_ONE_TICK, sub { |
254
|
23
|
|
|
23
|
|
1088168
|
my $me = shift; |
255
|
23
|
|
|
|
|
85
|
my $k; |
256
|
23
|
100
|
66
|
|
|
194
|
if (!$tick++ || !$flags) { |
257
|
15
|
|
|
|
|
160
|
$k = $me->keepalive(0); |
258
|
15
|
|
|
|
|
65
|
ff(); |
259
|
|
|
|
|
|
|
} |
260
|
23
|
100
|
33
|
|
|
251
|
if (!@Timers) { |
|
|
100
|
66
|
|
|
|
|
261
|
7
|
|
|
|
|
35
|
$me->stop; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
elsif ($k && ($flags || any {$_->{watcher} && $_->{watcher}->keepalive} @Timers)) { |
264
|
8
|
|
|
|
|
45
|
$me->keepalive(1); |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
} |
267
|
15
|
|
|
|
|
142
|
); |
268
|
15
|
50
|
66
|
2
|
|
200
|
if (!($flags || any {$_->{watcher} && $_->{watcher}->keepalive} @Timers)) { |
|
2
|
50
|
|
|
|
35
|
|
269
|
0
|
|
|
|
|
0
|
$w->keepalive(0); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
# $tick above and this second RUN_ONCE is work around bug in EV-4.10+ |
273
|
|
|
|
|
|
|
# http://lists.schmorp.de/pipermail/libev/2016q1/002656.html |
274
|
|
|
|
|
|
|
# FIXME I believe this workaround isn't correct with EV-4.03 - calling |
275
|
|
|
|
|
|
|
# RUN_ONCE twice must have side effect in processing two events |
276
|
|
|
|
|
|
|
# (at least one of them must be a non-timer event) instead of one. |
277
|
|
|
|
|
|
|
# To make it correct we probably need to mock all watcher types |
278
|
|
|
|
|
|
|
# to intercept invoking their callbacks and thus make it possible |
279
|
|
|
|
|
|
|
# to find out is first RUN_ONCE has actually called any callbacks. |
280
|
23
|
100
|
66
|
|
|
124
|
if ($flags && $flags == EV::RUN_ONCE()) { |
281
|
18
|
|
|
|
|
60
|
$Module{'EV'}->original('run')->(@_); |
282
|
|
|
|
|
|
|
} |
283
|
23
|
|
|
|
|
210
|
return $Module{'EV'}->original('run')->(@_); |
284
|
8
|
|
|
|
|
621
|
}); |
285
|
|
|
|
|
|
|
$Module{'EV'}->mock(timer => sub ($$$) { |
286
|
11
|
|
|
11
|
|
168
|
my ($after, $repeat, $cb) = @_; |
287
|
11
|
|
|
|
|
55
|
my $w = $Module{'EV'}->original('timer_ns')->(@_); |
288
|
11
|
|
|
|
|
163
|
weaken(my $weakw = $w); |
289
|
11
|
50
|
|
13
|
|
60
|
_add_timer('EV', $after, $repeat, sub { $weakw && $weakw->invoke(EV::TIMER()) }, $w); |
|
13
|
|
|
|
|
172
|
|
290
|
11
|
|
|
|
|
43
|
return $w; |
291
|
8
|
|
|
|
|
615
|
}); |
292
|
|
|
|
|
|
|
$Module{'EV'}->mock(timer_ns => sub ($$$) { |
293
|
1
|
|
|
1
|
|
4
|
my ($after, $repeat, $cb) = @_; |
294
|
1
|
|
|
|
|
4
|
my $w = EV::timer($after, $repeat, $cb); |
295
|
1
|
|
|
|
|
4
|
_stop_timer($w); |
296
|
1
|
|
|
|
|
3
|
return $w; |
297
|
8
|
|
|
|
|
607
|
}); |
298
|
|
|
|
|
|
|
$Module{'EV'}->mock(periodic => sub ($$$$) { |
299
|
2
|
|
|
2
|
|
9
|
my ($at, $repeat, $reschedule_cb, $cb) = @_; |
300
|
2
|
50
|
|
|
|
7
|
croak 'reschedule_cb is not supported yet' if $reschedule_cb; |
301
|
2
|
50
|
|
|
|
15
|
$at = sprintf '%.6f', $at < 0 ? 0 : $at; |
302
|
2
|
50
|
|
|
|
12
|
$repeat = sprintf '%.6f', $repeat < 0 ? 0 : $repeat; |
303
|
2
|
|
|
|
|
10
|
my $now = sprintf '%.6f', $Absolute + $Relative; |
304
|
2
|
100
|
66
|
|
|
15
|
if ($repeat > 0 && $at < $now) { |
305
|
8
|
|
|
8
|
|
22743
|
use bignum; |
|
8
|
|
|
|
|
52989
|
|
|
8
|
|
|
|
|
42
|
|
306
|
1
|
|
|
|
|
63
|
$at += $repeat * int(($now - $at) / $repeat + 1); |
307
|
1
|
|
|
|
|
2693
|
$at = sprintf '%.6f', $at; |
308
|
|
|
|
|
|
|
} |
309
|
2
|
50
|
|
|
|
113
|
my $after = $at > $now ? $at - $now : 0; |
310
|
2
|
|
|
|
|
10
|
$after = sprintf '%.6f', $after; |
311
|
2
|
|
|
|
|
10
|
my $w = $Module{'EV'}->original('periodic_ns')->(@_); |
312
|
2
|
|
|
|
|
31
|
weaken(my $weakw = $w); |
313
|
2
|
50
|
|
2
|
|
15
|
_add_timer('EV', $after, $repeat, sub { $weakw && $weakw->invoke(EV::TIMER()) }, $w); |
|
2
|
|
|
|
|
28
|
|
314
|
2
|
|
|
|
|
5
|
return $w; |
315
|
8
|
|
|
|
|
664
|
}); |
316
|
|
|
|
|
|
|
$Module{'EV'}->mock(periodic_ns => sub ($$$$) { |
317
|
0
|
|
|
0
|
|
0
|
my ($at, $repeat, $reschedule_cb, $cb) = @_; |
318
|
0
|
|
|
|
|
0
|
my $w = EV::periodic($at, $repeat, $reschedule_cb, $cb); |
319
|
0
|
|
|
|
|
0
|
_stop_timer($w); |
320
|
0
|
|
|
|
|
0
|
return $w; |
321
|
8
|
|
|
|
|
680
|
}); |
322
|
|
|
|
|
|
|
$Module{'EV::Watcher'}->mock(is_active => sub { |
323
|
2
|
|
|
2
|
|
6
|
my ($w) = @_; |
324
|
2
|
50
|
|
|
|
5
|
my ($active) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers; |
|
2
|
|
|
|
|
17
|
|
325
|
2
|
50
|
|
|
|
3
|
my ($inactive) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers_ns; |
|
2
|
|
|
|
|
14
|
|
326
|
2
|
100
|
|
|
|
8
|
if ($active) { |
|
|
50
|
|
|
|
|
|
327
|
1
|
|
|
|
|
6
|
return 1; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
elsif ($inactive) { |
330
|
1
|
|
|
|
|
5
|
return; |
331
|
|
|
|
|
|
|
} |
332
|
0
|
|
|
|
|
0
|
return $Module{'EV::Watcher'}->original('is_active')->(@_); |
333
|
8
|
|
|
|
|
652
|
}); |
334
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(DESTROY => sub { |
335
|
26
|
|
|
26
|
|
440
|
my ($w) = @_; |
336
|
26
|
50
|
|
|
|
58
|
@Timers = grep { !$_->{watcher} || $_->{watcher} ne $w } @Timers; |
|
18
|
|
|
|
|
264
|
|
337
|
26
|
50
|
|
|
|
57
|
@Timers_ns = grep { !$_->{watcher} || $_->{watcher} ne $w } @Timers_ns; |
|
11
|
|
|
|
|
87
|
|
338
|
26
|
|
|
|
|
150
|
return $Module{'EV::Timer'}->original('DESTROY')->(@_); |
339
|
8
|
|
|
|
|
672
|
}); |
340
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(start => sub { |
341
|
1
|
|
|
1
|
|
4
|
return _start_timer(@_); |
342
|
8
|
|
|
|
|
643
|
}); |
343
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(stop => sub { |
344
|
9
|
|
|
9
|
|
35
|
return _stop_timer(@_); |
345
|
8
|
|
|
|
|
615
|
}); |
346
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(set => sub { |
347
|
0
|
|
|
0
|
|
0
|
my ($w, $after, $repeat) = @_; |
348
|
0
|
0
|
|
|
|
0
|
if (!defined $repeat) { |
349
|
0
|
|
|
|
|
0
|
$repeat = 0; |
350
|
|
|
|
|
|
|
} |
351
|
0
|
0
|
|
|
|
0
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers, @Timers_ns; |
|
0
|
|
|
|
|
0
|
|
352
|
0
|
0
|
|
|
|
0
|
if ($timer) { |
353
|
0
|
|
|
|
|
0
|
$timer->{start} = $Relative; |
354
|
0
|
0
|
|
|
|
0
|
$timer->{after} = sprintf '%.6f', $after < 0 ? 0 : $after; |
355
|
0
|
0
|
|
|
|
0
|
$timer->{repeat}= sprintf '%.6f', $repeat < 0 ? 0 : $repeat; |
356
|
|
|
|
|
|
|
} |
357
|
0
|
|
|
|
|
0
|
return; |
358
|
8
|
|
|
|
|
600
|
}); |
359
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(remaining => sub { |
360
|
0
|
|
|
0
|
|
0
|
my ($w) = @_; |
361
|
0
|
0
|
|
|
|
0
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers, @Timers_ns; |
|
0
|
|
|
|
|
0
|
|
362
|
0
|
0
|
|
|
|
0
|
if ($timer) { |
363
|
0
|
|
|
|
|
0
|
return 0+sprintf '%.6f', $timer->{start} + $timer->{after} - $Relative; |
364
|
|
|
|
|
|
|
} |
365
|
0
|
|
|
|
|
0
|
return; |
366
|
8
|
|
|
|
|
614
|
}); |
367
|
|
|
|
|
|
|
$Module{'EV::Timer'}->mock(again => sub { |
368
|
3
|
|
|
3
|
|
45
|
my ($w, $repeat) = @_; |
369
|
3
|
50
|
33
|
|
|
18
|
if (defined $repeat && $repeat < 0) { |
370
|
0
|
|
|
|
|
0
|
$repeat = 0; |
371
|
|
|
|
|
|
|
} |
372
|
3
|
50
|
|
|
|
27
|
my ($active) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers; |
|
2
|
|
|
|
|
18
|
|
373
|
3
|
50
|
|
|
|
8
|
my ($inactive) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers_ns; |
|
2
|
|
|
|
|
12
|
|
374
|
3
|
100
|
|
|
|
9
|
if ($active) { |
|
|
50
|
|
|
|
|
|
375
|
2
|
50
|
|
|
|
22
|
$active->{repeat} = sprintf '%.6f', defined $repeat ? $repeat : $active->{repeat}; |
376
|
2
|
50
|
|
|
|
9
|
if ($active->{repeat} > 0) { |
377
|
2
|
|
|
|
|
5
|
$active->{after} = $active->{repeat}; |
378
|
2
|
|
|
|
|
5
|
$active->{start} = $Relative; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
else { |
381
|
0
|
|
|
|
|
0
|
_stop_timer($active->{watcher}); |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
elsif ($inactive) { |
385
|
1
|
50
|
|
|
|
12
|
$inactive->{repeat} = sprintf '%.6f', defined $repeat ? $repeat : $inactive->{repeat}; |
386
|
1
|
50
|
|
|
|
6
|
if ($inactive->{repeat} > 0) { |
387
|
1
|
|
|
|
|
3
|
$inactive->{after} = $inactive->{repeat}; |
388
|
1
|
|
|
|
|
3
|
$inactive->{start} = $Relative; |
389
|
1
|
|
|
|
|
4
|
_start_timer($inactive->{watcher}); |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
} |
392
|
3
|
|
|
|
|
8
|
return; |
393
|
8
|
|
|
|
|
652
|
}); |
394
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(DESTROY => sub { |
395
|
2
|
|
|
2
|
|
755
|
my ($w) = @_; |
396
|
2
|
50
|
|
|
|
5
|
@Timers = grep { !$_->{watcher} || $_->{watcher} ne $w } @Timers; |
|
1
|
|
|
|
|
16
|
|
397
|
2
|
50
|
|
|
|
5
|
@Timers_ns = grep { !$_->{watcher} || $_->{watcher} ne $w } @Timers_ns; |
|
2
|
|
|
|
|
16
|
|
398
|
2
|
|
|
|
|
7
|
return $Module{'EV::Periodic'}->original('DESTROY')->(@_); |
399
|
8
|
|
|
|
|
749
|
}); |
400
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(start => sub { |
401
|
0
|
|
|
0
|
|
0
|
return _start_timer(@_); |
402
|
8
|
|
|
|
|
754
|
}); |
403
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(stop => sub { |
404
|
0
|
|
|
0
|
|
0
|
return _stop_timer(@_); |
405
|
8
|
|
|
|
|
674
|
}); |
406
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(set => sub { |
407
|
0
|
|
|
0
|
|
0
|
my ($w, $at, $repeat, $reschedule_cb, $cb) = @_; |
408
|
0
|
0
|
|
|
|
0
|
croak 'reschedule_cb is not supported yet' if $reschedule_cb; |
409
|
0
|
0
|
|
|
|
0
|
$at = sprintf '%.6f', $at < 0 ? 0 : $at; |
410
|
0
|
0
|
|
|
|
0
|
$repeat = sprintf '%.6f', $repeat < 0 ? 0 : $repeat; |
411
|
0
|
|
|
|
|
0
|
my $now = sprintf '%.6f', $Absolute + $Relative; |
412
|
0
|
0
|
0
|
|
|
0
|
if ($repeat > 0 && $at < $now) { |
413
|
8
|
|
|
8
|
|
558102
|
use bigint; |
|
8
|
|
|
|
|
19
|
|
|
8
|
|
|
|
|
67
|
|
414
|
0
|
|
|
|
|
0
|
$at += $repeat * int(($now - $at) / $repeat + 1); |
415
|
0
|
|
|
|
|
0
|
$at = sprintf '%.6f', $at; |
416
|
|
|
|
|
|
|
} |
417
|
0
|
0
|
|
|
|
0
|
my $after = $at > $now ? $at - $now : 0; |
418
|
0
|
|
|
|
|
0
|
$after = sprintf '%.6f', $after; |
419
|
0
|
0
|
|
|
|
0
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers, @Timers_ns; |
|
0
|
|
|
|
|
0
|
|
420
|
0
|
0
|
|
|
|
0
|
if ($timer) { |
421
|
0
|
|
|
|
|
0
|
$timer->{start} = $Relative; |
422
|
0
|
|
|
|
|
0
|
$timer->{after} = $after; |
423
|
0
|
|
|
|
|
0
|
$timer->{repeat}= $repeat; |
424
|
|
|
|
|
|
|
} |
425
|
0
|
|
|
|
|
0
|
return; |
426
|
8
|
|
|
|
|
972
|
}); |
427
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(again => sub { |
428
|
0
|
|
|
0
|
|
0
|
return _start_timer(@_); |
429
|
8
|
|
|
|
|
700
|
}); |
430
|
|
|
|
|
|
|
$Module{'EV::Periodic'}->mock(at => sub { |
431
|
0
|
|
|
0
|
|
0
|
my ($w) = @_; |
432
|
0
|
0
|
|
|
|
0
|
my ($timer) = grep { $_->{watcher} && $_->{watcher} eq $w } @Timers, @Timers_ns; |
|
0
|
|
|
|
|
0
|
|
433
|
0
|
0
|
|
|
|
0
|
if ($timer) { |
434
|
0
|
|
|
|
|
0
|
return 0+sprintf '%.6f', $timer->{start} + $timer->{after}; |
435
|
|
|
|
|
|
|
} |
436
|
0
|
|
|
|
|
0
|
return; |
437
|
8
|
|
|
|
|
668
|
}); |
438
|
8
|
|
|
|
|
621
|
return; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub _mock_mojolicious { |
442
|
8
|
|
|
8
|
|
87
|
$Module{'Mojo::Reactor::Poll'} = Test::MockModule->new('Mojo::Reactor::Poll'); |
443
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(one_tick => sub { |
444
|
10
|
|
|
10
|
|
222
|
my ($self) = @_; |
445
|
10
|
100
|
|
|
|
24
|
if (!@Timers) { |
446
|
2
|
|
|
|
|
9
|
return $Module{'Mojo::Reactor::Poll'}->original('one_tick')->(@_); |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
my $id = $Module{'Mojo::Reactor::Poll'}->original('timer')->( |
449
|
8
|
|
|
8
|
|
71
|
$self, $WAIT_ONE_TICK, sub { ff() } |
450
|
8
|
|
|
|
|
43
|
); |
451
|
8
|
|
|
|
|
38
|
$Module{'Mojo::Reactor::Poll'}->original('one_tick')->(@_); |
452
|
8
|
|
|
|
|
63
|
$Module{'Mojo::Reactor::Poll'}->original('remove')->($self, $id); |
453
|
8
|
|
|
|
|
80
|
return; |
454
|
8
|
|
|
|
|
564
|
}); |
455
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(timer => sub { |
456
|
5
|
|
|
5
|
|
853
|
my ($self, $delay, $cb) = @_; |
457
|
5
|
50
|
|
|
|
11
|
if ($delay == 0) { # do not fake timer for 0 seconds to avoid hang |
458
|
0
|
|
|
|
|
0
|
return $Module{'Mojo::Reactor::Poll'}->original('timer')->(@_); |
459
|
|
|
|
|
|
|
} |
460
|
5
|
|
|
4
|
|
22
|
return _add_timer($self, $delay, 0, sub { $cb->($self) }); |
|
4
|
|
|
|
|
10
|
|
461
|
8
|
|
|
|
|
1076
|
}); |
462
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(recurring => sub { |
463
|
2
|
|
|
2
|
|
39
|
my ($self, $delay, $cb) = @_; |
464
|
2
|
|
|
4
|
|
11
|
return _add_timer($self, $delay, $delay, sub { $cb->($self) }); |
|
4
|
|
|
|
|
8
|
|
465
|
8
|
|
|
|
|
686
|
}); |
466
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(again => sub { |
467
|
2
|
|
|
2
|
|
18
|
my ($self, $id) = @_; |
468
|
2
|
50
|
|
|
|
12
|
if ($id !~ /\Afake_\d+\z/ms) { |
469
|
0
|
|
|
|
|
0
|
$Module{'Mojo::Reactor::Poll'}->original('again')->(@_); |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
else { |
472
|
2
|
|
|
|
|
6
|
my ($timer) = grep { $_->{id} eq $id } @Timers; |
|
2
|
|
|
|
|
7
|
|
473
|
2
|
50
|
|
|
|
6
|
if ($timer) { |
474
|
2
|
|
|
|
|
5
|
$timer->{start} = $Relative; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
} |
477
|
2
|
|
|
|
|
4
|
return; |
478
|
8
|
|
|
|
|
667
|
}); |
479
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(remove => sub { |
480
|
12
|
|
|
12
|
|
191
|
my ($self, $id) = @_; |
481
|
12
|
100
|
|
|
|
41
|
if ($id !~ /\Afake_\d+\z/ms) { |
482
|
10
|
|
|
|
|
24
|
$Module{'Mojo::Reactor::Poll'}->original('remove')->(@_); |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
else { |
485
|
2
|
50
|
|
|
|
3
|
@Timers = grep { $_->{loop} ne $self || $_->{id} ne $id } @Timers; |
|
2
|
|
|
|
|
24
|
|
486
|
|
|
|
|
|
|
} |
487
|
12
|
|
|
|
|
120
|
return; |
488
|
8
|
|
|
|
|
641
|
}); |
489
|
|
|
|
|
|
|
$Module{'Mojo::Reactor::Poll'}->mock(reset => sub { |
490
|
2
|
|
|
2
|
|
118
|
my ($self) = @_; |
491
|
2
|
|
|
|
|
8
|
@Timers = grep { $_->{loop} ne $self } @Timers; |
|
2
|
|
|
|
|
14
|
|
492
|
2
|
|
|
|
|
18
|
return $Module{'Mojo::Reactor::Poll'}->original('reset')->(@_); |
493
|
8
|
|
|
|
|
708
|
}); |
494
|
8
|
|
|
|
|
597
|
return; |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
1; |
499
|
|
|
|
|
|
|
__END__ |