roby 0.7.3 → 0.8.0

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 (236) hide show
  1. data/History.txt +7 -5
  2. data/Manifest.txt +91 -16
  3. data/README.txt +24 -24
  4. data/Rakefile +92 -64
  5. data/app/config/app.yml +42 -43
  6. data/app/config/init.rb +26 -0
  7. data/benchmark/alloc_misc.rb +123 -0
  8. data/benchmark/discovery_latency.rb +67 -0
  9. data/benchmark/garbage_collection.rb +48 -0
  10. data/benchmark/genom.rb +31 -0
  11. data/benchmark/transactions.rb +62 -0
  12. data/bin/roby +1 -1
  13. data/bin/roby-log +16 -6
  14. data/doc/guide/.gitignore +2 -0
  15. data/doc/guide/config.yaml +34 -0
  16. data/doc/guide/ext/init.rb +14 -0
  17. data/doc/guide/ext/previous_next.rb +40 -0
  18. data/doc/guide/ext/rdoc_links.rb +33 -0
  19. data/doc/guide/index.rdoc +16 -0
  20. data/doc/guide/overview.rdoc +62 -0
  21. data/doc/guide/plan_modifications.rdoc +67 -0
  22. data/doc/guide/src/abstraction/achieve_with.page +8 -0
  23. data/doc/guide/src/abstraction/forwarding.page +8 -0
  24. data/doc/guide/src/abstraction/hierarchy.page +19 -0
  25. data/doc/guide/src/abstraction/index.page +28 -0
  26. data/doc/guide/src/abstraction/task_models.page +13 -0
  27. data/doc/guide/src/basics.template +6 -0
  28. data/doc/guide/src/basics/app.page +139 -0
  29. data/doc/guide/src/basics/code_examples.page +33 -0
  30. data/doc/guide/src/basics/dry.page +69 -0
  31. data/doc/guide/src/basics/errors.page +443 -0
  32. data/doc/guide/src/basics/events.page +179 -0
  33. data/doc/guide/src/basics/hierarchy.page +275 -0
  34. data/doc/guide/src/basics/index.page +11 -0
  35. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  36. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  37. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  38. data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
  39. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  40. data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
  41. data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
  42. data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
  43. data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
  44. data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
  45. data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
  46. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  47. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  48. data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
  49. data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
  50. data/doc/guide/src/basics/plan_objects.page +71 -0
  51. data/doc/guide/src/basics/relations_display.page +203 -0
  52. data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
  53. data/doc/guide/src/basics/shell.page +102 -0
  54. data/doc/guide/src/basics/summary.page +32 -0
  55. data/doc/guide/src/basics/tasks.page +357 -0
  56. data/doc/guide/src/basics_shell_header.txt +16 -0
  57. data/doc/guide/src/cycle/cycle-overview.png +0 -0
  58. data/doc/guide/src/cycle/cycle-overview.svg +208 -0
  59. data/doc/guide/src/cycle/error_handling.page +168 -0
  60. data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
  61. data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
  62. data/doc/guide/src/cycle/garbage_collection.page +10 -0
  63. data/doc/guide/src/cycle/index.page +23 -0
  64. data/doc/guide/src/cycle/propagation.page +154 -0
  65. data/doc/guide/src/cycle/propagation_diamond.png +0 -0
  66. data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
  67. data/doc/guide/src/default.css +319 -0
  68. data/doc/guide/src/default.template +74 -0
  69. data/doc/guide/src/htmldoc.metainfo +20 -0
  70. data/doc/guide/src/htmldoc.virtual +18 -0
  71. data/doc/guide/src/images/bodybg.png +0 -0
  72. data/doc/guide/src/images/contbg.png +0 -0
  73. data/doc/guide/src/images/footerbg.png +0 -0
  74. data/doc/guide/src/images/gradient1.png +0 -0
  75. data/doc/guide/src/images/gradient2.png +0 -0
  76. data/doc/guide/src/index.page +7 -0
  77. data/doc/guide/src/introduction/index.page +29 -0
  78. data/doc/guide/src/introduction/install.page +133 -0
  79. data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
  80. data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
  81. data/doc/guide/src/plugins/fault_tolerance.page +44 -0
  82. data/doc/guide/src/plugins/index.page +11 -0
  83. data/doc/guide/src/plugins/subsystems.page +45 -0
  84. data/doc/guide/src/relations/dependency.page +89 -0
  85. data/doc/guide/src/relations/index.page +12 -0
  86. data/doc/misc/update_github +24 -0
  87. data/doc/tutorials/02-GoForward.rdoc +3 -3
  88. data/ext/graph/graph.cc +46 -0
  89. data/lib/roby.rb +57 -22
  90. data/lib/roby/app.rb +132 -112
  91. data/lib/roby/app/plugins/rake.rb +21 -0
  92. data/lib/roby/app/rake.rb +0 -7
  93. data/lib/roby/app/run.rb +1 -1
  94. data/lib/roby/app/scripts/distributed.rb +1 -2
  95. data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
  96. data/lib/roby/app/scripts/results.rb +2 -1
  97. data/lib/roby/app/scripts/run.rb +6 -2
  98. data/lib/roby/app/scripts/shell.rb +11 -11
  99. data/lib/roby/config.rb +1 -1
  100. data/lib/roby/decision_control.rb +62 -3
  101. data/lib/roby/distributed.rb +4 -0
  102. data/lib/roby/distributed/base.rb +8 -0
  103. data/lib/roby/distributed/communication.rb +12 -8
  104. data/lib/roby/distributed/connection_space.rb +61 -44
  105. data/lib/roby/distributed/distributed_object.rb +1 -1
  106. data/lib/roby/distributed/notifications.rb +22 -30
  107. data/lib/roby/distributed/peer.rb +13 -8
  108. data/lib/roby/distributed/proxy.rb +5 -5
  109. data/lib/roby/distributed/subscription.rb +4 -4
  110. data/lib/roby/distributed/transaction.rb +3 -3
  111. data/lib/roby/event.rb +176 -110
  112. data/lib/roby/exceptions.rb +12 -4
  113. data/lib/roby/execution_engine.rb +1604 -0
  114. data/lib/roby/external_process_task.rb +225 -0
  115. data/lib/roby/graph.rb +0 -6
  116. data/lib/roby/interface.rb +221 -137
  117. data/lib/roby/log/console.rb +5 -3
  118. data/lib/roby/log/data_stream.rb +94 -16
  119. data/lib/roby/log/dot.rb +8 -8
  120. data/lib/roby/log/event_stream.rb +13 -3
  121. data/lib/roby/log/file.rb +43 -18
  122. data/lib/roby/log/gui/basic_display_ui.rb +89 -0
  123. data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
  124. data/lib/roby/log/gui/data_displays.rb +4 -5
  125. data/lib/roby/log/gui/data_displays_ui.rb +146 -0
  126. data/lib/roby/log/gui/relations.rb +18 -18
  127. data/lib/roby/log/gui/relations_ui.rb +120 -0
  128. data/lib/roby/log/gui/relations_view_ui.rb +144 -0
  129. data/lib/roby/log/gui/replay.rb +41 -13
  130. data/lib/roby/log/gui/replay_controls.rb +3 -0
  131. data/lib/roby/log/gui/replay_controls.ui +133 -110
  132. data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
  133. data/lib/roby/log/hooks.rb +19 -18
  134. data/lib/roby/log/logger.rb +7 -6
  135. data/lib/roby/log/notifications.rb +4 -4
  136. data/lib/roby/log/plan_rebuilder.rb +20 -22
  137. data/lib/roby/log/relations.rb +44 -16
  138. data/lib/roby/log/server.rb +1 -4
  139. data/lib/roby/log/timings.rb +88 -19
  140. data/lib/roby/plan-object.rb +135 -11
  141. data/lib/roby/plan.rb +408 -224
  142. data/lib/roby/planning/loops.rb +32 -25
  143. data/lib/roby/planning/model.rb +157 -51
  144. data/lib/roby/planning/task.rb +47 -20
  145. data/lib/roby/query.rb +128 -92
  146. data/lib/roby/relations.rb +254 -136
  147. data/lib/roby/relations/conflicts.rb +6 -9
  148. data/lib/roby/relations/dependency.rb +358 -0
  149. data/lib/roby/relations/ensured.rb +0 -1
  150. data/lib/roby/relations/error_handling.rb +0 -1
  151. data/lib/roby/relations/events.rb +0 -2
  152. data/lib/roby/relations/executed_by.rb +26 -11
  153. data/lib/roby/relations/planned_by.rb +14 -14
  154. data/lib/roby/robot.rb +46 -0
  155. data/lib/roby/schedulers/basic.rb +34 -0
  156. data/lib/roby/standalone.rb +4 -0
  157. data/lib/roby/standard_errors.rb +21 -15
  158. data/lib/roby/state/events.rb +5 -4
  159. data/lib/roby/support.rb +107 -6
  160. data/lib/roby/task-operations.rb +23 -19
  161. data/lib/roby/task.rb +522 -148
  162. data/lib/roby/task_index.rb +80 -0
  163. data/lib/roby/test/common.rb +283 -44
  164. data/lib/roby/test/distributed.rb +53 -37
  165. data/lib/roby/test/testcase.rb +9 -204
  166. data/lib/roby/test/tools.rb +3 -3
  167. data/lib/roby/transactions.rb +154 -111
  168. data/lib/roby/transactions/proxy.rb +40 -7
  169. data/manifest.xml +20 -0
  170. data/plugins/fault_injection/README.txt +0 -3
  171. data/plugins/fault_injection/Rakefile +2 -8
  172. data/plugins/fault_injection/app.rb +1 -1
  173. data/plugins/fault_injection/fault_injection.rb +3 -3
  174. data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
  175. data/plugins/subsystems/README.txt +0 -3
  176. data/plugins/subsystems/Rakefile +2 -7
  177. data/plugins/subsystems/app.rb +27 -16
  178. data/plugins/subsystems/test/app/config/init.rb +3 -0
  179. data/plugins/subsystems/test/app/planners/main.rb +1 -1
  180. data/plugins/subsystems/test/app/tasks/services.rb +1 -1
  181. data/plugins/subsystems/test/test_subsystems.rb +23 -16
  182. data/test/distributed/test_communication.rb +32 -15
  183. data/test/distributed/test_connection.rb +28 -26
  184. data/test/distributed/test_execution.rb +59 -54
  185. data/test/distributed/test_mixed_plan.rb +34 -34
  186. data/test/distributed/test_plan_notifications.rb +26 -26
  187. data/test/distributed/test_protocol.rb +57 -48
  188. data/test/distributed/test_query.rb +11 -7
  189. data/test/distributed/test_remote_plan.rb +71 -71
  190. data/test/distributed/test_transaction.rb +50 -47
  191. data/test/mockups/external_process +28 -0
  192. data/test/planning/test_loops.rb +163 -119
  193. data/test/planning/test_model.rb +3 -3
  194. data/test/planning/test_task.rb +27 -7
  195. data/test/relations/test_conflicts.rb +3 -3
  196. data/test/relations/test_dependency.rb +324 -0
  197. data/test/relations/test_ensured.rb +2 -2
  198. data/test/relations/test_executed_by.rb +94 -19
  199. data/test/relations/test_planned_by.rb +11 -9
  200. data/test/suite_core.rb +6 -3
  201. data/test/suite_distributed.rb +1 -0
  202. data/test/suite_planning.rb +1 -0
  203. data/test/suite_relations.rb +2 -2
  204. data/test/tasks/test_external_process.rb +126 -0
  205. data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
  206. data/test/test_bgl.rb +21 -1
  207. data/test/test_event.rb +229 -155
  208. data/test/test_exceptions.rb +79 -80
  209. data/test/test_execution_engine.rb +987 -0
  210. data/test/test_gui.rb +1 -1
  211. data/test/test_interface.rb +11 -5
  212. data/test/test_log.rb +18 -7
  213. data/test/test_log_server.rb +1 -0
  214. data/test/test_plan.rb +229 -395
  215. data/test/test_query.rb +193 -35
  216. data/test/test_relations.rb +88 -8
  217. data/test/test_state.rb +55 -37
  218. data/test/test_support.rb +1 -1
  219. data/test/test_task.rb +371 -218
  220. data/test/test_testcase.rb +32 -16
  221. data/test/test_transactions.rb +211 -170
  222. data/test/test_transactions_proxy.rb +37 -19
  223. metadata +169 -71
  224. data/.gitignore +0 -29
  225. data/doc/styles/allison.css +0 -314
  226. data/doc/styles/allison.js +0 -316
  227. data/doc/styles/allison.rb +0 -276
  228. data/doc/styles/jamis.rb +0 -593
  229. data/lib/roby/control.rb +0 -746
  230. data/lib/roby/executives/simple.rb +0 -30
  231. data/lib/roby/propagation.rb +0 -562
  232. data/lib/roby/relations/hierarchy.rb +0 -239
  233. data/lib/roby/transactions/updates.rb +0 -139
  234. data/test/relations/test_hierarchy.rb +0 -158
  235. data/test/test_control.rb +0 -399
  236. data/test/test_propagation.rb +0 -210
