system_timer 1.0 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ unit_tests do
4
+
5
+ test "trigger_time returns the time given in the constructor" do
6
+ timer = SystemTimer::ThreadTimer.new(:a_tigger_time, nil)
7
+ assert_equal :a_tigger_time, timer.trigger_time
8
+ end
9
+
10
+ test "thread returns the thread given in the constructor" do
11
+ timer = SystemTimer::ThreadTimer.new(nil, :a_thread)
12
+ assert_equal :a_thread, timer.thread
13
+ end
14
+
15
+ test "to_s retruns a human friendly description of the timer" do
16
+ assert_match /<ThreadTimer :time => 24, :thread => #<Thread(.*)>, :exception_class => Timeout::Error>/,
17
+ SystemTimer::ThreadTimer.new(24, Thread.current).to_s
18
+ end
19
+
20
+ end
@@ -0,0 +1,282 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ functional_tests do
4
+
5
+ DEFAULT_ERROR_MARGIN = 2
6
+
7
+ test "original_ruby_sigalrm_handler is nil after reset" do
8
+ SystemTimer.send(:install_ruby_sigalrm_handler)
9
+ SystemTimer.send(:reset_original_ruby_sigalrm_handler)
10
+ assert_nil SystemTimer.send(:original_ruby_sigalrm_handler)
11
+ end
12
+
13
+ test "original_ruby_sigalrm_handler is set to existing handler after " +
14
+ "install_ruby_sigalrm_handler when save_previous_handler is true" do
15
+ SystemTimer.expects(:trap).with('SIGALRM').returns(:an_existing_handler)
16
+ SystemTimer.send(:install_ruby_sigalrm_handler)
17
+ assert_equal :an_existing_handler, SystemTimer.send(:original_ruby_sigalrm_handler)
18
+ end
19
+
20
+ test "restore_original_ruby_sigalrm_handler traps sigalrm using original_ruby_sigalrm_handler" do
21
+ SystemTimer.stubs(:original_ruby_sigalrm_handler).returns(:the_original_handler)
22
+ SystemTimer.expects(:trap).with('SIGALRM', :the_original_handler)
23
+ SystemTimer.send :restore_original_ruby_sigalrm_handler
24
+ end
25
+
26
+ test "restore_original_ruby_sigalrm_handler resets original_ruby_sigalrm_handler" do
27
+ SystemTimer.stubs(:trap)
28
+ SystemTimer.expects(:reset_original_ruby_sigalrm_handler)
29
+ SystemTimer.send :restore_original_ruby_sigalrm_handler
30
+ end
31
+
32
+ test "restore_original_ruby_sigalrm_handler reset SIGALRM handler to default when original_ruby_sigalrm_handler is nil" do
33
+ SystemTimer.stubs(:original_ruby_sigalrm_handler)
34
+ SystemTimer.expects(:trap).with('SIGALRM', 'DEFAULT')
35
+ SystemTimer.stubs(:reset_original_ruby_sigalrm_handler)
36
+ SystemTimer.send :restore_original_ruby_sigalrm_handler
37
+ end
38
+
39
+ test "restore_original_ruby_sigalrm_handler resets original_ruby_sigalrm_handler when trap raises" do
40
+ SystemTimer.stubs(:trap).returns(:the_original_handler)
41
+ SystemTimer.send(:install_ruby_sigalrm_handler)
42
+ SystemTimer.expects(:trap).raises("next time maybe...")
43
+ SystemTimer.expects(:reset_original_ruby_sigalrm_handler)
44
+
45
+ SystemTimer.send(:restore_original_ruby_sigalrm_handler) rescue nil
46
+ end
47
+
48
+ test "timeout_after raises TimeoutError if block takes too long" do
49
+ assert_raises(Timeout::Error) do
50
+ SystemTimer.timeout_after(1) {sleep 5}
51
+ end
52
+ end
53
+
54
+ test "timeout_after timeout can be a fraction of a second" do
55
+ assert_raises(Timeout::Error) do
56
+ SystemTimer.timeout_after(0.2) {sleep 3}
57
+ end
58
+ end
59
+
60
+
61
+ test "timeout_after raises a custom timeout when block takes too long and a custom exception class is provided" do
62
+ ACustomException = Class.new(Exception)
63
+ assert_raises(ACustomException) do
64
+ SystemTimer.timeout_after(1, ACustomException) {sleep 5}
65
+ end
66
+ end
67
+
68
+ test "timeout_after does not raises Timeout Error if block completes in time" do
69
+ SystemTimer.timeout_after(5) {sleep 1}
70
+ end
71
+
72
+ test "timeout_after returns the value returned by the black" do
73
+ assert_equal :block_value, SystemTimer.timeout_after(1) {:block_value}
74
+ end
75
+
76
+ test "timeout_after raises TimeoutError in thread that called timeout_after" do
77
+ raised_thread = nil
78
+ other_thread = Thread.new do
79
+ begin
80
+ SystemTimer.timeout_after(1) {sleep 5}
81
+ flunk "Should have timed out"
82
+ rescue Timeout::Error
83
+ raised_thread = Thread.current
84
+ end
85
+ end
86
+
87
+ other_thread.join
88
+ assert_equal other_thread, raised_thread
89
+ end
90
+
91
+ test "cancelling a timer that was installed restores previous ruby handler for SIG_ALRM" do
92
+ begin
93
+ fake_original_ruby_handler = proc {}
94
+ initial_ruby_handler = trap "SIGALRM", fake_original_ruby_handler
95
+ SystemTimer.install_first_timer_and_save_original_configuration 3
96
+ SystemTimer.restore_original_configuration
97
+ assert_equal fake_original_ruby_handler, trap("SIGALRM", "IGNORE")
98
+ ensure # avoid interfering with test infrastructure
99
+ trap("SIGALRM", initial_ruby_handler) if initial_ruby_handler
100
+ end
101
+ end
102
+
103
+ test "debug_enabled returns true after enabling debug" do
104
+ begin
105
+ SystemTimer.disable_debug
106
+ SystemTimer.enable_debug
107
+ assert_equal true, SystemTimer.debug_enabled?
108
+ ensure
109
+ SystemTimer.disable_debug
110
+ end
111
+ end
112
+
113
+ test "debug_enabled returns false after disable debug" do
114
+ begin
115
+ SystemTimer.enable_debug
116
+ SystemTimer.disable_debug
117
+ assert_equal false, SystemTimer.debug_enabled?
118
+ ensure
119
+ SystemTimer.disable_debug
120
+ end
121
+ end
122
+
123
+ test "timeout offers an API fully compatible with timeout.rb" do
124
+ assert_raises(Timeout::Error) do
125
+ SystemTimer.timeout(1) {sleep 5}
126
+ end
127
+ end
128
+
129
+ # Disable this test as it is failing on Ubuntu. The problem is that
130
+ # for some reason M.R.I 1.8 is trapping the Ruby signals at the
131
+ # time the system SIGALRM is delivered, hence we do not timeout as
132
+ # quickly as we should. Needs further investigation. At least the
133
+ # SIGALRM ensures that the system will schedule M.R.I. native thread.
134
+ #
135
+ #
136
+ # test "while exact timeouts cannot be guaranted the timeout should not exceed the provided timeout by 2 seconds" do
137
+ # start = Time.now
138
+ # begin
139
+ # SystemTimer.timeout_after(2) do
140
+ # open "http://www.invalid.domain.comz"
141
+ # end
142
+ # raise "should never get there"
143
+ # rescue SocketError => e
144
+ # rescue Timeout::Error => e
145
+ # end
146
+ # elapsed = Time.now - start
147
+ # assert elapsed < 4, "Got #{elapsed} s, expected 2, at most 4"
148
+ # end
149
+
150
+
151
+ test "timeout are enforced on system calls" do
152
+ assert_timeout_within(3) do
153
+ SystemTimer.timeout(3) do
154
+ sleep 30
155
+ end
156
+ end
157
+ end
158
+
159
+ test "timeout work when spawning a different thread" do
160
+ assert_timeout_within(3) do
161
+ thread = Thread.new do
162
+ SystemTimer.timeout(3) do
163
+ sleep 60
164
+ end
165
+ end
166
+ thread.join
167
+ end
168
+ end
169
+
170
+ test "can set multiple serial timers" do
171
+ 10.times do |i|
172
+ print(i) & STDOUT.flush
173
+ assert_timeout_within(1) do
174
+ SystemTimer.timeout(1) do
175
+ sleep 60
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ test "can set multiple serial timers with fractional timeout" do
182
+ 10.times do |i|
183
+ print(i) & STDOUT.flush
184
+ assert_timeout_within(0.5) do
185
+ SystemTimer.timeout(0.5) do
186
+ sleep 60
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ test "timeout work when setting concurrent timers, the first one expiring before the second one" do
193
+ first_thread = Thread.new do
194
+ assert_timeout_within(3) do
195
+ SystemTimer.timeout(3) do
196
+ sleep 60
197
+ end
198
+ end
199
+ end
200
+ second_thread = Thread.new do
201
+ assert_timeout_within(5) do
202
+ SystemTimer.timeout(5) do
203
+ sleep 60
204
+ end
205
+ end
206
+ end
207
+ first_thread.join
208
+ second_thread.join
209
+ end
210
+
211
+ test "timeout work when setting concurrent timers, the second one expiring before the first one" do
212
+
213
+ first_thread = Thread.new do
214
+ assert_timeout_within(10) do
215
+ SystemTimer.timeout(10) do
216
+ sleep 60
217
+ end
218
+ end
219
+ end
220
+ second_thread = Thread.new do
221
+ assert_timeout_within(3) do
222
+ SystemTimer.timeout(3) do
223
+ sleep 60
224
+ end
225
+ end
226
+ end
227
+ first_thread.join
228
+ second_thread.join
229
+ end
230
+
231
+ test "timeout work when setting concurrent timers with the exact same timeout" do
232
+
233
+ first_thread = Thread.new do
234
+ assert_timeout_within(2) do
235
+ SystemTimer.timeout(2) do
236
+ sleep 60
237
+ end
238
+ end
239
+ end
240
+ second_thread = Thread.new do
241
+ assert_timeout_within(2) do
242
+ SystemTimer.timeout(2) do
243
+ sleep 60
244
+ end
245
+ end
246
+ end
247
+ first_thread.join
248
+ second_thread.join
249
+ end
250
+
251
+ test "timeout works with random concurrent timers dynamics" do
252
+ all_threads = []
253
+
254
+ 10.times do
255
+ a_timeout = [1, (rand(10)).to_f].max
256
+ all_threads << Thread.new do
257
+ assert_timeout_within(a_timeout, 10) do
258
+ SystemTimer.timeout(a_timeout) do
259
+ sleep 180
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ all_threads.each {|t| t.join}
266
+ end
267
+
268
+ def assert_timeout_within(expected_timeout_in_seconds,
269
+ error_margin = DEFAULT_ERROR_MARGIN,
270
+ &block)
271
+ start = Time.now
272
+ yield
273
+ flunk "Did not timeout as expected!"
274
+ rescue Timeout::Error
275
+ elapsed = Time.now - start
276
+ assert elapsed >= expected_timeout_in_seconds,
277
+ "Timed out too early, expected #{expected_timeout_in_seconds}, got #{elapsed} s"
278
+ assert elapsed < (expected_timeout_in_seconds + error_margin),
279
+ "Timed out after #{elapsed} seconds, expected #{expected_timeout_in_seconds}"
280
+ end
281
+
282
+ end
@@ -0,0 +1,110 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ unit_tests do
4
+
5
+ test "timeout_after registers a new timer in the timer pool" do
6
+ pool = stub_everything
7
+ Thread.stubs(:current).returns(:the_current_thread)
8
+ SystemTimer.stubs(:timer_pool).returns(pool)
9
+ SystemTimer.stubs(:install_next_timer)
10
+ SystemTimer.stubs(:restore_original_configuration)
11
+
12
+ pool.expects(:add_timer).with(5, nil).returns(stub_everything)
13
+ SystemTimer.timeout_after(5) {}
14
+ end
15
+
16
+ test "timeout_after registers a new timer with a custom timeout exception in the timer pool" do
17
+ MyCustomException = Class.new(Exception)
18
+ pool = stub_everything
19
+ Thread.stubs(:current).returns(:the_current_thread)
20
+ SystemTimer.stubs(:timer_pool).returns(pool)
21
+ SystemTimer.stubs(:install_next_timer)
22
+ SystemTimer.stubs(:restore_original_configuration)
23
+
24
+ pool.expects(:add_timer).with(5, MyCustomException).returns(stub_everything)
25
+ SystemTimer.timeout_after(5, MyCustomException) {}
26
+ end
27
+
28
+ test "timeout_after installs a system timer saving the previous " +
29
+ "configuration when there is only one timer" do
30
+
31
+ now = Time.now
32
+ Time.stubs(:now).returns(now)
33
+ SystemTimer.stubs(:restore_original_configuration)
34
+ SystemTimer.expects(:install_first_timer_and_save_original_configuration) \
35
+ .with {|value| value.between?(23.99, 24.01) }
36
+ SystemTimer.timeout_after(24) {}
37
+ end
38
+
39
+ test "timeout_after installs a system timer without saving the previous " +
40
+ "configuration when there is more than one timer" do
41
+
42
+ now = Time.now
43
+ Time.stubs(:now).returns(now)
44
+ SystemTimer.timer_pool.register_timer now.to_f + 100, :a_thread
45
+ SystemTimer.stubs(:restore_original_configuration)
46
+ SystemTimer.stubs(:install_next_timer)
47
+
48
+ SystemTimer.expects(:install_next_timer) \
49
+ .with {|value| value.between?(23.99, 24.01) }
50
+ SystemTimer.timeout_after(24) {}
51
+ end
52
+
53
+ test "timeout_after installs a system timer with the interval before " +
54
+ "the next timer to expire" do
55
+
56
+ now = Time.now
57
+ Time.stubs(:now).returns(now)
58
+ SystemTimer.timer_pool.register_timer now.to_f + 24, :a_thread
59
+ SystemTimer.stubs(:restore_original_configuration)
60
+ SystemTimer.stubs(:install_next_timer)
61
+
62
+ SystemTimer.expects(:install_next_timer) \
63
+ .with {|value| value.between?(23.99, 24.01) }
64
+ SystemTimer.timeout_after(100) {}
65
+ end
66
+
67
+ test "timeout_after cancels the timer when the block completes without " +
68
+ "timeout" do
69
+
70
+ now = Time.now
71
+ the_timer = stub_everything
72
+ Time.stubs(:now).returns(now)
73
+ SystemTimer.stubs(:restore_original_configuration)
74
+ SystemTimer.stubs(:install_first_timer_and_save_original_configuration)
75
+ SystemTimer.timer_pool.stubs(:add_timer).returns(the_timer)
76
+ SystemTimer.timer_pool.stubs(:first_timer?).returns(true)
77
+
78
+ SystemTimer.timer_pool.expects(:cancel).with(the_timer)
79
+ SystemTimer.timeout_after(24) {}
80
+ end
81
+
82
+ test "debug does not output to stdout when debug is disabled" do
83
+ SystemTimer.stubs(:debug_enabled?).returns(false)
84
+ original_stdout = $stdout
85
+ begin
86
+ stdout = StringIO.new
87
+ $stdout = stdout
88
+
89
+ SystemTimer.send :debug, "a log message"
90
+ assert stdout.string.empty?
91
+ ensure
92
+ $stdout = original_stdout
93
+ end
94
+ end
95
+
96
+ test "debug logs messaget to stdout when debug is enabled" do
97
+ SystemTimer.stubs(:debug_enabled?).returns(true)
98
+ original_stdout = $stdout
99
+ begin
100
+ stdout = StringIO.new
101
+ $stdout = stdout
102
+
103
+ SystemTimer.send :debug, "a log message"
104
+ assert_match /a log message/, stdout.string
105
+ ensure
106
+ $stdout = original_stdout
107
+ end
108
+ end
109
+
110
+ end
@@ -0,0 +1,10 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../lib'
2
+ $:.unshift File.dirname(__FILE__) + '/../ext/system_timer'
3
+ $: << File.dirname(__FILE__) + "/../vendor/gems/dust-0.1.6/lib"
4
+ $: << File.dirname(__FILE__) + "/../vendor/gems/mocha-0.9.1/lib"
5
+ require 'test/unit'
6
+ require 'dust'
7
+ require 'mocha'
8
+ require 'stringio'
9
+ require "open-uri"
10
+ require 'system_timer'
metadata CHANGED
@@ -1,15 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: system_timer
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.0"
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 4
10
+ version: 1.2.4
5
11
  platform: ruby
