ruby_ex 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/AUTHORS +51 -0
  2. data/ChangeLog +1763 -0
  3. data/NEWS +3 -0
  4. data/README +1 -0
  5. data/Rakefile +8 -0
  6. data/SPEC.dyn.yml +10 -0
  7. data/SPEC.gem.yml +269 -0
  8. data/SPEC.yml +36 -0
  9. data/src/abstract.rb +253 -0
  10. data/src/abstract_node.rb +85 -0
  11. data/src/algorithms.rb +12 -0
  12. data/src/algorithms/simulated_annealing.rb +142 -0
  13. data/src/ask.rb +100 -0
  14. data/src/attributed_class.rb +303 -0
  15. data/src/cache.rb +350 -0
  16. data/src/checkout.rb +12 -0
  17. data/src/choose.rb +271 -0
  18. data/src/commands.rb +20 -0
  19. data/src/commands/command.rb +492 -0
  20. data/src/commands/datas.rb +16 -0
  21. data/src/commands/datas/composite.rb +31 -0
  22. data/src/commands/datas/data.rb +65 -0
  23. data/src/commands/datas/factory.rb +69 -0
  24. data/src/commands/datas/temp.rb +26 -0
  25. data/src/commands/factory.rb +67 -0
  26. data/src/commands/helpers.rb +81 -0
  27. data/src/commands/pipe.rb +66 -0
  28. data/src/commands/runners.rb +16 -0
  29. data/src/commands/runners/exec.rb +50 -0
  30. data/src/commands/runners/fork.rb +130 -0
  31. data/src/commands/runners/runner.rb +140 -0
  32. data/src/commands/runners/system.rb +57 -0
  33. data/src/commands/seq.rb +32 -0
  34. data/src/config_file.rb +95 -0
  35. data/src/const_regexp.rb +57 -0
  36. data/src/daemon.rb +135 -0
  37. data/src/diff.rb +665 -0
  38. data/src/dlogger.rb +62 -0
  39. data/src/drb/drb_observable.rb +95 -0
  40. data/src/drb/drb_observable_pool.rb +27 -0
  41. data/src/drb/drb_service.rb +44 -0
  42. data/src/drb/drb_undumped_attributes.rb +56 -0
  43. data/src/drb/drb_undumped_indexed_object.rb +55 -0
  44. data/src/drb/insecure_protected_methods.rb +101 -0
  45. data/src/drb_ex.rb +12 -0
  46. data/src/dumpable_proc.rb +57 -0
  47. data/src/filetype.rb +229 -0
  48. data/src/generate_id.rb +44 -0
  49. data/src/histogram.rb +222 -0
  50. data/src/hookable.rb +283 -0
  51. data/src/hooker.rb +54 -0
  52. data/src/indexed_node.rb +65 -0
  53. data/src/io_marshal.rb +99 -0
  54. data/src/ioo.rb +193 -0
  55. data/src/labeled_node.rb +62 -0
  56. data/src/logger_observer.rb +24 -0
  57. data/src/md5sum.rb +70 -0
  58. data/src/module/autoload_tree.rb +65 -0
  59. data/src/module/hierarchy.rb +334 -0
  60. data/src/module/instance_method_visibility.rb +71 -0
  61. data/src/node.rb +81 -0
  62. data/src/object_monitor.rb +143 -0
  63. data/src/object_monitor_activity.rb +34 -0
  64. data/src/observable.rb +138 -0
  65. data/src/observable_pool.rb +291 -0
  66. data/src/orderedhash.rb +252 -0
  67. data/src/pp_hierarchy.rb +30 -0
  68. data/src/random_generators.rb +29 -0
  69. data/src/random_generators/random_generator.rb +33 -0
  70. data/src/random_generators/ruby.rb +25 -0
  71. data/src/ruby_ex.rb +124 -0
  72. data/src/safe_eval.rb +346 -0
  73. data/src/sendmail.rb +214 -0
  74. data/src/service_manager.rb +122 -0
  75. data/src/shuffle.rb +30 -0
  76. data/src/spring.rb +134 -0
  77. data/src/spring_set.rb +134 -0
  78. data/src/symtbl.rb +108 -0
  79. data/src/synflow.rb +474 -0
  80. data/src/thread_mutex.rb +11 -0
  81. data/src/timeout_ex.rb +79 -0
  82. data/src/trace.rb +26 -0
  83. data/src/uri/druby.rb +78 -0
  84. data/src/uri/file.rb +63 -0
  85. data/src/uri/ftp_ex.rb +36 -0
  86. data/src/uri/http_ex.rb +41 -0
  87. data/src/uri/pgsql.rb +136 -0
  88. data/src/uri/ssh.rb +87 -0
  89. data/src/uri/svn.rb +113 -0
  90. data/src/uri_ex.rb +71 -0
  91. data/src/verbose_object.rb +70 -0
  92. data/src/yaml/basenode_ext.rb +63 -0
  93. data/src/yaml/chop_header.rb +24 -0
  94. data/src/yaml/transform.rb +450 -0
  95. data/src/yaml/yregexpath.rb +76 -0
  96. data/test/algorithms/simulated_annealing_test.rb +102 -0
  97. data/test/check-pkg-ruby_ex.yml +15 -0
  98. data/test/check-ruby_ex.yml +12 -0
  99. data/test/resources/autoload_tree/A.rb +11 -0
  100. data/test/resources/autoload_tree/B.rb +10 -0
  101. data/test/resources/autoload_tree/foo/C.rb +18 -0
  102. data/test/resources/foo.txt +6 -0
  103. data/test/sanity-suite.yml +12 -0
  104. data/test/sanity/multiple-requires.yml +20 -0
  105. data/test/sanity/single-requires.yml +24 -0
  106. data/test/test-unit-setup.rb +6 -0
  107. data/test/unit-suite.yml +14 -0
  108. metadata +269 -0
