File: group.rb

package info (click to toggle)
ruby-timers 4.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 216 kB
  • sloc: ruby: 973; makefile: 8
file content (252 lines) | stat: -rw-r--r-- 5,964 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2012-2017, by Tony Arcieri.
# Copyright, 2012, by Jesse Cooke.
# Copyright, 2012, by Dimitrij Denissenko.
# Copyright, 2013, by Chuck Remes.
# Copyright, 2013, by Ron Evans.
# Copyright, 2013, by Sean Gregory.
# Copyright, 2013-2014, by Utenmiki.
# Copyright, 2013, by Jeremy Hinegardner.
# Copyright, 2014, by Bruno Enten.
# Copyright, 2014-2025, by Samuel Williams.
# Copyright, 2017, by Vít Ondruch.

require "timers/group"
require "timer_quantum"

describe Timers::Group do
	let(:group) {subject.new}
	
	with "#wait" do
		it "calls the wait block with nil" do
			called = false
			
			group.wait do |interval|
				expect(interval).to be_nil
				called = true
			end
			
			expect(called).to be == true
		end
		
		it "calls the wait block with an interval" do
			called = false
			fired = false
			
			group.after(0.1) { fired = true }
			
			group.wait do |interval|
				expect(interval).to be_within(TIMER_QUANTUM).of(0.1)
				called = true
				sleep 0.2
			end
			
			expect(called).to be == true
			expect(fired).to be == true
		end
		
		it "repeatedly calls the wait block if it sleeps less than the interval" do
			called = 0
			fired = false
			
			group.after(0.1) { fired = true }
			
			group.wait do |interval|
				called += 1
				sleep(0.01)
			end
			
			expect(called).to be > 1
			expect(fired).to be == true
		end
	end
	
	it "sleeps until the next timer" do
		interval = 0.1
		
		fired = false
		group.after(interval) {fired = true}
		group.wait
		
		expect(fired).to be == true
	end
	
	it "fires instantly when next timer is in the past" do
		fired = false
		group.after(TIMER_QUANTUM) { fired = true }
		sleep(TIMER_QUANTUM * 2)
		group.wait
		
		expect(fired).to be == true
	end
	
	it "calculates the interval until the next timer should fire" do
		interval = 0.1
		
		group.after(interval)
		expect(group.wait_interval).to be_within(TIMER_QUANTUM).of interval
		
		sleep(interval)
		expect(group.wait_interval).to be <= 0
	end
	
	it "fires timers in the correct order" do
		result = []
		
		group.after(TIMER_QUANTUM * 2) { result << :two }
		group.after(TIMER_QUANTUM * 3) { result << :three }
		group.after(TIMER_QUANTUM * 1) { result << :one }
		
		sleep(TIMER_QUANTUM * 4)
		group.fire
		
		expect(result).to be == [:one, :two, :three]
	end
	
	it "raises TypeError if given an invalid time" do
		expect do
			group.after(nil) { nil }
		end.to raise_exception(TypeError)
	end
	
	with "#now_and_after" do
		it "fires the timer immediately" do
			result = []
			
			group.now_and_after(TIMER_QUANTUM * 2) { result << :foo }
			
			expect(result).to be == [:foo]
		end
		
		it "fires the timer at the correct time" do
			result = []
			
			group.now_and_after(TIMER_QUANTUM * 2) { result << :foo }
			
			group.wait
			
			expect(result).to be == [:foo, :foo]
		end
	end
	
	with "recurring timers" do
		it "continues to fire the timers at each interval" do
			result = []
			
			group.every(TIMER_QUANTUM * 2) { result << :foo }
			
			sleep TIMER_QUANTUM * 3
			group.fire
			expect(result).to be == [:foo]
			
			sleep TIMER_QUANTUM * 5
			group.fire
			expect(result).to be == [:foo, :foo]
		end
	end
	
	it "calculates the proper interval to wait until firing" do
		interval_ms = 25
		
		group.after(interval_ms / 1000.0)
		
		expect(group.wait_interval).to be_within(TIMER_QUANTUM).of(interval_ms / 1000.0)
	end
	
	with "delay timer" do
		it "adds appropriate amount of time to timer" do
			timer = group.after(10)
			timer.delay(5)
			expect(timer.offset - group.current_offset).to be_within(TIMER_QUANTUM).of(15)
		end
	end
	
	with "delay timer collection" do
		it "delay on set adds appropriate amount of time to all timers" do
			timer = group.after(10)
			timer2 = group.after(20)
			group.delay(5)
			expect(timer.offset - group.current_offset).to be_within(TIMER_QUANTUM).of(15)
			expect(timer2.offset - group.current_offset).to be_within(TIMER_QUANTUM).of(25)
		end
	end
	
	with "on delaying a timer" do
		it "fires timers in the correct order" do
			result = []
			
			group.after(TIMER_QUANTUM * 2) { result << :two }
			group.after(TIMER_QUANTUM * 3) { result << :three }
			first = group.after(TIMER_QUANTUM * 1) { result << :one }
			first.delay(TIMER_QUANTUM * 3)
			
			sleep TIMER_QUANTUM * 5
			group.fire
			
			expect(result).to be == [:two, :three, :one]
		end
	end
	
	with "#inspect" do
		it "before firing" do
			fired = false
			timer = group.after(TIMER_QUANTUM * 5) { fired = true }
			timer.pause
			expect(fired).not.to be == true
			expect(timer.inspect).to be =~ /\A#<Timers::Timer:0x[\da-f]+ fires in [-\.\de]+ seconds>\Z/
		end
		
		it "after firing" do
			fired = false
			timer = group.after(TIMER_QUANTUM) { fired = true }
			
			group.wait
			
			expect(fired).to be == true
			expect(timer.inspect).to be =~/\A#<Timers::Timer:0x[\da-f]+ fired [-\.\de]+ seconds ago>\Z/
		end
		
		it "recurring firing" do
			result = []
			timer = group.every(TIMER_QUANTUM) { result << :foo }
			
			group.wait
			expect(result).to be(:any?)
			regex = /\A#<Timers::Timer:0x[\da-f]+ fires in [-\.\de]+ seconds, recurs every #{TIMER_QUANTUM}>\Z/
			expect(timer.inspect).to be =~ regex
		end
	end
	
	with "#fires_in" do
		let(:interval) {0.01}
		
		with "recurring timer" do
			let(:timer) {group.every(interval){true}}

			it "calculates the interval until the next fire if it's recurring" do
				expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
			end
		end
		
		with "non-recurring timer" do
			let(:timer) {group.after(interval){true}}
			
			it "calculates the interval until the next fire if it hasn't already fired" do
				expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
			end
			
			it "calculates the interval since last fire if already fired" do
				# Create the timer:
				timer
				
				group.wait
				
				sleep(TIMER_QUANTUM)
				
				expect(timer.fires_in).to be < 0.0
			end
		end
	end
end