fsevent 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -70,7 +70,7 @@ class FSEvent::ProcessDevice < FSEvent::AbstractDevice
70
70
  msgtype, *rest = Marshal.load(@io)
71
71
  end
72
72
  if msgtype != :return_to_parent
73
- raise RuntimeError, "unexpected message type: #{msgtype.inspect}"
73
+ raise FSEvent::FSEventError, "unexpected message type: #{msgtype.inspect}"
74
74
  end
75
75
  rest[0]
76
76
  end
@@ -25,8 +25,8 @@ class FSEvent::ProcessDeviceC < FSEvent::AbstractDevice
25
25
  @obj.call_parent(:add_watch, watchee_device_name, status_name)
26
26
  end
27
27
 
28
- def status_changed(status_name, value)
29
- @obj.call_parent(:status_changed, status_name, value)
28
+ def modify_status(status_name, value)
29
+ @obj.call_parent(:modify_status, status_name, value)
30
30
  end
31
31
  end
32
32
 
@@ -55,7 +55,7 @@ class FSEvent::ProcessDeviceC < FSEvent::AbstractDevice
55
55
  msgtype, *rest = Marshal.load(STDIN)
56
56
  end
57
57
  if msgtype != :return_to_child
58
- raise RuntimeError, "unexpected message type: #{msgtype.inspect}"
58
+ raise FSEvent::FSEventError, "unexpected message type: #{msgtype.inspect}"
59
59
  end
60
60
  rest[0]
61
61
  end
@@ -69,7 +69,7 @@ class FSEvent::ProcessDeviceC < FSEvent::AbstractDevice
69
69
  exit true
70
70
  end
71
71
  if msgtype != :call_child
72
- raise RuntimeError, "unexpected message type: #{msgtype.inspect}"
72
+ raise FSEvent::FSEventError, "unexpected message type: #{msgtype.inspect}"
73
73
  end
74
74
  method, *args = rest
75
75
  ret = this_device.send(method, *args)
@@ -40,7 +40,7 @@ class FSEvent::SimpleDevice < FSEvent::AbstractDevice
40
40
  end
41
41
  end
42
42
 
43
- def run(watched_status_change)
44
- @run_block.call watched_status_change
43
+ def run(watched_status, changed_status)
44
+ @run_block.call watched_status, changed_status
45
45
  end
46
46
  end
@@ -48,16 +48,46 @@ module FSEvent::Util
48
48
  end
49
49
  end
50
50
 