@@ -1,399 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
- require 'roby/test/common'
3
- require 'roby/test/tasks/simple_task'
4
- require 'roby/test/tasks/empty_task'
5
- require 'mockups/tasks'
6
- require 'flexmock'
7
- require 'utilrb/hash/slice'
8
-
9
- class TC_Control < Test::Unit::TestCase
10
- include Roby::Test
11
-
12
- def test_add_framework_errors
13
- # Shut up the logger in this test
14
- Roby.logger.level = Logger::FATAL
15
- exception = begin; raise RuntimeError
16
- rescue; $!
17
- end
18
-
19
- Roby.control.abort_on_application_exception = false
20
- assert_nothing_raised { Propagation.add_framework_error(exception, :exceptions) }
21
-
22
- Roby.control.abort_on_application_exception = true
23
- assert_raises(RuntimeError) { Propagation.add_framework_error(exception, :exceptions) }
24
- end
25
-
26
- def test_event_loop
27
- plan.insert(start_node = EmptyTask.new)
28
- next_event = [ start_node, :start ]
29
- plan.insert(if_node = ChoiceTask.new)
30
- start_node.on(:stop) { next_event = [if_node, :start] }
31
- if_node.on(:stop) { }
32
-
33
- Control.event_processing << lambda do
34
- next unless next_event
35
- task, event = *next_event
36
- next_event = nil
37
- task.event(event).call(nil)
38
- end
39
- process_events
40
- assert(start_node.finished?)
41
-
42
- process_events
43
- assert(if_node.finished?)
44
- end
45
-
46
- def test_every
47
- # Check that every(cycle_length) works fine
48
- Roby.control.run :cycle => 0.1, :detach => true
49
-
50
- samples = []
51
- id = Control.every(0.1) do
52
- samples << Roby.control.cycle_start
53
- end
54
- sleep(1)
55
- Control.remove_periodic_handler(id)
56
- size = samples.size
57
- assert(size > 2, samples.map { |t| t.to_hms })
58
-
59
- samples.each_cons(2) do |a, b|
60
- assert_in_delta(0.1, b - a, 0.001)
61
- end
62
-
63
- # Check that no samples have been added after the 'remove_periodic_handler'
64
- assert_equal(size, samples.size)
65
- end
66
-
67
- def test_once
68
- FlexMock.use do |mock|
69
- Control.once { mock.called }
70
- mock.should_receive(:called).once
71
- process_events
72
- end
73
- FlexMock.use do |mock|
74
- Control.once { mock.called }
75
- mock.should_receive(:called).once
76
- process_events
77
- process_events
78
- end
79
- end
80
-
81
- def test_failing_once
82
- Roby.logger.level = Logger::FATAL
83
- Roby.control.abort_on_exception = true
84
- Roby.control.run :detach => true
85
-
86
- FlexMock.use do |mock|
87
- Control.once { mock.called; raise }
88
- mock.should_receive(:called).once
89
-
90
- assert_raises(ControlQuitError) do
91
- Roby.wait_one_cycle
92
- Roby.control.join
93
- end
94
- end
95
- end
96
-
97
- class SpecificException < RuntimeError; end
98
- def test_unhandled_event_exceptions
99
- Roby.control.abort_on_exception = true
100
-
101
- # Test that the event is not pending if the command raises
102
- model = Class.new(SimpleTask) do
103
- event :start do |context|
104
- raise SpecificException, "bla"
105
- end
106
- end
107
- plan.insert(t = model.new)
108
-
109
- assert_original_error(SpecificException, CommandFailed) { t.start! }
110
- assert(!t.event(:start).pending?)
111
-
112
- # Check that the propagation is pruned if the command raises
113
- t = nil
114
- FlexMock.use do |mock|
115
- t = Class.new(SimpleTask) do
116
- event :start do |context|
117
- mock.command_called
118
- raise SpecificException, "bla"
119
- emit :start
120
- end
121
- on(:start) { |ev| mock.handler_called }
122
- end.new
123
- plan.insert(t)
124
-
125
- mock.should_receive(:command_called).once
126
- mock.should_receive(:handler_called).never
127
-
128
- Control.once { t.start!(nil) }
129
- assert_original_error(SpecificException, CommandFailed) { process_events }
130
- assert(!t.event(:start).pending)
131
- end
132
-
133
- # Check that the task has been garbage collected in the process
134
- assert(! plan.include?(t))
135
- end
136
-
137
- def apply_structure_checking(&block)
138
- Control.structure_checks.clear
139
- Control.structure_checks << lambda(&block)
140
- process_events
141
- ensure
142
- Control.structure_checks.clear
143
- end
144
-
145
- def test_structure_checking
146
- Roby.logger.level = Logger::FATAL
147
- Roby.control.abort_on_exception = false
148
-
149
- # Check on a single task
150
- plan.insert(t = SimpleTask.new)
151
- apply_structure_checking { LocalizedError.new(t) }
152
- assert(! plan.include?(t))
153
-
154
- # Make sure that a task which has been repaired will not be killed
155
- plan.insert(t = SimpleTask.new)
156
- did_once = false
157
- apply_structure_checking do
158
- unless did_once
159
- did_once = true
160
- LocalizedError.new(t)
161
- end
162
- end
163
- assert(plan.include?(t))
164
-
165
- # Check that whole task trees are killed
166
- t0, t1, t2, t3 = prepare_plan :discover => 4
167
- t0.realized_by t2
168
- t1.realized_by t2
169
- t2.realized_by t3
170
-
171
- plan.insert(t0)
172
- plan.insert(t1)
173
- FlexMock.use do |mock|
174
- mock.should_receive(:checking).twice
175
- apply_structure_checking do
176
- mock.checking
177
- LocalizedError.new(t2)
178
- end
179
- end
180
- assert(!plan.include?(t0))
181
- assert(!plan.include?(t1))
182
- assert(!plan.include?(t2))
183
- process_events
184
- assert(!plan.include?(t3))
185
-
186
- # Check that we can kill selectively by returning a hash
187
- t0, t1, t2 = prepare_plan :discover => 3
188
- t0.realized_by t2
189
- t1.realized_by t2
190
- plan.insert(t0)
191
- plan.insert(t1)
192
- apply_structure_checking { { LocalizedError.new(t2) => t0 } }
193
- assert(!plan.include?(t0))
194
- assert(plan.include?(t1))
195
- assert(plan.include?(t2))
196
- end
197
-
198
- def test_at_cycle_end
199
- # Shut up the logger in this test
200
- Roby.logger.level = Logger::FATAL
201
- Roby.control.abort_on_application_exception = false
202
-
203
- FlexMock.use do |mock|
204
- mock.should_receive(:before_error).at_least.once
205
- mock.should_receive(:after_error).never
206
- mock.should_receive(:called).at_least.once
207
-
208
- Control.at_cycle_end do
209
- mock.before_error
210
- raise
211
- mock.after_error
212
- end
213
-
214
- Control.at_cycle_end do
215
- mock.called
216
- unless Roby.control.quitting?
217
- Roby.control.quit
218
- end
219
- end
220
- Roby.control.run
221
- end
222
- end
223
-
224
- def test_inside_outside_control
225
- # First, no control thread
226
- assert(Roby.inside_control?)
227
- assert(Roby.outside_control?)
228
-
229
- # Add a fake control thread
230
- begin
231
- Roby.control.thread = Thread.main
232
- assert(Roby.inside_control?)
233
- assert(!Roby.outside_control?)
234
-
235
- t = Thread.new do
236
- assert(!Roby.inside_control?)
237
- assert(Roby.outside_control?)
238
- end
239
- t.value
240
- ensure
241
- Roby.control.thread = nil
242
- end
243
-
244
- # .. and test with the real one
245
- Roby.control.run :detach => true
246
- Roby.execute do
247
- assert(Roby.inside_control?)
248
- assert(!Roby.outside_control?)
249
- end
250
- assert(!Roby.inside_control?)
251
- assert(Roby.outside_control?)
252
- end
253
-
254
- def test_execute
255
- # Set a fake control thread
256
- Roby.control.thread = Thread.main
257
-
258
- FlexMock.use do |mock|
259
- mock.should_receive(:thread_before).once.ordered
260
- mock.should_receive(:main_before).once.ordered
261
- mock.should_receive(:execute).once.ordered.with(Thread.current).and_return(42)
262
- mock.should_receive(:main_after).once.ordered(:finish)
263
- mock.should_receive(:thread_after).once.ordered(:finish)
264
-
265
- returned_value = nil
266
- t = Thread.new do
267
- mock.thread_before
268
- returned_value = Roby.execute do
269
- mock.execute(Thread.current)
270
- end
271
- mock.thread_after
272
- end
273
-
274
- # Wait for the thread to block
275
- while !t.stop?; sleep(0.1) end
276
- mock.main_before
277
- assert(t.alive?)
278
- process_events
279
- mock.main_after
280
- t.join
281
-
282
- assert_equal(42, returned_value)
283
- end
284
-
285
- ensure
286
- Roby.control.thread = nil
287
- end
288
-
289
- def test_execute_error
290
- assert(!Roby.control.thread)
291
- # Set a fake control thread
292
- Roby.control.thread = Thread.main
293
- assert(!Roby.control.quitting?)
294
-
295
- returned_value = nil
296
- t = Thread.new do
297
- returned_value = begin
298
- Roby.execute do
299
- raise ArgumentError
300
- end
301
- rescue ArgumentError => e
302
- e
303
- end
304
- end
305
-
306
- # Wait for the thread to block
307
- while !t.stop?; sleep(0.1) end
308
- process_events
309
- t.join
310
-
311
- assert_kind_of(ArgumentError, returned_value)
312
- assert(!Roby.control.quitting?)
313
-
314
- ensure
315
- Roby.control.thread = nil
316
- end
317
-
318
- def test_wait_until
319
- # Set a fake control thread
320
- Roby.control.thread = Thread.main
321
-
322
- plan.permanent(task = SimpleTask.new)
323
- t = Thread.new do
324
- Roby.wait_until(task.event(:start)) do
325
- task.start!
326
- end
327
- end
328
-
329
- while !t.stop?; sleep(0.1) end
330
- process_events
331
- assert_nothing_raised { t.value }
332
-
333
- ensure
334
- Roby.control.thread = nil
335
- end
336
-
337
- def test_wait_until_unreachable
338
- # Set a fake control thread
339
- Roby.control.thread = Thread.main
340
-
341
- plan.permanent(task = SimpleTask.new)
342
- t = Thread.new do
343
- begin
344
- Roby.wait_until(task.event(:success)) do
345
- task.start!
346
- task.stop!
347
- end
348
- rescue Exception => e
349
- e
350
- end
351
- end
352
-
353
- while !t.stop?; sleep(0.1) end
354
- process_events
355
-
356
- result = t.value
357
- assert_kind_of(UnreachableEvent, result)
358
- assert_equal(task.event(:success), result.generator)
359
-
360
- ensure
361
- Roby.control.thread = nil
362
- end
363
-
364
- class CaptureLastStats
365
- attr_reader :last_stats
366
- def splat?; true end
367
- def cycle_end(time, stats)
368
- @last_stats = stats
369
- end
370
- end
371
-
372
- def test_stats
373
- Roby.control.run :detach => true, :cycle => 0.1
374
-
375
- capture = CaptureLastStats.new
376
- Roby::Log.add_logger capture
377
-
378
- time_events = [:real_start, :events, :structure_check, :exception_propagation, :exception_fatal, :garbage_collect, :application_errors, :ruby_gc, :sleep, :end]
379
- 10.times do
380
- Roby.control.wait_one_cycle
381
- next unless capture.last_stats
382
-
383
- Roby::Control.synchronize do
384
- timepoints = capture.last_stats.slice(*time_events)
385
- assert(timepoints.all? { |name, d| d > 0 })
386
-
387
- sorted_by_time = timepoints.sort_by { |name, d| d }
388
- sorted_by_name = timepoints.sort_by { |name, d| time_events.index(name) }
389
- sorted_by_time.each_with_index do |(name, d), i|
390
- assert(sorted_by_name[i][1] == d)
391
- end
392
- end
393
- end
394
-
395
- ensure
396
- Roby::Log.remove_logger capture if capture
397
- end
398
- end
399
-
@@ -1,210 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
- require 'roby/test/common'
3
- require 'flexmock'
4
- require 'roby/test/tasks/simple_task'
5
-
6
- class TC_Propagation < Test::Unit::TestCase
7
- include Roby::Test
8
-
9
- def test_gather_propagation
10
- e1, e2, e3 = EventGenerator.new(true), EventGenerator.new(true), EventGenerator.new(true)
11
- plan.discover [e1, e2, e3]
12
-
13
- set = Propagation.gather_propagation do
14
- e1.call(1)
15
- e1.call(4)
16
- e2.emit(2)
17
- e2.emit(3)
18
- e3.call(5)
19
- e3.emit(6)
20
- end
21
- assert_equal({ e1 => [nil, [nil, [1], nil, nil, [4], nil]], e2 => [[nil, [2], nil, nil, [3], nil], nil], e3 => [[nil, [6], nil], [nil, [5], nil]] }, set)
22
- end
23
-
24
- def test_prepare_propagation
25
- g1, g2 = EventGenerator.new(true), EventGenerator.new(true)
26
- ev = Event.new(g2, 0, nil)
27
-
28
- step = [nil, [1], nil, nil, [4], nil]
29
- source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
30
- assert_equal(ValueSet.new, source_events)
31
- assert_equal(ValueSet.new, source_generators)
32
- assert_equal([1, 4], context)
33
-
34
- step = [nil, [], nil, nil, [4], nil]
35
- source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
36
- assert_equal(ValueSet.new, source_events)
37
- assert_equal(ValueSet.new, source_generators)
38
- assert_equal([4], context)
39
-
40
- step = [g1, [], nil, ev, [], nil]
41
- source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
42
- assert_equal([g1, g2].to_value_set, source_generators)
43
- assert_equal([ev].to_value_set, source_events)
44
- assert_equal(nil, context)
45
-
46
- step = [g2, [], nil, ev, [], nil]
47
- source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
48
- assert_equal([g2].to_value_set, source_generators)
49
- assert_equal([ev].to_value_set, source_events)
50
- assert_equal(nil, context)
51
- end
52
-
53
- def test_precedence_graph
54
- e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
55
- Propagation.event_ordering << :bla
56
- Roby.plan.discover e1
57
- Roby.plan.discover e2
58
- assert(Propagation.event_ordering.empty?)
59
-
60
- task = Roby::Task.new
61
- Roby.plan.discover(task)
62
- assert(Propagation.event_ordering.empty?)
63
- assert(EventStructure::Precedence.linked?(task.event(:start), task.event(:updated_data)))
64
-
65
- e1.signal e2
66
- assert(EventStructure::Precedence.linked?(e1, e2))
67
- assert(Propagation.event_ordering.empty?)
68
-
69
- Propagation.event_ordering << :bla
70
- e1.remove_signal e2
71
- assert(Propagation.event_ordering.empty?)
72
- assert(!EventStructure::Precedence.linked?(e1, e2))
73
- end
74
-
75
- def test_next_step
76
- # For the test to be valid, we need +pending+ to have a deterministic ordering
77
- # Fix that here
78
- e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
79
- plan.discover [e1, e2]
80
- pending = [ [e1, [true, nil, nil, nil]], [e2, [false, nil, nil, nil]] ]
81
- def pending.each_key; each { |(k, v)| yield(k) } end
82
- def pending.delete(ev); delete_if { |(k, v)| k == ev } end
83
-
84
- e1.add_precedence e2
85
- assert_equal(e1, Propagation.next_event(pending).first)
86
-
87
- e1.remove_precedence e2
88
- e2.add_precedence e1
89
- assert_equal(e2, Propagation.next_event(pending).first)
90
- end
91
-
92
- def test_delay
93
- plan.insert(t = SimpleTask.new)
94
- e = EventGenerator.new(true)
95
- t.event(:start).on e, :delay => 0.1
96
- Control.once { t.start! }
97
- process_events
98
- assert(!e.happened?)
99
- sleep(0.5)
100
- process_events
101
- assert(e.happened?)
102
- end
103
-
104
- def test_duplicate_signals
105
- plan.insert(t = SimpleTask.new)
106
-
107
- FlexMock.use do |mock|
108
- t.on(:start) { |event| t.emit(:success, *event.context) }
109
- t.on(:start) { |event| t.emit(:success, *event.context) }
110
-
111
- t.on(:success) { |event| mock.success(event.context) }
112
- t.on(:stop) { |event| mock.stop(event.context) }
113
- mock.should_receive(:success).with([42, 42]).once.ordered
114
- mock.should_receive(:stop).with([42, 42]).once.ordered
115
- t.start!(42)
116
- end
117
- end
118
- def test_diamond_structure
119
- a = Class.new(SimpleTask) do
120
- event :child_success
121
- event :child_stop
122
- forward :child_success => :child_stop
123
- end.new(:id => 'a')
124
-
125
- plan.insert(a)
126
- a.realized_by(b = SimpleTask.new(:id => 'b'))
127
-
128
- b.forward(:success, a, :child_success)
129
- b.forward(:stop, a, :child_stop)
130
-
131
- FlexMock.use do |mock|
132
- a.on(:child_stop) { mock.stopped }
133
- mock.should_receive(:stopped).once.ordered
134
- a.start!
135
- b.start!
136
- b.success!
137
- end
138
- end
139
-
140
- def test_signal_forward
141
- forward = EventGenerator.new(true)
142
- signal = EventGenerator.new(true)
143
- plan.discover [forward, signal]
144
-
145
- FlexMock.use do |mock|
146
- sink = EventGenerator.new do |context|
147
- mock.command_called(context)
148
- sink.emit(42)
149
- end
150
- sink.on { |event| mock.handler_called(event.context) }
151
-
152
- forward.forward sink
153
- signal.signal sink
154
-
155
- seed = lambda do
156
- forward.call(24)
157
- signal.call(42)
158
- end
159
- mock.should_receive(:command_called).with([42]).once.ordered
160
- mock.should_receive(:handler_called).with([42, 24]).once.ordered
161
- Propagation.propagate_events([seed])
162
- end
163
- end
164
-
165
- module LogEventGathering
166
- class << self
167
- attr_accessor :mockup
168
- def handle(name, obj)
169
- mockup.send(name, obj, Roby::Propagation.sources) if mockup
170
- end
171
- end
172
-
173
- def signalling(event, to)
174
- super if defined? super
175
- LogEventGathering.handle(:signalling, self)
176
- end
177
- def forwarding(event, to)
178
- super if defined? super
179
- LogEventGathering.handle(:forwarding, self)
180
- end
181
- def emitting(context)
182
- super if defined? super
183
- LogEventGathering.handle(:emitting, self)
184
- end
185
- def calling(context)
186
- super if defined? super
187
- LogEventGathering.handle(:calling, self)
188
- end
189
- end
190
- EventGenerator.include LogEventGathering
191
-
192
- def test_log_events
193
- FlexMock.use do |mock|
194
- LogEventGathering.mockup = mock
195
- dst = EventGenerator.new { }
196
- src = EventGenerator.new { dst.call }
197
- plan.discover [src, dst]
198
-
199
- mock.should_receive(:signalling).never
200
- mock.should_receive(:forwarding).never
201
- mock.should_receive(:calling).with(src, [].to_value_set).once
202
- mock.should_receive(:calling).with(dst, [src].to_value_set).once
203
- src.call
204
- end
205
-
206
- ensure
207
- LogEventGathering.mockup = nil
208
- end
209
- end
210
-