fsevent 0.1 → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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