roby 0.7

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 (240) hide show
  1. data/.gitignore +29 -0
  2. data/History.txt +4 -0
  3. data/License-fr.txt +519 -0
  4. data/License.txt +515 -0
  5. data/Manifest.txt +245 -0
  6. data/NOTES +4 -0
  7. data/README.txt +163 -0
  8. data/Rakefile +161 -0
  9. data/TODO.txt +146 -0
  10. data/app/README.txt +24 -0
  11. data/app/Rakefile +8 -0
  12. data/app/config/ROBOT.rb +5 -0
  13. data/app/config/app.yml +91 -0
  14. data/app/config/init.rb +7 -0
  15. data/app/config/roby.yml +3 -0
  16. data/app/controllers/.gitattributes +0 -0
  17. data/app/controllers/ROBOT.rb +2 -0
  18. data/app/data/.gitattributes +0 -0
  19. data/app/planners/ROBOT/main.rb +6 -0
  20. data/app/planners/main.rb +5 -0
  21. data/app/scripts/distributed +3 -0
  22. data/app/scripts/generate/bookmarks +3 -0
  23. data/app/scripts/replay +3 -0
  24. data/app/scripts/results +3 -0
  25. data/app/scripts/run +3 -0
  26. data/app/scripts/server +3 -0
  27. data/app/scripts/shell +3 -0
  28. data/app/scripts/test +3 -0
  29. data/app/tasks/.gitattributes +0 -0
  30. data/app/tasks/ROBOT/.gitattributes +0 -0
  31. data/bin/roby +210 -0
  32. data/bin/roby-log +168 -0
  33. data/bin/roby-shell +25 -0
  34. data/doc/images/event_generalization.png +0 -0
  35. data/doc/images/exception_propagation_1.png +0 -0
  36. data/doc/images/exception_propagation_2.png +0 -0
  37. data/doc/images/exception_propagation_3.png +0 -0
  38. data/doc/images/exception_propagation_4.png +0 -0
  39. data/doc/images/exception_propagation_5.png +0 -0
  40. data/doc/images/replay_handler_error.png +0 -0
  41. data/doc/images/replay_handler_error_0.png +0 -0
  42. data/doc/images/replay_handler_error_1.png +0 -0
  43. data/doc/images/roby_cycle_overview.png +0 -0
  44. data/doc/images/roby_replay_02.png +0 -0
  45. data/doc/images/roby_replay_03.png +0 -0
  46. data/doc/images/roby_replay_04.png +0 -0
  47. data/doc/images/roby_replay_event_representation.png +0 -0
  48. data/doc/images/roby_replay_first_state.png +0 -0
  49. data/doc/images/roby_replay_relations.png +0 -0
  50. data/doc/images/roby_replay_startup.png +0 -0
  51. data/doc/images/task_event_generalization.png +0 -0
  52. data/doc/papers.rdoc +11 -0
  53. data/doc/styles/allison.css +314 -0
  54. data/doc/styles/allison.js +316 -0
  55. data/doc/styles/allison.rb +276 -0
  56. data/doc/styles/jamis.rb +593 -0
  57. data/doc/tutorials/01-GettingStarted.rdoc +86 -0
  58. data/doc/tutorials/02-GoForward.rdoc +220 -0
  59. data/doc/tutorials/03-PlannedPath.rdoc +268 -0
  60. data/doc/tutorials/04-EventPropagation.rdoc +236 -0
  61. data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
  62. data/doc/tutorials/06-Overview.rdoc +40 -0
  63. data/doc/videos.rdoc +69 -0
  64. data/ext/droby/dump.cc +175 -0
  65. data/ext/droby/extconf.rb +3 -0
  66. data/ext/graph/algorithm.cc +746 -0
  67. data/ext/graph/extconf.rb +7 -0
  68. data/ext/graph/graph.cc +529 -0
  69. data/ext/graph/graph.hh +183 -0
  70. data/ext/graph/iterator_sequence.hh +102 -0
  71. data/ext/graph/undirected_dfs.hh +226 -0
  72. data/ext/graph/undirected_graph.hh +421 -0
  73. data/lib/roby.rb +41 -0
  74. data/lib/roby/app.rb +870 -0
  75. data/lib/roby/app/rake.rb +56 -0
  76. data/lib/roby/app/run.rb +14 -0
  77. data/lib/roby/app/scripts/distributed.rb +13 -0
  78. data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
  79. data/lib/roby/app/scripts/replay.rb +31 -0
  80. data/lib/roby/app/scripts/results.rb +15 -0
  81. data/lib/roby/app/scripts/run.rb +26 -0
  82. data/lib/roby/app/scripts/server.rb +18 -0
  83. data/lib/roby/app/scripts/shell.rb +88 -0
  84. data/lib/roby/app/scripts/test.rb +40 -0
  85. data/lib/roby/basic_object.rb +151 -0
  86. data/lib/roby/config.rb +5 -0
  87. data/lib/roby/control.rb +747 -0
  88. data/lib/roby/decision_control.rb +17 -0
  89. data/lib/roby/distributed.rb +32 -0
  90. data/lib/roby/distributed/base.rb +440 -0
  91. data/lib/roby/distributed/communication.rb +871 -0
  92. data/lib/roby/distributed/connection_space.rb +592 -0
  93. data/lib/roby/distributed/distributed_object.rb +206 -0
  94. data/lib/roby/distributed/drb.rb +62 -0
  95. data/lib/roby/distributed/notifications.rb +539 -0
  96. data/lib/roby/distributed/peer.rb +550 -0
  97. data/lib/roby/distributed/protocol.rb +529 -0
  98. data/lib/roby/distributed/proxy.rb +343 -0
  99. data/lib/roby/distributed/subscription.rb +311 -0
  100. data/lib/roby/distributed/transaction.rb +498 -0
  101. data/lib/roby/event.rb +897 -0
  102. data/lib/roby/exceptions.rb +234 -0
  103. data/lib/roby/executives/simple.rb +30 -0
  104. data/lib/roby/graph.rb +166 -0
  105. data/lib/roby/interface.rb +390 -0
  106. data/lib/roby/log.rb +3 -0
  107. data/lib/roby/log/chronicle.rb +303 -0
  108. data/lib/roby/log/console.rb +72 -0
  109. data/lib/roby/log/data_stream.rb +197 -0
  110. data/lib/roby/log/dot.rb +279 -0
  111. data/lib/roby/log/event_stream.rb +151 -0
  112. data/lib/roby/log/file.rb +340 -0
  113. data/lib/roby/log/gui/basic_display.ui +83 -0
  114. data/lib/roby/log/gui/chronicle.rb +26 -0
  115. data/lib/roby/log/gui/chronicle_view.rb +40 -0
  116. data/lib/roby/log/gui/chronicle_view.ui +70 -0
  117. data/lib/roby/log/gui/data_displays.rb +172 -0
  118. data/lib/roby/log/gui/data_displays.ui +155 -0
  119. data/lib/roby/log/gui/notifications.rb +26 -0
  120. data/lib/roby/log/gui/relations.rb +248 -0
  121. data/lib/roby/log/gui/relations.ui +123 -0
  122. data/lib/roby/log/gui/relations_view.rb +185 -0
  123. data/lib/roby/log/gui/relations_view.ui +149 -0
  124. data/lib/roby/log/gui/replay.rb +327 -0
  125. data/lib/roby/log/gui/replay_controls.rb +200 -0
  126. data/lib/roby/log/gui/replay_controls.ui +259 -0
  127. data/lib/roby/log/gui/runtime.rb +130 -0
  128. data/lib/roby/log/hooks.rb +185 -0
  129. data/lib/roby/log/logger.rb +202 -0
  130. data/lib/roby/log/notifications.rb +244 -0
  131. data/lib/roby/log/plan_rebuilder.rb +470 -0
  132. data/lib/roby/log/relations.rb +1056 -0
  133. data/lib/roby/log/server.rb +550 -0
  134. data/lib/roby/log/sqlite.rb +47 -0
  135. data/lib/roby/log/timings.rb +164 -0
  136. data/lib/roby/plan-object.rb +247 -0
  137. data/lib/roby/plan.rb +762 -0
  138. data/lib/roby/planning.rb +13 -0
  139. data/lib/roby/planning/loops.rb +302 -0
  140. data/lib/roby/planning/model.rb +906 -0
  141. data/lib/roby/planning/task.rb +151 -0
  142. data/lib/roby/propagation.rb +562 -0
  143. data/lib/roby/query.rb +619 -0
  144. data/lib/roby/relations.rb +583 -0
  145. data/lib/roby/relations/conflicts.rb +70 -0
  146. data/lib/roby/relations/ensured.rb +20 -0
  147. data/lib/roby/relations/error_handling.rb +23 -0
  148. data/lib/roby/relations/events.rb +9 -0
  149. data/lib/roby/relations/executed_by.rb +193 -0
  150. data/lib/roby/relations/hierarchy.rb +239 -0
  151. data/lib/roby/relations/influence.rb +10 -0
  152. data/lib/roby/relations/planned_by.rb +63 -0
  153. data/lib/roby/robot.rb +7 -0
  154. data/lib/roby/standard_errors.rb +218 -0
  155. data/lib/roby/state.rb +5 -0
  156. data/lib/roby/state/events.rb +221 -0
  157. data/lib/roby/state/information.rb +55 -0
  158. data/lib/roby/state/pos.rb +110 -0
  159. data/lib/roby/state/shapes.rb +32 -0
  160. data/lib/roby/state/state.rb +353 -0
  161. data/lib/roby/support.rb +92 -0
  162. data/lib/roby/task-operations.rb +182 -0
  163. data/lib/roby/task.rb +1618 -0
  164. data/lib/roby/test/common.rb +399 -0
  165. data/lib/roby/test/distributed.rb +214 -0
  166. data/lib/roby/test/tasks/empty_task.rb +9 -0
  167. data/lib/roby/test/tasks/goto.rb +36 -0
  168. data/lib/roby/test/tasks/simple_task.rb +23 -0
  169. data/lib/roby/test/testcase.rb +519 -0
  170. data/lib/roby/test/tools.rb +160 -0
  171. data/lib/roby/thread_task.rb +87 -0
  172. data/lib/roby/transactions.rb +462 -0
  173. data/lib/roby/transactions/proxy.rb +292 -0
  174. data/lib/roby/transactions/updates.rb +139 -0
  175. data/plugins/fault_injection/History.txt +4 -0
  176. data/plugins/fault_injection/README.txt +37 -0
  177. data/plugins/fault_injection/Rakefile +18 -0
  178. data/plugins/fault_injection/TODO.txt +0 -0
  179. data/plugins/fault_injection/app.rb +52 -0
  180. data/plugins/fault_injection/fault_injection.rb +89 -0
  181. data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
  182. data/plugins/subsystems/README.txt +40 -0
  183. data/plugins/subsystems/Rakefile +18 -0
  184. data/plugins/subsystems/app.rb +171 -0
  185. data/plugins/subsystems/test/app/README +24 -0
  186. data/plugins/subsystems/test/app/Rakefile +8 -0
  187. data/plugins/subsystems/test/app/config/app.yml +71 -0
  188. data/plugins/subsystems/test/app/config/init.rb +9 -0
  189. data/plugins/subsystems/test/app/config/roby.yml +3 -0
  190. data/plugins/subsystems/test/app/planners/main.rb +20 -0
  191. data/plugins/subsystems/test/app/scripts/distributed +3 -0
  192. data/plugins/subsystems/test/app/scripts/replay +3 -0
  193. data/plugins/subsystems/test/app/scripts/results +3 -0
  194. data/plugins/subsystems/test/app/scripts/run +3 -0
  195. data/plugins/subsystems/test/app/scripts/server +3 -0
  196. data/plugins/subsystems/test/app/scripts/shell +3 -0
  197. data/plugins/subsystems/test/app/scripts/test +3 -0
  198. data/plugins/subsystems/test/app/tasks/services.rb +15 -0
  199. data/plugins/subsystems/test/test_subsystems.rb +71 -0
  200. data/test/distributed/test_communication.rb +178 -0
  201. data/test/distributed/test_connection.rb +282 -0
  202. data/test/distributed/test_execution.rb +373 -0
  203. data/test/distributed/test_mixed_plan.rb +341 -0
  204. data/test/distributed/test_plan_notifications.rb +238 -0
  205. data/test/distributed/test_protocol.rb +516 -0
  206. data/test/distributed/test_query.rb +102 -0
  207. data/test/distributed/test_remote_plan.rb +491 -0
  208. data/test/distributed/test_transaction.rb +463 -0
  209. data/test/mockups/tasks.rb +27 -0
  210. data/test/planning/test_loops.rb +380 -0
  211. data/test/planning/test_model.rb +427 -0
  212. data/test/planning/test_task.rb +106 -0
  213. data/test/relations/test_conflicts.rb +42 -0
  214. data/test/relations/test_ensured.rb +38 -0
  215. data/test/relations/test_executed_by.rb +149 -0
  216. data/test/relations/test_hierarchy.rb +158 -0
  217. data/test/relations/test_planned_by.rb +54 -0
  218. data/test/suite_core.rb +24 -0
  219. data/test/suite_distributed.rb +9 -0
  220. data/test/suite_planning.rb +3 -0
  221. data/test/suite_relations.rb +8 -0
  222. data/test/test_bgl.rb +508 -0
  223. data/test/test_control.rb +399 -0
  224. data/test/test_event.rb +894 -0
  225. data/test/test_exceptions.rb +592 -0
  226. data/test/test_interface.rb +37 -0
  227. data/test/test_log.rb +114 -0
  228. data/test/test_log_server.rb +132 -0
  229. data/test/test_plan.rb +584 -0
  230. data/test/test_propagation.rb +210 -0
  231. data/test/test_query.rb +266 -0
  232. data/test/test_relations.rb +180 -0
  233. data/test/test_state.rb +414 -0
  234. data/test/test_support.rb +16 -0
  235. data/test/test_task.rb +938 -0
  236. data/test/test_testcase.rb +122 -0
  237. data/test/test_thread_task.rb +73 -0
  238. data/test/test_transactions.rb +569 -0
  239. data/test/test_transactions_proxy.rb +198 -0
  240. metadata +570 -0