6
- authors: []
7
-
12
+ authors:
13
+ - Philippe Hanrigou
14
+ - David Vollbracht
8
15
  autorequire: system_timer
9
16
  bindir: bin
10
17
  cert_chain: []
11
18
 
12
- date: 2008-05-26 00:00:00 -07:00
19
+ date: 2011-06-11 00:00:00 -07:00
13
20
  default_executable:
14
21
  dependencies: []
15
22
 
@@ -27,40 +34,54 @@ files:
27
34
  - ChangeLog
28
35
  - ext/system_timer/system_timer_native.c
29
36
  - ext/system_timer/extconf.rb
37
+ - lib/system_timer/concurrent_timer_pool.rb
38
+ - lib/system_timer/thread_timer.rb
30
39
  - lib/system_timer.rb
31
40
  - lib/system_timer_stub.rb
32
41
  - test/all_tests.rb
33
- - test/system_timer_test.rb
42
+ - test/system_timer/concurrent_timer_pool_unit_test.rb
43
+ - test/system_timer/thread_timer_test.rb
44
+ - test/system_timer_functional_test.rb
45
+ - test/system_timer_unit_test.rb
46
+ - test/test_helper.rb
34
47
  - README
35
48
  has_rdoc: true
36
49
  homepage:
50
+ licenses: []
51
+
37
52
  post_install_message:
38
53
  rdoc_options:
39
54
  - --title
40
- - SystemTimer
55
+ - System Timer
41
56
  - --main
42
57
  - README
43
58
  - --line-numbers
44
59
  require_paths:
45
60
  - lib
46
61
  required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
47
63
  requirements:
48
64
  - - ">="
49
65
  - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
50
69
  version: "0"
51
- version:
52
70
  required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
53
72
  requirements:
54
73
  - - ">="
55
74
  - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
56
78
  version: "0"
57
- version:
58
79
  requirements: []
59
80
 
60
- rubyforge_project:
61
- rubygems_version: 1.0.1
81
+ rubyforge_project: systemtimer
82
+ rubygems_version: 1.3.7
62
83
  signing_key:
63
- specification_version: 2
84
+ specification_version: 3
64
85
  summary: Set a Timeout based on signals, which are more reliable than Timeout. Timeout is based on green threads.
65
86
  test_files:
66
87
  - test/all_tests.rb