vcs 0.1 → 0.2.148

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 (132) hide show
  1. data/Rakefile +17 -3
  2. data/bin/vcs +57 -34
  3. data/doc/jamis.rb +564 -0
  4. data/ruby_ex/abstract.rb +254 -0
  5. data/ruby_ex/abstract_node.rb +85 -0
  6. data/ruby_ex/algorithms/simulated_annealing.rb +140 -0
  7. data/ruby_ex/array_each_pair.rb +18 -0
  8. data/ruby_ex/ask.rb +101 -0
  9. data/ruby_ex/attributed_class.rb +302 -0
  10. data/ruby_ex/cache.rb +373 -0
  11. data/ruby_ex/checkout.rb +12 -0
  12. data/ruby_ex/choose.rb +271 -0
  13. data/ruby_ex/commands.rb +18 -0
  14. data/ruby_ex/commands/command.rb +401 -0
  15. data/ruby_ex/commands/datas.rb +16 -0
  16. data/ruby_ex/commands/datas/data.rb +33 -0
  17. data/ruby_ex/commands/datas/factory.rb +66 -0
  18. data/ruby_ex/commands/factory.rb +66 -0
  19. data/ruby_ex/commands/helpers.rb +67 -0
  20. data/ruby_ex/commands/pipe.rb +64 -0
  21. data/ruby_ex/commands/runners.rb +17 -0
  22. data/ruby_ex/commands/runners/exec.rb +49 -0
  23. data/ruby_ex/commands/runners/fork.rb +97 -0
  24. data/ruby_ex/commands/runners/runner.rb +107 -0
  25. data/ruby_ex/commands/seq.rb +27 -0
  26. data/ruby_ex/config_file.rb +96 -0
  27. data/ruby_ex/const_regexp.rb +59 -0
  28. data/ruby_ex/daemon.rb +134 -0
  29. data/ruby_ex/diff.rb +667 -0
  30. data/ruby_ex/dlogger.rb +62 -0
  31. data/ruby_ex/drb/dispatcher.rb +252 -0
  32. data/ruby_ex/drb/dispatcher_server_test.rb +29 -0
  33. data/ruby_ex/drb/drb_observable.rb +97 -0
  34. data/ruby_ex/drb/drb_observable_pool.rb +27 -0
  35. data/ruby_ex/drb/drb_service.rb +43 -0
  36. data/ruby_ex/drb/drb_undumped_attributes.rb +55 -0
  37. data/ruby_ex/drb/drb_undumped_indexed_object.rb +54 -0
  38. data/ruby_ex/drb/insecure_protected_methods.rb +103 -0
  39. data/ruby_ex/drb/session_client_test.rb +40 -0
  40. data/ruby_ex/drb/session_manager.rb +246 -0
  41. data/ruby_ex/drb/session_server.rb +53 -0
  42. data/ruby_ex/dtime.rb +143 -0
  43. data/ruby_ex/dumpable_proc.rb +63 -0
  44. data/ruby_ex/exception.rb +32 -0
  45. data/ruby_ex/filetype.rb +229 -0
  46. data/ruby_ex/fileutils_ex.rb +44 -0
  47. data/ruby_ex/fold.rb +58 -0
  48. data/ruby_ex/generate_id.rb +44 -0
  49. data/ruby_ex/hookable.rb +262 -0
  50. data/ruby_ex/hooker.rb +54 -0
  51. data/ruby_ex/inactive_timeout.rb +137 -0
  52. data/ruby_ex/indexed_node.rb +66 -0
  53. data/ruby_ex/io_marshal.rb +100 -0
  54. data/ruby_ex/ioo.rb +194 -0
  55. data/ruby_ex/labeled_node.rb +63 -0
  56. data/ruby_ex/logger_observer.rb +23 -0
  57. data/ruby_ex/md5sum.rb +66 -0
  58. data/ruby_ex/mktemp.rb +208 -0
  59. data/ruby_ex/module/attr_once.rb +36 -0
  60. data/ruby_ex/module/autoload_tree.rb +75 -0
  61. data/ruby_ex/module/hierarchy.rb +335 -0
  62. data/ruby_ex/module/instance_method_visibility.rb +73 -0
  63. data/ruby_ex/module_ex.rb +11 -0
  64. data/ruby_ex/node.rb +80 -0
  65. data/ruby_ex/object_monitor.rb +145 -0
  66. data/ruby_ex/object_monitor_activity.rb +33 -0
  67. data/ruby_ex/observable.rb +140 -0
  68. data/ruby_ex/observable_pool.rb +293 -0
  69. data/ruby_ex/orderedhash.rb +252 -0
  70. data/ruby_ex/pathname_ex.rb +152 -0
  71. data/ruby_ex/pp_hierarchy.rb +29 -0
  72. data/ruby_ex/pseudo_cache.rb +190 -0
  73. data/ruby_ex/queue.rb +56 -0
  74. data/ruby_ex/random_generators.rb +25 -0
  75. data/ruby_ex/random_generators/random_generator.rb +31 -0
  76. data/ruby_ex/random_generators/ruby.rb +23 -0
  77. data/ruby_ex/safe_eval.rb +348 -0
  78. data/ruby_ex/sendmail.rb +215 -0
  79. data/ruby_ex/service_manager.rb +121 -0
  80. data/ruby_ex/session/administrable.rb +120 -0
  81. data/ruby_ex/session/client.rb +153 -0
  82. data/ruby_ex/session/const.rb +18 -0
  83. data/ruby_ex/session/dispatcher.rb +184 -0
  84. data/ruby_ex/session/error.rb +21 -0
  85. data/ruby_ex/session/fetchable.rb +57 -0
  86. data/ruby_ex/session/fetcher.rb +62 -0
  87. data/ruby_ex/session/hookable.rb +26 -0
  88. data/ruby_ex/session/profile.rb +110 -0
  89. data/ruby_ex/session/server.rb +582 -0
  90. data/ruby_ex/session/test/administrable_test.rb +337 -0
  91. data/ruby_ex/session/test/basic_test.rb +523 -0
  92. data/ruby_ex/session/test/dispatcher_test.rb +409 -0
  93. data/ruby_ex/session/test/fetchable_test.rb +119 -0
  94. data/ruby_ex/session/test/sub_server_test.rb +188 -0
  95. data/ruby_ex/shuffle.rb +30 -0
  96. data/ruby_ex/spring.rb +136 -0
  97. data/ruby_ex/spring_set.rb +137 -0
  98. data/ruby_ex/string_ex.rb +28 -0
  99. data/ruby_ex/symtbl.rb +106 -0
  100. data/ruby_ex/synflow.rb +474 -0
  101. data/ruby_ex/test/unit/ui/yaml/testrunner.rb +164 -0
  102. data/ruby_ex/thread_mutex.rb +10 -0
  103. data/ruby_ex/timeout_ex.rb +81 -0
  104. data/ruby_ex/top_down.rb +73 -0
  105. data/ruby_ex/trace.rb +26 -0
  106. data/ruby_ex/uri/druby.rb +81 -0
  107. data/ruby_ex/uri/file.rb +65 -0
  108. data/ruby_ex/uri/ftp_ex.rb +37 -0
  109. data/ruby_ex/uri/http_ex.rb +43 -0
  110. data/ruby_ex/uri/ssh.rb +92 -0
  111. data/ruby_ex/uri/svn.rb +118 -0
  112. data/ruby_ex/uri_ex.rb +45 -0
  113. data/ruby_ex/verbose_object.rb +30 -0
  114. data/ruby_ex/version.rb +66 -0
  115. data/ruby_ex/yaml/basenode_ext.rb +63 -0
  116. data/ruby_ex/yaml/chop_header.rb +23 -0
  117. data/ruby_ex/yaml/transform.rb +449 -0
  118. data/ruby_ex/yaml/yregexpath.rb +76 -0
  119. data/src/changelog.rb +28 -18
  120. data/src/conflict.rb +20 -0
  121. data/src/diff.rb +18 -0
  122. data/src/diffstat.rb +9 -3
  123. data/src/last_changed_date.rb +18 -0
  124. data/src/mail.rb +33 -65
  125. data/src/message.rb +15 -9
  126. data/src/mycommit.rb +29 -14
  127. data/src/news.rb +24 -3
  128. data/src/status.rb +17 -0
  129. data/src/svn.rb +2 -2
  130. data/src/vcs.rb +24 -3
  131. metadata +124 -5
  132. data/lrdetools.rb +0 -12