data/src/spring_set.rb ADDED
@@ -0,0 +1,134 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
+ # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy: ertai $
6
+ # $Id: spring_set.rb 258 2005-06-01 00:22:51Z ertai $
7
+
8
+
9
+ require 'spring'
10
+
11
+
12
+ class SpringSet
13
+
14
+ def initialize(*springs)
15
+ @springs = {}
16
+ springs.flatten.each do |s|
17
+ @springs[s.object_id] = {
18
+ :spring => s,
19
+ :num_collecter => s.num_collecter,
20
+ :size => s.size
21
+ }
22
+ s.add_observer(self)
23
+ end
24
+ end
25
+
26
+ def update(spring_id, msg, collecter_id)
27
+ case msg
28
+ when Spring::SIGN_UP
29
+ @springs[spring_id][:num_collecter] += 1
30
+ when Spring::GET
31
+ @springs[spring_id][:size] -= 1 if @springs[spring_id][:size] > 0
32
+ end
33
+ end
34
+
35
+ def get_most_free
36
+ calc_stat(:num_collecter) { |a, b| a < b }
37
+ end
38
+
39
+ def get_most_busy
40
+ calc_stat(:num_collecter) { |a, b| a > b }
41
+ end
42
+
43
+ def get_most_full
44
+ calc_stat(:size) { |a, b| a > b }
45
+ end
46
+
47
+ def get_most_empty
48
+ calc_stat(:size) { |a, b| a < b }
49
+ end
50
+
51
+ def size
52
+ @springs.size
53
+ end
54
+
55
+ alias length size
56
+
57
+ def num_collecter(spring_id)
58
+ @springs[spring_id][:num_collecter]
59
+ end
60
+
61
+ def spring_size(spring_id)
62
+ @springs[spring_id][:size]
63
+ end
64
+
65
+ alias spring_length spring_size
66
+
67
+ def each
68
+ @springs.values.each { |v| yield(v[:spring]) }
69
+ end
70
+
71
+ protected
72
+ def calc_stat(field, &cmp)
73
+ spring = nil
74
+ @springs.values.each do |s|
75
+ if spring.nil? or cmp[s[field], spring[field]]
76
+ spring = s
77
+ end
78
+ end
79
+ return spring[:spring]
80
+ end
81
+
82
+ end # class SpringSet
83
+
84
+
85
+ #
86
+ # Unit test suite
87
+ #
88
+ test_section __FILE__ do
89
+
90
+
91
+ class SpringSetTest < Test::Unit::TestCase
92
+
93
+ #
94
+ # tests
95
+ #
96
+ def test_simple
97
+ s1 = Spring.new('hello', 'world')
98
+ s2 = Spring.new('bonjour', 'tout', 'monde')
99
+ s = SpringSet.new(s1, s2)
100
+ assert_equal(s1.num_collecter, s.num_collecter(s1.object_id))
101
+ assert_equal(s2.num_collecter, s.num_collecter(s2.object_id))
102
+ assert_equal(s1.size, s.spring_size(s1.object_id))
103
+ assert_equal(s2.length, s.spring_length(s2.object_id))
104
+ thread = Thread.new do
105
+ sleep(0.0001)
106
+ assert_equal(2, s.size)
107
+ assert_equal(2, s.length)
108
+ assert_equal(s2, s.get_most_full)
109
+ assert_equal(s1, s.get_most_empty)
110
+ s1.sign_up(thread.object_id)
111
+ assert_equal(s1.num_collecter, s.num_collecter(s1.object_id))
112
+ assert_equal(s1, s.get_most_busy)
113
+ assert_equal(s2, s.get_most_free)
114
+ s2.sign_up(thread.object_id)
115
+ assert_equal(s2.num_collecter, s.num_collecter(s2.object_id), 'bad num collecter')
116
+ assert_equal('bonjour', s2.get(thread.object_id))
117
+ assert_equal(s2.size, s.spring_size(s2.object_id), 'bad size')
118
+ assert_equal('tout', s2.get(thread.object_id))
119
+ assert_equal(s2.size, s.spring_size(s2.object_id))
120
+ assert_equal('monde', s2.get(thread.object_id))
121
+ assert_equal(s2.size, s.spring_size(s2.object_id))
122
+ assert_equal(nil, s2.get(thread.object_id))
123
+ assert_equal(s2.size, s.spring_size(s2.object_id))
124
+ assert_equal(0, s.spring_size(s2.object_id))
125
+ assert_equal(s1, s.get_most_full)
126
+ assert_equal(s2, s.get_most_empty)
127
+ end
128
+ thread.join
129
+ end
130
+
131
+ end # class SpringSetTest
132
+
133
+
134
+ end
data/src/symtbl.rb ADDED
@@ -0,0 +1,108 @@
1
+ # Author: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright: Copyright (c) 2004 Nicolas Pouillard. All rights reserved.
3
+ # License: Ruby license.
4
+
5
+ # $LastChangedBy: ertai $
6
+ # $Id: symtbl.rb 266 2005-06-01 14:27:18Z ertai $
7
+
8
+ require 'ruby_ex'
9
+ require 'set'
10
+
11
+ class SymTbl
12
+
13
+ @@sid = -1
14
+
15
+ attr_reader :sid, :local, :father
16
+
17
+ def initialize ( father_env=nil, default=nil )
18
+ @father = father_env
19
+ @sid = (@@sid += 1)
20
+ @local = Hash.new(default)
21
+ end
22
+
23
+ def [] ( aKey )
24
+ if @local.has_key? aKey
25
+ @local[aKey]
26
+ elsif @father.nil?
27
+ @local.default
28
+ else
29
+ @father[aKey]
30
+ end
31
+ end
32
+
33
+ def []= ( aKey, aValue )
34
+ @local[aKey] = aValue
35
+ end
36
+
37
+ # FIXME
38
+ def each ( &block )
39
+ key_set = Set.new
40
+ blk = lambda do |k,v|
41
+ block[k, v] unless key_set.include? k
42
+ key_set << k
43
+ end
44
+ @local.each(&blk)
45
+ @father.each(&blk) unless @father.nil?
46
+ end
47
+
48
+ def ancestors
49
+ (@father.is_a?(SymTbl))? [self] + @father.ancestors : [self]
50
+ end
51
+
52
+ def desc_one
53
+ if defined? @already_described
54
+ return sid
55
+ else
56
+ @already_described = true
57
+ return { sid => @local }
58
+ end
59
+ end
60
+
61
+ def desc
62
+ ancestors.map{ |s| s.desc_one }.to_yaml
63
+ end
64
+
65
+ end # class SymTbl
66
+
67
+
68
+
69
+ test_section __FILE__ do
70
+
71
+ require 'ruby_ex'
72
+ class SymTblTest < Test::Unit::TestCase
73
+
74
+ def test1
75
+ root = SymTbl.new
76
+
77
+ root[:a] = 0
78
+ root[:b] = 1
79
+
80
+ assert_equal(1, root[:b], 't1')
81
+ assert_equal(0, root[:a], 't2')
82
+
83
+ sub1 = SymTbl.new(root)
84
+
85
+ sub1[:a] = 2
86
+ sub1[:c] = 3
87
+
88
+ assert_equal(1, sub1[:b], 't3')
89
+ assert_equal(2, sub1[:a], 't4')
90
+ assert_equal(3, sub1[:c], 't5')
91
+
92
+ assert_equal(0, root[:a], 't6')
93
+
94
+ sub2 = SymTbl.new(sub1)
95
+
96
+ assert_equal(2, sub2[:a], 't7')
97
+
98
+ sub2[:a] = 42
99
+
100
+ assert_equal(42, sub2[:a], 't8')
101
+
102
+ assert_equal([{2=>{:a=>42}}, {1=>{:a=>2, :c=>3}}, {0=>{:b=>1, :a=>0}}],
103
+ YAML::load(sub2.desc))
104
+ end
105
+
106
+ end # class SymTblTest
107
+
108
+ end
data/src/synflow.rb ADDED
@@ -0,0 +1,474 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Pouillard. All rights reserved.
2
+ # Author: Nicolas Pouillard <ertai@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy$
6
+ # $Id$
7
+
8
+ #
9
+ # Efficients control flows for synchronisation (and mutual exclusion) in
10
+ # parallel systems.
11
+ #
12
+
13
+ require 'ruby_ex'
14
+ require 'thread'
15
+ require 'set'
16
+
17
+ #
18
+ # The +SynFlowFactory+ define the common part for a set of flows.
19
+ #
20
+ # A SynFlow is like an automaton (finite state machine):
21
+ # * states
22
+ # * transitions
23
+ # * an alphabet
24
+ # * an initial state
25
+ # * a set of final states
26
+ #
27
+ # With this automaton (diagram, graph...) you can easily describe important
28
+ # steps of your program control flow.
29
+ #
30
+ # Your automaton describe a model of execution and constraint every execution
31
+ # to it.
32
+ #
33
+ # When a thread want to change the state of its flow it proceed like that:
34
+ # flow << :a_symbol_of_the_alphabet
35
+ #
36
+ # If a transition between the _current_ state and a state _destination_ is
37
+ # labeled by _symbol_, then the state is updated to _destination_.
38
+ # Otherwise the thread is constraint to wait the modification of the _current_
39
+ # state.
40
+ #
41
+ # See examples below to know how to use these class.
42
+ #
43
+ class SynFlowFactory
44
+
45
+ class Transition
46
+ attr_reader :src, :dest, :label
47
+
48
+ def initialize ( src, label, dest )
49
+ @src, @label, @dest = src, label, dest
50
+ end
51
+
52
+ def to_a
53
+ [@src, @label, @dest]
54
+ end
55
+
56
+ def == ( rhs )
57
+ rhs.is_a? self.class and
58
+ @label == rhs.label and
59
+ @dest == rhs.dest and
60
+ @src == rhs.src
61
+ end
62
+ end # class Transition
63
+
64
+
65
+ class TransitionSet
66
+
67
+ def initialize
68
+ @val = {}
69
+ end
70
+
71
+ def include? ( *a )
72
+ case a.size
73
+ when 1
74
+ t = a[0]
75
+ case t
76
+ when Array
77
+ return include?(*t)
78
+ else
79
+ return delta(t.src, t.label) == t.dest
80
+ end
81
+ when 2
82
+ state, label = a
83
+ return ! delta(state, label).nil?
84
+ when 3
85
+ state, label, dest = a
86
+ return delta(state, label) == dest
87
+ else
88
+ raise ArgumentError, 'bad transition'
89
+ end
90
+ end
91
+
92
+ def add ( src, label, dest )
93
+ @val[src] ||= {}
94
+ @val[src][label] = dest
95
+ end
96
+
97
+ def add_transition ( t )
98
+ add(t.src, t.label, t.dest)
99
+ end
100
+
101
+ def delta ( src, label )
102
+ @val[src] ||= {}
103
+ @val[src][label]
104
+ end
105
+
106
+ def << ( transition )
107
+ case transition
108
+ when Array
109
+ add(*transition)
110
+ when Hash
111
+ transition.each do |src, x|
112
+ unless x.is_a? Hash
113
+ raise TypeError, "bad transtion: #{transition.inspect}"
114
+ end
115
+ x.each do |label, dest|
116
+ add(src, label, dest)
117
+ end
118
+ end
119
+ when Transition
120
+ add_transition(transition)
121
+ else
122
+ raise TypeError, "bad transtion: #{transition.inspect}"
123
+ end
124
+ self
125
+ end
126
+
127
+ end # class TransitionSet
128
+
129
+
130
+ attr_accessor :initial, :transitions
131
+
132
+
133
+ def initialize
134
+ @transitions = TransitionSet.new
135
+ @initial = nil
136
+ end
137
+
138
+
139
+ def << ( transition )
140
+ @transitions << transition
141
+ self
142
+ end
143
+
144
+
145
+ def include? ( *transition )
146
+ @transitions.include?(*transition)
147
+ end
148
+
149
+
150
+ def delta ( src, label )
151
+ @transitions.delta(src, label)
152
+ end
153
+
154
+
155
+ def new_flow
156
+ SynFlow.new(self, @initial)
157
+ end
158
+
159
+
160
+ def initial? ( state )
161
+ state == @initial
162
+ end
163
+
164
+ end # class SynFlowFactory
165
+
166
+
167
+ class SynFlow
168
+
169
+ class Error < Exception
170
+ end
171
+
172
+ attr_reader :state
173
+ attr_reader :i
174
+
175
+ @@i = -1
176
+ def initialize ( factory, initial_state )
177
+ @i = (@@i += 1)
178
+ super()
179
+ @mutex = Mutex.new
180
+ @condition = ConditionVariable.new
181
+ @factory = factory
182
+ @state = initial_state
183
+ end
184
+
185
+
186
+ def feed ( label )
187
+ D "#@i: Want read label #{label} (#@state)"
188
+ @mutex.synchronize do
189
+ while not @factory.include?(@state, label)
190
+ begin
191
+ @condition.wait(@mutex)
192
+ rescue ThreadError
193
+ raise Error,
194
+ 'Cannot wait for change state because only one thread is running'
195
+ end
196
+ end
197
+ dest = @factory.delta(@state, label)
198
+ D "#@i: Ok change state with label #{label} (#@state -> #{dest})"
199
+ @state = dest
200
+ @condition.broadcast
201
+ end
202
+ end
203
+
204
+ alias advance feed
205
+ alias << feed
206
+
207
+
208
+ def try_feed ( label )
209
+ D "#@i: Try read label #{label} (#@state)"
210
+ if @mutex.try_lock
211
+ begin
212
+ if @factory.include?(@state, label)
213
+ dest = @factory.delta(@state, label)
214
+ D "#@i: Ok change state with label #{label} (#@state -> #{dest})"
215
+ @state = dest
216
+ @condition.broadcast
217
+ return true
218
+ end
219
+ ensure
220
+ @mutex.unlock
221
+ end
222
+ end
223
+ D "#@i: Ko you cannot change state"
224
+ return false
225
+ end
226
+
227
+ alias try_advance try_feed
228
+
229
+
230
+ def destroy
231
+ @i = @mutex = @condition = @factory = @state = nil
232
+ end
233
+
234
+
235
+ @@out = []
236
+
237
+ def self.debug_out
238
+ @@out
239
+ end
240
+
241
+ def D ( msg )
242
+ # @@out << msg
243
+ # STDERR.puts msg
244
+ end
245
+ private :D
246
+
247
+ end # class SynFlow
248
+
249
+
250
+
251
+ test_section __FILE__ do
252
+
253
+ require 'timeout'
254
+
255
+
256
+ class SynFlowTest < Test::Unit::TestCase
257
+
258
+ T = SynFlowFactory::Transition
259
+ TSet = SynFlowFactory::TransitionSet
260
+
261
+ def test_aa_simple_transition
262
+ assert_equal(T.new(:a, :b, :c), T.new(:a, :b, :c))
263
+ assert_not_equal(T.new(:b, :a, :c), T.new(:a, :b, :d))
264
+ end
265
+
266
+ def test_ab_simple_transition_set
267
+ s = TSet.new
268
+ s << T.new(:a, :b, :c) << T.new(:b, :a, :d) << [:e, :f, :g]
269
+ assert(s.include?(:a, :b))
270
+ assert(s.include?(T.new(:a, :b, :c)))
271
+ assert(s.include?(:b, :a, :d))
272
+ assert(s.include?([:e, :f]))
273
+ end
274
+
275
+ def test_ac_bad_transition_set
276
+ s = TSet.new
277
+ s << T.new(:a, :b, :c) << T.new(:b, :a, :d)
278
+ assert(! s.include?(T.new(:b, :b, :c)))
279
+ assert(! s.include?(:a, :d, :c))
280
+ assert(! s.include?([:c, :b]))
281
+ end
282
+
283
+ #
284
+ # g
285
+ # +---------------------------+
286
+ # | |
287
+ # v a b c d |
288
+ # 1 ---> 2 ---> 3 ---> 4 ---> 5
289
+ # | ^
290
+ # | e f |
291
+ # +----> 6 -----+
292
+ #
293
+ def make_simple_factory
294
+ f = SynFlowFactory.new
295
+ f << [1, :a, 2] \
296
+ << [6, :f, 4] \
297
+ << SynFlowFactory::Transition.new(3, :c, 4)
298
+ f << { 2 => { :e => 6, :b => 3 },
299
+ 4 => { :d => 5 },
300
+ 5 => { :g => 1 }
301
+ }
302
+ f.initial = 1
303
+ return f
304
+ end
305
+
306
+ def test_ad_simple_factory
307
+ f = nil
308
+ assert_nothing_raised do
309
+ f = make_simple_factory
310
+ end
311
+ transitions =
312
+ [[1, :a, 2],
313
+ [6, :f, 4],
314
+ [3, :c, 4],
315
+ [2, :e, 6],
316
+ [2, :b, 3],
317
+ [4, :d, 5],
318
+ [5, :g, 1]]
319
+ transitions.each do |s, l, d|
320
+ assert(f.transitions.include?(s, l, d))
321
+ end
322
+
323
+ assert(! f.transitions.include?(1, :a, 3))
324
+ assert(! f.transitions.include?(2, :a))
325
+ assert(! f.transitions.include?(1, :a, 1))
326
+
327
+ assert(f.initial?(1))
328
+ assert(! f.initial?(2))
329
+ end
330
+
331
+ def test_ba_simple_flow
332
+ f = make_simple_factory
333
+ m = nil
334
+ assert_nothing_raised { m = f.new_flow }
335
+ assert_nothing_raised do
336
+ Timeout.timeout(2) do
337
+ assert_equal(1, m.state)
338
+ m << :a
339
+ assert_equal(2, m.state)
340
+ m << :b
341
+ assert_equal(3, m.state)
342
+ m << :c
343
+ assert_equal(4, m.state)
344
+ m << :d
345
+ assert_equal(5, m.state)
346
+ m << :g
347
+ assert_equal(1, m.state)
348
+ end
349
+ end
350
+ end
351
+
352
+ def test_bb_simple_loop
353
+ f = make_simple_factory
354
+ f << [6, :e, 6]
355
+ m = f.new_flow
356
+ assert_nothing_raised do
357
+ Timeout.timeout(2) do
358
+ assert_equal(1, m.state)
359
+ m << :a
360
+ assert_equal(2, m.state)
361
+ m << :e
362
+ assert_equal(6, m.state)
363
+ m << :e
364
+ assert_equal(6, m.state)
365
+ m << :f
366
+ assert_equal(4, m.state)
367
+ end
368
+ end
369
+ end
370
+
371
+ def test_bc_simple_try_advance
372
+ f = make_simple_factory
373
+ m = f.new_flow
374
+ assert_nothing_raised do
375
+ Timeout.timeout(2) do
376
+ assert(m.try_advance(:a))
377
+ assert_equal(2, m.state)
378
+ m << :b
379
+ assert_equal(3, m.state)
380
+ assert(! m.try_advance(:e))
381
+ assert_equal(3, m.state)
382
+ m << :c
383
+ assert_equal(4, m.state)
384
+ end
385
+ end
386
+ end
387
+
388
+ def test_c_avanced_flow
389
+ f = make_simple_factory
390
+ m = f.new_flow
391
+ th = Thread.new { sleep ; m << :e }
392
+ assert_raise(Timeout::Error) do
393
+ Timeout.timeout(0.2) do
394
+ th.wakeup
395
+ th.join
396
+ end
397
+ end
398
+ assert_nothing_raised do
399
+ Timeout.timeout(2) do
400
+ m << :a
401
+ sleep 0.1
402
+ assert_equal(6, m.state)
403
+ end
404
+ end
405
+ assert_nothing_raised do
406
+ Timeout.timeout(2) do
407
+ m << :f
408
+ assert_equal(4, m.state)
409
+ m << :d
410
+ assert_equal(5, m.state)
411
+ m << :g
412
+ assert_equal(1, m.state)
413
+ end
414
+ end
415
+ end
416
+
417
+ def test_d_multi_threads
418
+ f = make_simple_factory
419
+ m = f.new_flow
420
+
421
+ assert_nothing_raised do
422
+ Timeout.timeout(5) do
423
+ t = []
424
+ t << Thread.new { m << :d }
425
+ t << Thread.new { m << :c }
426
+ t << Thread.new { m << :a }
427
+ t << Thread.new { m << :b }
428
+ t.each { |t| t.join }
429
+ end
430
+ end
431
+ assert_equal(5, m.state)
432
+ end
433
+
434
+ class E < Exception
435
+ end
436
+
437
+ def test_e_with_block
438
+ f = make_simple_factory
439
+ m = f.new_flow
440
+
441
+ assert_nothing_raised do
442
+ Timeout.timeout(5) do
443
+ t1 = Thread.new do
444
+ sleep
445
+ m << :a
446
+ sleep
447
+ end
448
+ t2 = Thread.new do
449
+ m << :e
450
+ t1.raise E
451
+ end
452
+ t1.wakeup
453
+ t2.join
454
+ assert_raise(E) { t1.join }
455
+ end
456
+ end
457
+ assert_equal(6, m.state)
458
+ end
459
+
460
+ def test_f_dumpable
461
+ f = make_simple_factory
462
+ m = f.new_flow
463
+
464
+ assert_nothing_raised do
465
+ Marshal.load(Marshal.dump(m))
466
+ end
467
+ assert_nothing_raised do
468
+ Marshal.load(Marshal.dump(f))
469
+ end
470
+ end
471
+
472
+ end # class SynFlowTest
473
+
474
+ end