@@ -0,0 +1,106 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/planning'
4
+
5
+ require 'flexmock'
6
+ require 'roby/test/tasks/simple_task'
7
+
8
+ class TC_PlanningTask < Test::Unit::TestCase
9
+ include Roby::Planning
10
+ include Roby::Test
11
+
12
+ def planning_task_result(planning_task)
13
+ assert(planning_task)
14
+ plan.permanent(planning_task)
15
+ planning_task.start! if planning_task.pending?
16
+ planning_task.thread.join
17
+ process_events
18
+ assert(planning_task.success?, planning_task.terminal_event.context)
19
+ planning_task.planned_task
20
+ end
21
+
22
+ def test_planning_task_one_shot
23
+ result_task = SimpleTask.new
24
+ planner = Class.new(Planning::Planner) do
25
+ method(:task) do
26
+ raise arguments.to_s unless arguments[:bla] == 42
27
+ raise arguments.to_s unless arguments[:blo] == 84
28
+ raise arguments.to_s unless arguments[:context] == [42]
29
+ result_task
30
+ end
31
+ end
32
+
33
+ planning_task = PlanningTask.new(:planner_model => planner, :method_name => :task,
34
+ :method_options => { :bla => 42 },
35
+ :blo => 84)
36
+ plan.insert(planned_task = Task.new)
37
+ planned_task.planned_by planning_task
38
+
39
+ planning_task.start!(42)
40
+ FlexMock.use do |mock|
41
+ planning_task.on(:success) do
42
+ mock.planned_task(planning_task.planned_task)
43
+ planning_task.planned_task.start!
44
+ end
45
+ mock.should_receive(:planned_task).with(result_task).once
46
+ planning_task.thread.join
47
+ process_events
48
+ end
49
+
50
+ plan_task = plan.missions.find { true }
51
+ assert_equal(result_task, plan_task)
52
+ assert_equal(result_task, planning_task.planned_task)
53
+ end
54
+
55
+ def test_planning_interruption
56
+ Thread.abort_on_exception = false
57
+ started, normal_finish = nil
58
+ planner = Class.new(Planning::Planner) do
59
+ method(:interruptible) do
60
+ started = true
61
+ 10.times do
62
+ sleep 0.1
63
+ interruption_point
64
+ end
65
+ normal_finish = true
66
+ end
67
+ end
68
+
69
+ planning_task = PlanningTask.new(:planner_model => planner, :method_name => :interruptible)
70
+ plan.permanent(planning_task)
71
+ planning_task.start!
72
+ loop { sleep 0.1 ; break if started }
73
+ planning_task.stop!
74
+ loop do
75
+ begin
76
+ process_events
77
+ rescue Interrupt
78
+ end
79
+ break unless planning_task.running?
80
+ end
81
+ assert(!normal_finish)
82
+ end
83
+
84
+ def test_replan_task
85
+ planner = Class.new(Planning::Planner) do
86
+ method(:test_task) do
87
+ result_task = SimpleTask.new(:id => arguments[:task_id])
88
+ result_task.realized_by replan_task(:task_id => arguments[:task_id] + 1)
89
+ plan.permanent(result_task)
90
+ result_task
91
+ end
92
+ end.new(plan)
93
+
94
+ plan.permanent(task = planner.test_task(:task_id => 100))
95
+ assert_kind_of(SimpleTask, task)
96
+ assert_equal(100, task.arguments[:id])
97
+
98
+ assert(planning_task = task.enum_child_objects(Roby::TaskStructure::Hierarchy).to_a.first)
99
+ assert_kind_of(PlanningTask, planning_task)
100
+ assert(planning_task.pending?)
101
+
102
+ new_task = planning_task_result(planning_task)
103
+ assert_kind_of(SimpleTask, new_task, planning_task)
104
+ assert_equal(101, new_task.arguments[:id])
105
+ end
106
+ end
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
2
+
3
+ require 'roby/test/common'
4
+ require 'roby/test/tasks/simple_task'
5
+ require 'roby/relations/conflicts'
6
+ require 'flexmock'
7
+
8
+ class TC_Conflicts < Test::Unit::TestCase
9
+ include Roby::Test
10
+
11
+ def test_model_relations
12
+ m1, m2 = (1..2).map do
13
+ Class.new(SimpleTask)
14
+ end
15
+
16
+ m1.conflicts_with m2
17
+ assert(!m1.conflicts_with?(m1))
18
+ assert(m1.conflicts_with?(m2))
19
+ assert(m2.conflicts_with?(m1))
20
+
21
+ # Create two tasks ...
22
+ plan.discover(t1 = m1.new)
23
+ plan.discover(t2 = m2.new)
24
+ assert !t1.child_object?(t2, Roby::TaskStructure::Conflicts)
25
+ assert !t2.child_object?(t1, Roby::TaskStructure::Conflicts)
26
+
27
+ # Start t1 ...
28
+ t1.start!
29
+ assert !t1.child_object?(t2, Roby::TaskStructure::Conflicts)
30
+ assert t2.child_object?(t1, Roby::TaskStructure::Conflicts)
31
+
32
+ # And now, start the conflicting task. The default decision control
33
+ # should postpone start until t1 is stopped
34
+ t2.start!
35
+ assert(!t2.running?)
36
+ assert t1.event(:stop).child_object?(t2.event(:start), Roby::EventStructure::Signal)
37
+ t1.stop!
38
+ assert(!t1.running?)
39
+ assert(t2.running?)
40
+ end
41
+ end
42
+
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'flexmock'
4
+
5
+ class TC_EnsuredEvent < Test::Unit::TestCase
6
+ include Roby::Test
7
+
8
+ def test_ensure
9
+ setup = lambda do |mock|
10
+ e1, e2 = EventGenerator.new(true), Roby::EventGenerator.new(true)
11
+ plan.discover [e1, e2]
12
+ e1.ensure e2
13
+ e1.on { mock.e1 }
14
+ e2.on { mock.e2 }
15
+ [e1, e2]
16
+ end
17
+ FlexMock.use do |mock|
18
+ e1, e2 = setup[mock]
19
+ mock.should_receive(:e2).ordered.once
20
+ mock.should_receive(:e1).ordered.once
21
+ e1.call(nil)
22
+ end
23
+ FlexMock.use do |mock|
24
+ e1, e2 = setup[mock]
25
+ mock.should_receive(:e1).never
26
+ mock.should_receive(:e2).once
27
+ e2.call(nil)
28
+ end
29
+ FlexMock.use do |mock|
30
+ e1, e2 = setup[mock]
31
+ mock.should_receive(:e2).ordered.once
32
+ mock.should_receive(:e1).ordered.once
33
+ e2.call(nil)
34
+ e1.call(nil)
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,149 @@
1
+ $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/tasks/simple_task'
4
+ require 'flexmock'
5
+
6
+ class TC_ExecutedBy < Test::Unit::TestCase
7
+ include Roby::Test
8
+
9
+ class ExecutionAgentModel < SimpleTask
10
+ event :ready
11
+ forward :start => :ready
12
+ end
13
+
14
+ def test_relationships
15
+ plan.discover(task = SimpleTask.new)
16
+ exec_task = ExecutionAgentModel.new
17
+
18
+ task.executed_by exec_task
19
+ assert_equal(exec_task, task.execution_agent)
20
+ end
21
+
22
+ def test_inherits_execution_model
23
+ model = Class.new(Roby::Task) do
24
+ executed_by ExecutionAgentModel
25
+ end
26
+ submodel = Class.new(model)
27
+
28
+ assert_equal(ExecutionAgentModel, submodel.execution_agent)
29
+ end
30
+
31
+ def test_nominal
32
+ plan.discover(task = SimpleTask.new)
33
+ task.executed_by(ExecutionAgentModel.new)
34
+ task.executed_by(exec = ExecutionAgentModel.new)
35
+
36
+ FlexMock.use do |mock|
37
+ exec.on(:start) { mock.agent_started }
38
+ exec.on(:ready) { mock.agent_ready }
39
+ task.on(:start) { mock.task_started }
40
+
41
+ mock.should_receive(:agent_started).once.ordered
42
+ mock.should_receive(:agent_ready).once.ordered
43
+ mock.should_receive(:task_started).once.ordered
44
+ task.start!
45
+ end
46
+
47
+ task.stop!
48
+ assert_nothing_raised { exec.stop! }
49
+ end
50
+
51
+ def test_agent_fails
52
+ plan.discover(task = SimpleTask.new)
53
+ exec = ExecutionAgentModel.new
54
+ task.executed_by exec
55
+ task.start!
56
+
57
+ FlexMock.use do |mock|
58
+ task.on(:aborted) { mock.aborted }
59
+ mock.should_receive(:aborted).once
60
+ exec.stop!
61
+ end
62
+ assert(!task.running?)
63
+ end
64
+
65
+ def test_agent_start_failed
66
+ plan.insert(task = SimpleTask.new)
67
+ exec = Class.new(SimpleTask) do
68
+ event :ready
69
+ on :start => :failed
70
+ end.new
71
+ task.executed_by exec
72
+
73
+ assert_original_error(NilClass, EmissionFailed) { task.start! }
74
+ assert(!task.running?)
75
+ assert(!exec.running?)
76
+ assert(exec.finished?)
77
+ end
78
+
79
+ def test_agent_model
80
+ task_model = Class.new(SimpleTask)
81
+
82
+ task_model.executed_by ExecutionAgentModel
83
+ plan.insert(task = task_model.new)
84
+ assert(task.execution_agent)
85
+ assert(ExecutionAgentModel, task.execution_agent.class)
86
+
87
+ task.start!
88
+ assert(task.running?)
89
+ assert(task.execution_agent.running?)
90
+ end
91
+
92
+ def test_respawn
93
+ task_model = Class.new(SimpleTask)
94
+ task_model.executed_by ExecutionAgentModel
95
+ first, second = prepare_plan :discover => 2, :model => task_model
96
+ assert(first.execution_agent)
97
+ assert(ExecutionAgentModel, first.execution_agent.class)
98
+ assert(second.execution_agent)
99
+ assert(ExecutionAgentModel, second.execution_agent.class)
100
+ assert_same(first.execution_agent, second.execution_agent)
101
+
102
+ first.start!
103
+ assert(first.running?)
104
+ first_agent = first.execution_agent
105
+ assert(first_agent.running?)
106
+
107
+ plan.discover(third = task_model.new)
108
+ assert_equal(first.execution_agent, third.execution_agent)
109
+
110
+ first.execution_agent.stop!
111
+ assert(first.event(:aborted).happened?)
112
+ assert(first_agent.finished?)
113
+ assert(second.execution_agent)
114
+ assert(second.execution_agent.pending?)
115
+ end
116
+
117
+ def test_cannot_respawn
118
+ plan.insert(task = Class.new(SimpleTask).new)
119
+ task.executed_by(agent = ExecutionAgentModel.new)
120
+
121
+ agent.start!
122
+ agent.stop!
123
+ assert_raises(CommandFailed) { task.start! }
124
+ end
125
+
126
+ def test_initialization
127
+ agent = Class.new(SimpleTask) do
128
+ event :ready, :command => true
129
+ end.new
130
+ task, (init1, init2) = prepare_plan :missions => 1, :discover => 2, :model => SimpleTask
131
+ task.executed_by agent
132
+ init1.executed_by agent
133
+ init2.executed_by agent
134
+
135
+ agent.realized_by(init = (init1 + init2))
136
+ agent.on(:start, init, :start)
137
+ init.forward(:success, agent, :ready)
138
+
139
+ task.start!
140
+ assert(!task.running?)
141
+ assert(!agent.event(:ready).happened?)
142
+ assert(init1.running?)
143
+ assert(!init2.running?)
144
+ init1.success!
145
+ init2.success!
146
+ assert(agent.event(:ready).happened?)
147
+ end
148
+ end
149
+
@@ -0,0 +1,158 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/tasks/simple_task'
4
+
5
+ class TC_RealizedBy < Test::Unit::TestCase
6
+ include Roby::Test
7
+
8
+ def test_definition
9
+ tag = TaskModelTag.new
10
+ klass = Class.new(SimpleTask) do
11
+ argument :id
12
+ include tag
13
+ end
14
+ plan.discover(t1 = SimpleTask.new)
15
+
16
+ # Check validation of the model
17
+ child = nil
18
+ assert_nothing_raised { t1.realized_by((child = klass.new), :model => SimpleTask) }
19
+
20
+ assert_same(Hierarchy.interesting_events, EventGenerator.event_gathering[child.event(:success)].find { true })
21
+ assert_same(Hierarchy.interesting_events, EventGenerator.event_gathering[child.event(:failed)].find { true })
22
+ assert_equal([SimpleTask, {}], t1[child, Hierarchy][:model])
23
+
24
+ assert_nothing_raised { t1.realized_by klass.new, :model => [Roby::Task, {}] }
25
+ assert_nothing_raised { t1.realized_by klass.new, :model => tag }
26
+
27
+ plan.discover(simple_task = SimpleTask.new)
28
+ assert_raises(ArgumentError) { t1.realized_by simple_task, :model => [Class.new(Roby::Task), {}] }
29
+ assert_raises(ArgumentError) { t1.realized_by simple_task, :model => TaskModelTag.new }
30
+
31
+ # Check validation of the arguments
32
+ plan.discover(model_task = klass.new)
33
+ assert_raises(ArgumentError) { t1.realized_by model_task, :model => [SimpleTask, {:id => 'bad'}] }
34
+
35
+ plan.discover(child = klass.new(:id => 'good'))
36
+ assert_raises(ArgumentError) { t1.realized_by child, :model => [klass, {:id => 'bad'}] }
37
+ assert_nothing_raised { t1.realized_by child, :model => [klass, {:id => 'good'}] }
38
+ assert_equal([klass, { :id => 'good' }], t1[child, TaskStructure::Hierarchy][:model])
39
+
40
+ # Check edge annotation
41
+ t2 = SimpleTask.new
42
+ t1.realized_by t2, :model => SimpleTask
43
+ assert_equal([SimpleTask, {}], t1[t2, TaskStructure::Hierarchy][:model])
44
+ t2 = klass.new(:id => 10)
45
+ t1.realized_by t2, :model => [klass, { :id => 10 }]
46
+ end
47
+
48
+ Hierarchy = TaskStructure::Hierarchy
49
+
50
+ def assert_children_failed(children, plan)
51
+ result = Hierarchy.check_structure(plan)
52
+ assert_equal(children.to_set, result.map { |e| e.failed_task }.to_set)
53
+ end
54
+
55
+ def test_failure_point
56
+ model = Class.new(SimpleTask) do
57
+ event :specialized_failure, :command => true
58
+ forward :specialized_failure => :failed
59
+ end
60
+ parent, child = prepare_plan :discover => 1, :tasks => 1, :model => model
61
+ parent.realized_by child
62
+
63
+ parent.start!
64
+ child.start!
65
+ child.specialized_failure!
66
+
67
+ error = Hierarchy.check_structure(plan).first.exception
68
+ assert_kind_of(ChildFailedError, error)
69
+ assert_equal(child.event(:specialized_failure).last, error.failure_point)
70
+ assert_equal(child.event(:specialized_failure).last, error.failed_event)
71
+
72
+ parent.stop!
73
+ end
74
+
75
+ def test_exception_printing
76
+ parent, child = prepare_plan :discover => 2, :model => SimpleTask
77
+ parent.realized_by child
78
+ parent.start!
79
+ child.start!
80
+ child.failed!
81
+
82
+ error = Hierarchy.check_structure(plan).first.exception
83
+ assert_kind_of(ChildFailedError, error)
84
+ assert_nothing_raised do
85
+ Roby.format_exception(error)
86
+ end
87
+
88
+ parent.stop!
89
+ end
90
+
91
+ def test_structure_checking
92
+ child_model = Class.new(SimpleTask) do
93
+ event :first, :command => true
94
+ event :second, :command => true
95
+ end
96
+
97
+ p1 = SimpleTask.new
98
+ child = child_model.new
99
+ plan.discover([p1, child])
100
+ p1.realized_by child
101
+ plan.insert(p1)
102
+
103
+ child.start!; p1.start!
104
+ assert_equal([], Hierarchy.check_structure(plan))
105
+ child.stop!
106
+ assert_equal([child.event(:failed).last], Hierarchy.interesting_events)
107
+ assert_children_failed([child], plan)
108
+
109
+ plan.clear
110
+ p1 = SimpleTask.new
111
+ child = child_model.new
112
+ plan.discover([p1, child])
113
+ p1.realized_by child, :success => [:second], :failure => [:first]
114
+ plan.insert(p1)
115
+ child.start! ; p1.start!
116
+ child.event(:first).emit(nil)
117
+ assert_children_failed([child], plan)
118
+
119
+ plan.clear
120
+ p1 = SimpleTask.new
121
+ child = child_model.new
122
+ plan.discover([p1, child])
123
+ p1.realized_by child, :success => [:first], :failure => [:second]
124
+ plan.insert(p1)
125
+ child.start! ; p1.start!
126
+ child.event(:first).emit(nil)
127
+ assert_children_failed([], plan)
128
+ child.event(:second).emit(nil)
129
+ assert_children_failed([], plan)
130
+ end
131
+
132
+ def test_fullfilled_model
133
+ tag = TaskModelTag.new
134
+ klass = Class.new(SimpleTask) do
135
+ include tag
136
+ end
137
+
138
+ p1, p2, child = prepare_plan :discover => 3, :model => klass
139
+
140
+ p1.realized_by child, :model => SimpleTask
141
+ p2.realized_by child, :model => Roby::Task
142
+ assert_equal([[SimpleTask], {}], child.fullfilled_model)
143
+ p1.remove_child(child)
144
+ assert_equal([[Roby::Task], {}], child.fullfilled_model)
145
+ p1.realized_by child, :model => tag
146
+ assert_equal([[Roby::Task, tag], {}], child.fullfilled_model)
147
+ end
148
+
149
+ def test_first_children
150
+ p, c1, c2 = prepare_plan :discover => 3, :model => SimpleTask
151
+ p.realized_by c1
152
+ p.realized_by c2
153
+ assert_equal([c1, c2].to_value_set, p.first_children)
154
+
155
+ c1.on(:start, c2, :start)
156
+ assert_equal([c1].to_value_set, p.first_children)
157
+ end
158
+ end