@@ -0,0 +1,28 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2004, 2005 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id$
5
+
6
+ class String
7
+
8
+ #
9
+ # Provide an helper to cut strings.
10
+ #
11
+ # Example:
12
+ #
13
+ # puts "
14
+ # | A very complex
15
+ # | string
16
+ # | with a specific indentation.
17
+ # |
18
+ # |I prefer that instead of a HERE doc
19
+ # | because I keep my indentation.
20
+ # |".head_cut!
21
+ #
22
+ def head_cut! ( sep='\|' )
23
+ gsub!(/^\s*#{sep}/, '')
24
+ self
25
+ end
26
+
27
+ end # class String
28
+
@@ -0,0 +1,106 @@
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 189 2005-04-03 00:33:40Z ertai $
7
+
8
+ require 'set'
9
+
10
+ class SymTbl
11
+
12
+ @@sid = -1
13
+
14
+ attr_reader :sid, :local, :father
15
+
16
+ def initialize ( father_env=nil, default=nil )
17
+ @father = father_env
18
+ @sid = (@@sid += 1)
19
+ @local = Hash.new(default)
20
+ end
21
+
22
+ def [] ( aKey )
23
+ if @local.has_key? aKey
24
+ @local[aKey]
25
+ elsif @father.nil?
26
+ @local.default
27
+ else
28
+ @father[aKey]
29
+ end
30
+ end
31
+
32
+ def []= ( aKey, aValue )
33
+ @local[aKey] = aValue
34
+ end
35
+
36
+ # FIXME
37
+ def each ( &block )
38
+ key_set = Set.new
39
+ blk = lambda do |k,v|
40
+ block[k, v] unless key_set.include? k
41
+ key_set << k
42
+ end
43
+ @local.each(&blk)
44
+ @father.each(&blk) unless @father.nil?
45
+ end
46
+
47
+ def ancestors
48
+ (@father.is_a?(SymTbl))? [self] + @father.ancestors : [self]
49
+ end
50
+
51
+ def desc_one
52
+ if defined? @already_described
53
+ return sid
54
+ else
55
+ @already_described = true
56
+ return { sid => @local }
57
+ end
58
+ end
59
+
60
+ def desc
61
+ ancestors.map{ |s| s.desc_one }.to_yaml
62
+ end
63
+
64
+ end # class SymTbl
65
+
66
+
67
+
68
+ if defined? TEST_MODE or __FILE__ == $0
69
+
70
+ require 'test/unit'
71
+ class SymTblTest < Test::Unit::TestCase
72
+
73
+ def test1
74
+ root = SymTbl.new
75
+
76
+ root[:a] = 0
77
+ root[:b] = 1
78
+
79
+ assert_equal(1, root[:b], 't1')
80
+ assert_equal(0, root[:a], 't2')
81
+
82
+ sub1 = SymTbl.new(root)
83
+
84
+ sub1[:a] = 2
85
+ sub1[:c] = 3
86
+
87
+ assert_equal(1, sub1[:b], 't3')
88
+ assert_equal(2, sub1[:a], 't4')
89
+ assert_equal(3, sub1[:c], 't5')
90
+
91
+ assert_equal(0, root[:a], 't6')
92
+
93
+ sub2 = SymTbl.new(sub1)
94
+
95
+ assert_equal(2, sub2[:a], 't7')
96
+
97
+ sub2[:a] = 42
98
+
99
+ assert_equal(42, sub2[:a], 't8')
100
+
101
+ assert_equal([], sub2.desc)
102
+ end
103
+
104
+ end # class SymTblTest
105
+
106
+ end
@@ -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 'thread'
14
+ require 'set'
15
+
16
+ #
17
+ # The +SynFlowFactory+ define the common part for a set of flows.
18
+ #
19
+ # A SynFlow is like an automaton (finite state machine):
20
+ # * states
21
+ # * transitions
22
+ # * an alphabet
23
+ # * an initial state
24
+ # * a set of final states
25
+ #
26
+ # With this automaton (diagram, graph...) you can easily describe important
27
+ # steps of your program control flow.
28
+ #
29
+ # Your automaton describe a model of execution and constraint every execution
30
+ # to it.
31
+ #
32
+ # When a thread want to change the state of its flow it proceed like that:
33
+ # flow << :a_symbol_of_the_alphabet
34
+ #
35
+ # If a transition between the _current_ state and a state _destination_ is
36
+ # labeled by _symbol_, then the state is updated to _destination_.
37
+ # Otherwise the thread is constraint to wait the modification of the _current_
38
+ # state.
39
+ #
40
+ # See examples below to know how to use these class.
41
+ #
42
+ class SynFlowFactory
43
+
44
+ class Transition
45
+ attr_reader :src, :dest, :label
46
+
47
+ def initialize ( src, label, dest )
48
+ @src, @label, @dest = src, label, dest
49
+ end
50
+
51
+ def to_a
52
+ [@src, @label, @dest]
53
+ end
54
+
55
+ def == ( rhs )
56
+ rhs.is_a? self.class and
57
+ @label == rhs.label and
58
+ @dest == rhs.dest and
59
+ @src == rhs.src
60
+ end
61
+ end # class Transition
62
+
63
+
64
+ class TransitionSet
65
+
66
+ def initialize
67
+ @val = {}
68
+ end
69
+
70
+ def include? ( *a )
71
+ case a.size
72
+ when 1
73
+ t = a[0]
74
+ case t
75
+ when Array
76
+ return include?(*t)
77
+ else
78
+ return delta(t.src, t.label) == t.dest
79
+ end
80
+ when 2
81
+ state, label = a
82
+ return ! delta(state, label).nil?
83
+ when 3
84
+ state, label, dest = a
85
+ return delta(state, label) == dest
86
+ else
87
+ raise ArgumentError, 'bad transition'
88
+ end
89
+ end
90
+
91
+ def add ( src, label, dest )
92
+ @val[src] ||= {}
93
+ @val[src][label] = dest
94
+ end
95
+
96
+ def add_transition ( t )
97
+ add(t.src, t.label, t.dest)
98
+ end
99
+
100
+ def delta ( src, label )
101
+ @val[src] ||= {}
102
+ @val[src][label]
103
+ end
104
+
105
+ def << ( transition )
106
+ case transition
107
+ when Array
108
+ add(*transition)
109
+ when Hash
110
+ transition.each do |src, x|
111
+ unless x.is_a? Hash
112
+ raise TypeError, "bad transtion: #{transition.inspect}"
113
+ end
114
+ x.each do |label, dest|
115
+ add(src, label, dest)
116
+ end
117
+ end
118
+ when Transition
119
+ add_transition(transition)
120
+ else
121
+ raise TypeError, "bad transtion: #{transition.inspect}"
122
+ end
123
+ self
124
+ end
125
+
126
+ end # class TransitionSet
127
+
128
+
129
+ attr_accessor :initial, :transitions
130
+
131
+
132
+ def initialize
133
+ @transitions = TransitionSet.new
134
+ @initial = nil
135
+ end
136
+
137
+
138
+ def << ( transition )
139
+ @transitions << transition
140
+ self
141
+ end
142
+
143
+
144
+ def include? ( *transition )
145
+ @transitions.include?(*transition)
146
+ end
147
+
148
+
149
+ def delta ( src, label )
150
+ @transitions.delta(src, label)
151
+ end
152
+
153
+
154
+ def new_flow
155
+ SynFlow.new(self, @initial)
156
+ end
157
+
158
+
159
+ def initial? ( state )
160
+ state == @initial
161
+ end
162
+
163
+ end # class SynFlowFactory
164
+
165
+
166
+ class SynFlow
167
+
168
+ class Error < Exception
169
+ end
170
+
171
+ attr_reader :state
172
+ attr_reader :i
173
+
174
+ @@i = -1
175
+ def initialize ( factory, initial_state )
176
+ @i = (@@i += 1)
177
+ super()
178
+ @mutex = Mutex.new
179
+ @condition = ConditionVariable.new
180
+ @factory = factory
181
+ @state = initial_state
182
+ end
183
+
184
+
185
+ def feed ( label )
186
+ D "#@i: Want read label #{label} (#@state)"
187
+ @mutex.synchronize do
188
+ while not @factory.include?(@state, label)
189
+ begin
190
+ @condition.wait(@mutex)
191
+ rescue ThreadError
192
+ raise Error,
193
+ 'Cannot wait for change state because only one thread is running'
194
+ end
195
+ end
196
+ dest = @factory.delta(@state, label)
197
+ D "#@i: Ok change state with label #{label} (#@state -> #{dest})"
198
+ @state = dest
199
+ @condition.broadcast
200
+ end
201
+ end
202
+
203
+ alias advance feed
204
+ alias << feed
205
+
206
+
207
+ def try_feed ( label )
208
+ D "#@i: Try read label #{label} (#@state)"
209
+ if @mutex.try_lock
210
+ begin
211
+ if @factory.include?(@state, label)
212
+ dest = @factory.delta(@state, label)
213
+ D "#@i: Ok change state with label #{label} (#@state -> #{dest})"
214
+ @state = dest
215
+ @condition.broadcast
216
+ return true
217
+ end
218
+ ensure
219
+ @mutex.unlock
220
+ end
221
+ end
222
+ D "#@i: Ko you cannot change state"
223
+ return false
224
+ end
225
+
226
+ alias try_advance try_feed
227
+
228
+
229
+ def destroy
230
+ @i = @mutex = @condition = @factory = @state = nil
231
+ end
232
+
233
+
234
+ @@out = []
235
+
236
+ def self.debug_out
237
+ @@out
238
+ end
239
+
240
+ def D ( msg )
241
+ # @@out << msg
242
+ # STDERR.puts msg
243
+ end
244
+ private :D
245
+
246
+ end # class SynFlow
247
+
248
+
249
+
250
+ if $0 == __FILE__
251
+
252
+ require 'test/unit'
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