ruby_ex 0.1.1

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.
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