51
+ def valid_device_name_for_read?(str)
52
+ /\A_?[a-z][a-z0-9_]*\z/ =~ str
53
+ end
54
+
55
+ def valid_device_name_pat_for_read?(str)
56
+ /\A_?(?:[a-z][a-z0-9_]*)?\*?\z/ =~ str
57
+ end
58
+
59
+ def valid_status_name_for_read?(str)
60
+ /\A_?[a-z][a-z0-9_]*\z/ =~ str
61
+ end
62
+
63
+ def valid_status_name_pat_for_read?(str)
64
+ /\A_?(?:[a-z][a-z0-9_]*)?\*?\z/ =~ str
65
+ end
66
+
67
+ def valid_device_name_for_write?(str)
68
+ /\A[a-z][a-z0-9_]*\z/ =~ str
69
+ end
70
+
71
+ def valid_status_name_for_write?(str)
72
+ /\A[a-z][a-z0-9_]*\z/ =~ str
73
+ end
74
+
75
+ def prefixpat_match(pat, str)
76
+ if /\*\z/ =~ pat
77
+ str.start_with?($`)
78
+ else
79
+ pat == str
80
+ end
81
+ end
82
+
51
83
  def reaction_immediate_at_beginning?(reaction)
52
84
  case reaction
53
85
  when :immediate
54
86
  true
55
- when :immediate_only_at_beginning
56
- true
57
87
  when :schedule
58
88
  false
59
89
  else
60
- raise "unexpected reaction: #{reaction.inspect}"
90
+ raise ArgumentError, "unexpected reaction: #{reaction.inspect}"
61
91
  end
62
92
  end
63
93
 
@@ -65,12 +95,10 @@ module FSEvent::Util
65
95
  case reaction
66
96
  when :immediate
67
97
  true
68
- when :immediate_only_at_beginning
69
- false
70
98
  when :schedule
71
99
  false
72
100
  else
73
- raise "unexpected reaction: #{reaction.inspect}"
101
+ raise ArgumentError, "unexpected reaction: #{reaction.inspect}"
74
102
  end
75
103
  end
76
104
 
@@ -0,0 +1,133 @@
1
+ # watchset.rb --- set of watches
2
+ #
3
+ # Copyright (C) 2014 National Institute of Advanced Industrial Science and Technology (AIST)
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class FSEvent::WatchSet
19
+ include FSEvent::Util
20
+
21
+ def initialize
22
+ # valid values of reaction: :immediate, :schedule
23
+ @watch_defs = nested_hash(3) # watcher_device_name -> watchee_device_name_pat -> status_name_pat -> reaction
24
+
25
+ @watch_exact_exact = nested_hash(3) # watchee_device_name_exact -> status_name_exact -> watcher_device_name -> reaction
26
+ @watch_exact_prefix = nested_hash(3) # watchee_device_name_exact -> status_name_prefix -> watcher_device_name -> reaction
27
+ @watch_prefix_exact = nested_hash(3) # watchee_device_name_prefix -> status_name_exact -> watcher_device_name -> reaction
28
+ @watch_prefix_prefix = nested_hash(3) # watchee_device_name_prefix -> status_name_prefix -> watcher_device_name -> reaction
29
+ end
30
+
31
+ def add(watchee_device_name_pat, status_name_pat, watcher_device_name, reaction)
32
+ @watch_defs[watcher_device_name][watchee_device_name_pat][status_name_pat] = reaction
33
+ if /\*\z/ =~ watchee_device_name_pat
34
+ watchee_device_name_prefix = $`
35
+ if /\*\z/ =~ status_name_pat
36
+ status_name_prefix = $`
37
+ @watch_prefix_prefix[watchee_device_name_prefix][status_name_prefix][watcher_device_name] = reaction
38
+ else
39
+ @watch_prefix_exact[watchee_device_name_prefix][status_name_pat][watcher_device_name] = reaction
40
+ end
41
+ else
42
+ if /\*\z/ =~ status_name_pat
43
+ status_name_prefix = $`
44
+ @watch_exact_prefix[watchee_device_name_pat][status_name_prefix][watcher_device_name] = reaction
45
+ else
46
+ @watch_exact_exact[watchee_device_name_pat][status_name_pat][watcher_device_name] = reaction
47
+ end
48
+ end
49
+ end
50
+
51
+ def del(watchee_device_name_pat, status_name_pat, watcher_device_name)
52
+ @watch_defs[watcher_device_name][watchee_device_name_pat].delete status_name_pat
53
+ if /\*\z/ =~ watchee_device_name_pat
54
+ watchee_device_name_prefix = $`
55
+ if /\*\z/ =~ status_name_pat
56
+ status_name_prefix = $`
57
+ @watch_prefix_prefix[watchee_device_name_prefix][status_name_prefix].delete watcher_device_name
58
+ else
59
+ @watch_prefix_exact[watchee_device_name_prefix][status_name_pat].delete watcher_device_name
60
+ end
61
+ else
62
+ if /\*\z/ =~ status_name_pat
63
+ status_name_prefix = $`
64
+ @watch_exact_prefix[watchee_device_name_pat][status_name_prefix].delete watcher_device_name
65
+ else
66
+ @watch_exact_exact[watchee_device_name_pat][status_name_pat].delete watcher_device_name
67
+ end
68
+ end
69
+ end
70
+
71
+ def lookup_watchers(watchee_device_name, status_name)
72
+ # needs cache for performance?
73
+ result = []
74
+ if @watch_exact_exact.has_key?(watchee_device_name) &&
75
+ @watch_exact_exact[watchee_device_name].has_key?(status_name)
76
+ @watch_exact_exact[watchee_device_name][status_name].each {|watcher_device_name, reaction|
77
+ result << [watcher_device_name, reaction]
78
+ }
79
+ end
80
+ if @watch_exact_prefix.has_key?(watchee_device_name)
81
+ @watch_exact_prefix[watchee_device_name].each {|status_name_prefix, h| # linear search. can be slow. binary search is better.
82
+ if status_name.start_with? status_name_prefix
83
+ h.each {|watcher_device_name, reaction|
84
+ result << [watcher_device_name, reaction]
85
+ }
86
+ end
87
+ }
88
+ end
89
+ @watch_prefix_exact.each {|watchee_device_name_prefix, h1| # linear search. can be slow. binary search is better.
90
+ next unless watchee_device_name.start_with? watchee_device_name_prefix
91
+ if @watch_prefix_exact[watchee_device_name_prefix].has_key?(status_name)
92
+ @watch_prefix_exact[watchee_device_name_prefix][status_name].each {|watcher_device_name, reaction|
93
+ result << [watcher_device_name, reaction]
94
+ }
95
+ end
96
+ }
97
+ @watch_prefix_prefix.each {|watchee_device_name_prefix, h1| # linear search. can be slow. binary search is better.
98
+ next unless watchee_device_name.start_with? watchee_device_name_prefix
99
+ @watch_prefix_prefix[watchee_device_name_prefix].each {|status_name_prefix, h| # linear search. can be slow. binary search is better.
100
+ if status_name.start_with? status_name_prefix
101
+ h.each {|watcher_device_name, reaction|
102
+ result << [watcher_device_name, reaction]
103
+ }
104
+ end
105
+ }
106
+ }
107
+ result
108
+ end
109
+
110
+ def watcher_each(watcher_device_name)
111
+ return unless @watch_defs.has_key? watcher_device_name
112
+ @watch_defs[watcher_device_name].each {|watchee_device_name_pat, h|
113
+ h.each {|status_name_pat, reaction|
114
+ yield watchee_device_name_pat, status_name_pat, reaction
115
+ }
116
+ }
117
+ end
118
+
119
+ def delete_watcher(watcher_device_name)
120
+ @watch_defs.delete watcher_device_name
121
+
122
+ [@watch_exact_exact,
123
+ @watch_exact_prefix,
124
+ @watch_prefix_exact,
125
+ @watch_prefix_prefix].each {|h0|
126
+ h0.each {|watchee_device_name, h1|
127
+ h1.each {|status_name, h2|
128
+ h2.delete watcher_device_name
129
+ }
130
+ }
131
+ }
132
+ end
133
+ end
@@ -9,7 +9,7 @@ class Repeater < FSEvent::AbstractDevice
9
9
  @schedule = schedule
10
10
  end
11
11
 
12
- def run(watched_status_change)
12
+ def run(watched_status, changed_status)
13
13
  @framework.set_elapsed_time(1)
14
14
  p @framework.current_time.iso8601(3)
15
15
  end
@@ -8,7 +8,7 @@ class Repeater < FSEvent::AbstractDevice
8
8
  @schedule = schedule
9
9
  end
10
10
 
11
- def run(watched_status_change)
11
+ def run(watched_status, changed_status)
12
12
  p [self.name, @framework.current_time]
13
13
  end
14
14
  end
@@ -35,10 +35,10 @@ class TestFSEventFailSafeDevice < Test::Unit::TestCase
35
35
  define_status("s", @init)
36
36
  end
37
37
 
38
- def run(watched_status_change)
38
+ def run(watched_status, changed_status)
39
39
  @test_result << [@framework.current_time, @values.first]
40
40
  set_elapsed_time(@elapsed)
41
- status_changed "s", @values.shift
41
+ modify_status "s", @values.shift
42
42
  end
43
43
  end
44
44
 
@@ -68,9 +68,9 @@ class TestFSEventFailSafeDevice < Test::Unit::TestCase
68
68
  set_elapsed_time(1)
69
69
  end
70
70
 
71
- def run(watched_status_change)
71
+ def run(watched_status, changed_status)
72
72
  set_elapsed_time(1)
73
- super(watched_status_change)
73
+ super(watched_status, changed_status)
74
74
  end
75
75
  end
76
76
 
@@ -89,9 +89,9 @@ class TestFSEventFailSafeDevice < Test::Unit::TestCase
89
89
  add_watch(@watchee_device_name, @watchee_status)
90
90
  end
91
91
 
92
- def run(watched_status_change)
92
+ def run(watched_status, changed_status)
93
93
  set_elapsed_time(1)
94
- @test_result << [@framework.current_time, watched_status_change]
94
+ @test_result << [@framework.current_time, watched_status]
95
95
  end
96
96
  end
97
97
 
@@ -36,6 +36,7 @@ class TestFSEventFramework < Test::Unit::TestCase
36
36
  def test_inactive_device
37
37
  fsevent = FSEvent.new
38
38
  device = FSEvent::AbstractDevice.new("test_inactive_device")
39
+ fsevent.register_device device
39
40
  assert_nothing_raised { fsevent.start }
40
41
  end
41
42
 
@@ -45,13 +46,13 @@ class TestFSEventFramework < Test::Unit::TestCase
45
46
  fsevent = FSEvent.new(t0)
46
47
  device = TDevice.new("test_single_run")
47
48
  device.schedule.merge_schedule([t1])
48
- def device.run(watched_status_change)
49
+ def device.run(watched_status, changed_status)
49
50
  @test_result << @framework.current_time
50
- @test_result << watched_status_change
51
+ @test_result << watched_status
51
52
  end
52
53
  fsevent.register_device(device)
53
54
  assert_nothing_raised { fsevent.start }
54
- assert_equal([t1, nil], device.test_result)
55
+ assert_equal([t1, {}], device.test_result)
55
56
  end
56
57
 
57
58
  def test_double_run
@@ -61,13 +62,13 @@ class TestFSEventFramework < Test::Unit::TestCase
61
62
  fsevent = FSEvent.new(t0)
62
63
  device = TDevice.new("test_double_run")
63
64
  device.schedule.merge_schedule([t1, t2])
64
- def device.run(watched_status_change)
65
+ def device.run(watched_status, changed_status)
65
66
  @test_result << @framework.current_time
66
- @test_result << watched_status_change
67
+ @test_result << watched_status
67
68
  end
68
69
  fsevent.register_device(device)
69
70
  assert_nothing_raised { fsevent.start }
70
- assert_equal([t1, nil, t2, nil], device.test_result)
71
+ assert_equal([t1, {}, t2, {}], device.test_result)
71
72
  end
72
73
 
73
74
  def test_repeated_run
@@ -77,7 +78,7 @@ class TestFSEventFramework < Test::Unit::TestCase
77
78
  device = TDevice.new("test_repeated_run")
78
79
  schedule = FSEvent::PeriodicSchedule.new(t1, 3)
79
80
  device.schedule.merge_schedule(schedule)
80
- def device.run(watched_status_change)
81
+ def device.run(watched_status, changed_status)
81
82
  @test_result << @framework.current_time
82
83
  @schedule = [] if 2 < @test_result.length
83
84
  end
@@ -93,12 +94,12 @@ class TestFSEventFramework < Test::Unit::TestCase
93
94
  fsevent = FSEvent.new(t0)
94
95
  device1 = TDevice.new("test_twodevice_1")
95
96
  device1.schedule.merge_schedule([t1])
96
- def device1.run(watched_status_change)
97
+ def device1.run(watched_status, changed_status)
97
98
  @test_result << @framework.current_time
98
99
  end
99
100
  device2 = TDevice.new("test_twodevice_2")
100
101
  device2.schedule.merge_schedule([t2])
101
- def device2.run(watched_status_change)
102
+ def device2.run(watched_status, changed_status)
102
103
  @test_result << @framework.current_time
103
104
  end
104
105
  fsevent.register_device(device1)
@@ -108,13 +109,45 @@ class TestFSEventFramework < Test::Unit::TestCase
108
109
  assert_equal([t2], device2.test_result)
109
110
  end
110
111
 
112
+ def test_negative_elapsed_time
113
+ t = Time.utc(2000)
114
+ fse = FSEvent.new(t)
115
+ d = FSEvent::AbstractDevice.new("d")
116
+ def d.registered
117
+ set_elapsed_time(-1)
118
+ end
119
+ fse.register_device d
120
+ assert_raise(ArgumentError) { fse.start }
121
+ end
122
+
123
+ def test_undefine_status
124
+ t = Time.utc(2000)
125
+ fse = FSEvent.new(t)
126
+ d1 = FSEvent::SimpleDevice.new("d1", {"s"=>0}, [], 5, [t+10]) {|watched_status, changed_status|
127
+ fse.undefine_status("s")
128
+ fse.set_elapsed_time(1)
129
+ }
130
+ result = []
131
+ d2 = FSEvent::SimpleDevice.new("d2", {}, [["d1", "s", :immediate]], 1) {|watched_status, changed_status|
132
+ result << [fse.current_time, watched_status, changed_status]
133
+ fse.set_elapsed_time(1)
134
+ }
135
+ fse.register_device d1
136
+ fse.register_device d2
137
+ fse.start
138
+ assert_equal(
139
+ [[t+5, {"d1"=>{"s"=>0}}, {"d1"=>{"s"=>t+5}}],
140
+ [t+11, {"d1"=>{}}, {"d1"=>{"s"=>t+11}}]],
141
+ result)
142
+ end
143
+
111
144
  def test_unregister_in_sleeping
112
145
  t0 = Time.utc(2000)
113
146
  fsevent = FSEvent.new(t0)
114
147
  sched1 = FSEvent::PeriodicSchedule.new(t0+10,5)
115
148
  result = []
116
149
  device1 = FSEvent::SimpleDevice.new("target", {}, [], 1, sched1) {
117
- |watched_status_change|
150
+ |watched_status, changed_status|
118
151
  result << fsevent.current_time
119
152
  fsevent.set_elapsed_time(2)
120
153
  }
@@ -133,7 +166,7 @@ class TestFSEventFramework < Test::Unit::TestCase
133
166
  sched1 = FSEvent::PeriodicSchedule.new(t0+10,5)
134
167
  result = []
135
168
  device1 = FSEvent::SimpleDevice.new("target", {}, [], 1, sched1) {
136
- |watched_status_change|
169
+ |watched_status, changed_status|
137
170
  result << fsevent.current_time
138
171
  fsevent.set_elapsed_time(2)
139
172
  }
@@ -152,7 +185,7 @@ class TestFSEventFramework < Test::Unit::TestCase
152
185
  sched1 = FSEvent::PeriodicSchedule.new(t0+10,5)
153
186
  result = []
154
187
  device1 = FSEvent::SimpleDevice.new("target", {}, [], 1, sched1) {
155
- |watched_status_change|
188
+ |watched_status, changed_status|
156
189
  result << fsevent.current_time
157
190
  if fsevent.current_time == t0+20
158
191
  fsevent.unregister_device("target")
@@ -164,4 +197,147 @@ class TestFSEventFramework < Test::Unit::TestCase
164
197
  assert_equal([t0+10,t0+15,t0+20], result)
165
198
  end
166
199
 
200
+ def test_unregister_time
201
+ t = Time.utc(2000)
202
+ fse = FSEvent.new(t)
203
+ d1 = FSEvent::SimpleDevice.new("d1", {"s"=>0}, [], 5, [t+10]) {|watched_status, changed_status|
204
+ fse.unregister_device("d1")
205
+ fse.set_elapsed_time(1)
206
+ }
207
+ result = []
208
+ d2 = FSEvent::SimpleDevice.new("d2", {}, [["d1", "s", :immediate]], 1) {|watched_status, changed_status|
209
+ result << [fse.current_time, watched_status, changed_status]
210
+ fse.set_elapsed_time(1)
211
+ }
212
+ fse.register_device d1
213
+ fse.register_device d2
214
+ fse.start
215
+ assert_equal(
216
+ [[t+5, {"d1"=>{"s"=>0}}, {"d1"=>{"s"=>t+5}}],
217
+ [t+11, {"d1"=>{}}, {"d1"=>{"s"=>t+11}}]],
218
+ result)
219
+ end
220
+
221
+ def test_clock_proc
222
+ t = Time.utc(2000)
223
+ fse = FSEvent.new(t)
224
+ d = FSEvent::SimpleDevice.new("d1", {"s"=>0}, [], 5, [t+20, t+32]) {|watched_status, changed_status|
225
+ fse.set_elapsed_time(1)
226
+ }
227
+ fse.register_device d
228
+ result = []
229
+ fse.clock_proc = lambda {|current_time, next_time|
230
+ result << next_time - current_time
231
+ }
232
+ fse.start
233
+ assert_equal([5, 15, 1, 11, 1], result)
234
+ end
235
+
236
+ def test_device_registered1
237
+ t = Time.utc(2000)
238
+ fse = FSEvent.new(t)
239
+ #fse.register_device FSEvent::DebugDumper.new
240
+ d11 = FSEvent::SimpleDevice.new("d1", {}, [], 1, [t+19, t+29, t+39, t+49]) {|watched_status, changed_status|
241
+ case fse.current_time
242
+ when t+10
243
+ when t+19
244
+ fse.define_status("s", 100)
245
+ when t+29
246
+ fse.undefine_status("s")
247
+ when t+39
248
+ fse.define_status("s", 200)
249
+ when t+49
250
+ fse.unregister_device("d1")
251
+ else
252
+ raise "unexpected time"
253
+ end
254
+ fse.set_elapsed_time(1)
255
+ }
256
+ d12 = FSEvent::SimpleDevice.new("d1", {}, [], 1, []) {|watched_status, changed_status|
257
+ fse.set_elapsed_time(1)
258
+ }
259
+ d0 = FSEvent::SimpleDevice.new("d0", {}, [], 1, [t+9, t+59]) {|watched_status, changed_status|
260
+ fse.set_elapsed_time(1)
261
+ case fse.current_time
262
+ when t+9
263
+ fse.register_device d11
264
+ when t+59
265
+ fse.register_device d12
266
+ else
267
+ raise "unexpected wakeup d0"
268
+ end
269
+ }
270
+ times = []
271
+ d2 = FSEvent::SimpleDevice.new("d2", {},
272
+ [["_fsevent", "_device_registered_d1", :immediate],
273
+ ["_fsevent", "_device_unregistered_d1", :immediate],
274
+ ["d1", "_status_defined_s", :immediate],
275
+ ["d1", "_status_undefined_s", :immediate],
276
+ ["d1", "s", :immediate]],
277
+ 1, [t+5]) {|watched_status, changed_status|
278
+ case fse.current_time
279
+ when t+5
280
+ assert_equal({"_fsevent"=>{}, "d1"=>{}}, watched_status)
281
+ assert_equal({"_fsevent"=>{}, "d1"=>{}}, changed_status)
282
+ when t+11
283
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11}, "d1"=>{}}, watched_status)
284
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11}, "d1"=>{}}, changed_status)
285
+ when t+20
286
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11}, "d1"=>{"s"=>100, "_status_defined_s"=>t+20}}, watched_status)
287
+ assert_equal({"_fsevent"=>{}, "d1"=>{"s"=>t+20, "_status_defined_s"=>t+20}}, changed_status)
288
+ when t+30
289
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11}, "d1"=>{"_status_defined_s"=>t+20, "_status_undefined_s"=>t+30}}, watched_status)
290
+ assert_equal({"_fsevent"=>{}, "d1"=>{"s"=>t+30, "_status_undefined_s"=>t+30}}, changed_status)
291
+ when t+40
292
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11}, "d1"=>{"s"=>200, "_status_defined_s"=>t+40, "_status_undefined_s"=>t+30}}, watched_status)
293
+ assert_equal({"_fsevent"=>{}, "d1"=>{"s"=>t+40, "_status_defined_s"=>t+40}}, changed_status)
294
+ when t+50
295
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+11, "_device_unregistered_d1"=>t+50}, "d1"=>{}}, watched_status)
296
+ assert_equal({"_fsevent"=>{"_device_unregistered_d1"=>t+50}, "d1"=>{"s"=>t+50, "_status_undefined_s"=>t+50}}, changed_status)
297
+ when t+61
298
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+61, "_device_unregistered_d1"=>t+50}, "d1"=>{}}, watched_status)
299
+ assert_equal({"_fsevent"=>{"_device_registered_d1"=>t+61}, "d1"=>{}}, changed_status)
300
+ else
301
+ raise "unexpected wakeup d2 #{fse.current_time}"
302
+ end
303
+ times << fse.current_time
304
+ fse.set_elapsed_time(1)
305
+ }
306
+ fse.register_device d0
307
+ fse.register_device d2
308
+ fse.start
309
+ assert_equal([t+5, t+11, t+20, t+30, t+40, t+50, t+61], times)
310
+ end
311
+
312
+ def test_valid_name_for_write
313
+ t = Time.utc(2000)
314
+ fse = FSEvent.new(t)
315
+ assert_raise(ArgumentError) {
316
+ d = FSEvent::AbstractDevice.new("_d")
317
+ fse.register_device(d)
318
+ }
319
+ assert_raise(ArgumentError) { fse.define_status("_s", 0) }
320
+ assert_raise(ArgumentError) { fse.modify_status("_s", 0) }
321
+ assert_raise(ArgumentError) { fse.undefine_status("_s") }
322
+ assert_raise(ArgumentError) { fse.unregister_device("_d") }
323
+
324
+ end
325
+
326
+ def test_register_time
327
+ t = Time.utc(2000)
328
+ fse = FSEvent.new(t)
329
+ result = []
330
+ d1 = FSEvent::SimpleDevice.new("d1", {}, [], 1, [t+10]) {|watched_status, changed_status|
331
+ fse.set_elapsed_time(10)
332
+ d2 = FSEvent::AbstractDevice.new("d2")
333
+ class << d2; self end.send(:define_method, :registered) {
334
+ result << fse.current_time
335
+ }
336
+ fse.register_device(d2)
337
+ }
338
+ fse.register_device d1
339
+ fse.start
340
+ assert_equal([t+20], result)
341
+ end
342
+
167
343
  end