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,4 +1,4 @@
1
- $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
1
+ $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), File.dirname(__FILE__))
2
2
 
3
3
  require 'roby/test/common'
4
4
  require 'roby/test/tasks/simple_task'
@@ -19,8 +19,8 @@ class TC_Conflicts < Test::Unit::TestCase
19
19
  assert(m2.conflicts_with?(m1))
20
20
 
21
21
  # Create two tasks ...
22
- plan.discover(t1 = m1.new)
23
- plan.discover(t2 = m2.new)
22
+ plan.add(t1 = m1.new)
23
+ plan.add(t2 = m2.new)
24
24
  assert !t1.child_object?(t2, Roby::TaskStructure::Conflicts)
25
25
  assert !t2.child_object?(t1, Roby::TaskStructure::Conflicts)
26
26
 
@@ -0,0 +1,324 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), 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_check_structure_registration
9
+ assert plan.structure_checks.include?(Dependency.method(:check_structure))
10
+ end
11
+
12
+ def test_definition
13
+ tag = TaskModelTag.new
14
+ klass = Class.new(SimpleTask) do
15
+ argument :id
16
+ include tag
17
+ end
18
+ plan.add(t1 = SimpleTask.new)
19
+
20
+ # Check validation of the model
21
+ child = nil
22
+ assert_nothing_raised { t1.depends_on((child = klass.new), :model => SimpleTask) }
23
+ assert_equal([SimpleTask, {}], t1[child, Dependency][:model])
24
+
25
+ assert_nothing_raised { t1.depends_on klass.new, :model => [Roby::Task, {}] }
26
+ assert_nothing_raised { t1.depends_on klass.new, :model => tag }
27
+
28
+ plan.add(simple_task = SimpleTask.new)
29
+ assert_raises(ArgumentError) { t1.depends_on simple_task, :model => [Class.new(Roby::Task), {}] }
30
+ assert_raises(ArgumentError) { t1.depends_on simple_task, :model => TaskModelTag.new }
31
+
32
+ # Check validation of the arguments
33
+ plan.add(model_task = klass.new)
34
+ assert_raises(ArgumentError) { t1.depends_on model_task, :model => [SimpleTask, {:id => 'bad'}] }
35
+
36
+ plan.add(child = klass.new(:id => 'good'))
37
+ assert_raises(ArgumentError) { t1.depends_on child, :model => [klass, {:id => 'bad'}] }
38
+ assert_nothing_raised { t1.depends_on child, :model => [klass, {:id => 'good'}] }
39
+ assert_equal([klass, { :id => 'good' }], t1[child, TaskStructure::Dependency][:model])
40
+
41
+ # Check edge annotation
42
+ t2 = SimpleTask.new
43
+ t1.depends_on t2, :model => SimpleTask
44
+ assert_equal([SimpleTask, {}], t1[t2, TaskStructure::Dependency][:model])
45
+ t2 = klass.new(:id => 10)
46
+ t1.depends_on t2, :model => [klass, { :id => 10 }]
47
+ end
48
+
49
+ Dependency = TaskStructure::Dependency
50
+
51
+ def test_exception_printing
52
+ parent, child = prepare_plan :add => 2, :model => SimpleTask
53
+ parent.depends_on child
54
+ parent.start!
55
+ child.start!
56
+ child.failed!
57
+
58
+ error = plan.check_structure.find { true }[0].exception
59
+ assert_kind_of(ChildFailedError, error)
60
+ assert_nothing_raised do
61
+ Roby.format_exception(error)
62
+ end
63
+
64
+ parent.stop!
65
+ end
66
+
67
+ # This method is a common method used in the various error/nominal tests
68
+ # below. It creates two tasks:
69
+ # p1 which is an instance of SimpleTask
70
+ # child which is an instance of a task model with two controllable events
71
+ # 'first' and 'second'
72
+ #
73
+ # p1 is a parent of child. Both tasks are started and returned.
74
+ def create_pair(options)
75
+ child_model = Class.new(SimpleTask) do
76
+ event :first, :command => true
77
+ event :second, :command => true
78
+ end
79
+
80
+ p1 = SimpleTask.new
81
+ child = child_model.new
82
+ plan.add([p1, child])
83
+ p1.depends_on child, options
84
+ plan.add_mission(p1)
85
+
86
+ child.start!; p1.start!
87
+ return p1, child
88
+ end
89
+
90
+ def assert_child_failed(child, reason, plan)
91
+ result = plan.check_structure
92
+ assert_equal([child].to_set, result.map { |e, _| e.exception.failed_task }.to_set)
93
+ assert_equal([reason].to_set, result.map { |e, _| e.exception.failed_event }.to_set)
94
+ end
95
+
96
+
97
+ def test_success
98
+ parent, child = create_pair :success => [:first],
99
+ :failure => [:stop],
100
+ :remove_when_done => false
101
+
102
+ assert_equal({}, plan.check_structure)
103
+ child.first!
104
+ assert_equal({}, plan.check_structure)
105
+ assert(parent.depends_on?(child))
106
+ end
107
+
108
+ def test_success_removal
109
+ parent, child = create_pair :success => [:first],
110
+ :failure => [:stop],
111
+ :remove_when_done => true
112
+
113
+ child.first!
114
+ assert_equal({}, plan.check_structure)
115
+ assert(!parent.depends_on?(child))
116
+ end
117
+
118
+ def test_success_preempts_explicit_failed
119
+ parent, child = create_pair :success => [:first],
120
+ :failure => [:stop]
121
+
122
+ child.first!
123
+ child.stop!
124
+ assert_equal({}, plan.check_structure)
125
+ end
126
+
127
+ def test_success_preempts_failure_on_unreachable
128
+ parent, child = create_pair :success => [:first]
129
+
130
+ child.first!
131
+ child.stop!
132
+ assert_equal({}, plan.check_structure)
133
+ end
134
+
135
+ def test_failure_explicit
136
+ parent, child = create_pair :success => [:first],
137
+ :failure => [:stop]
138
+
139
+ child.stop!
140
+ assert_child_failed(child, child.event(:stop).last, plan)
141
+ plan.clear
142
+ end
143
+
144
+ def test_failure_on_unreachable
145
+ parent, child = create_pair :success => [:first]
146
+
147
+ child.stop!
148
+ assert_child_failed(child, child.event(:failed).last, plan)
149
+ plan.clear
150
+ end
151
+
152
+ def test_fullfilled_model_validation
153
+ tag = TaskModelTag.new
154
+ klass = Class.new(Roby::Task)
155
+
156
+ p1, p2, child = prepare_plan :add => 3, :model => SimpleTask
157
+ p1.depends_on child, :model => [SimpleTask, { :id => "discover-3" }]
158
+ p2.depends_on child, :model => [SimpleTask, { :id => 'discover-3' }]
159
+
160
+ # Mess with the relation definition
161
+ p1[child, Dependency][:model].last[:id] = 'discover-10'
162
+ assert_raises(ModelViolation) { child.fullfilled_model }
163
+ p1[child, Dependency][:model] = [klass, {}]
164
+ assert_raises(ModelViolation) { child.fullfilled_model }
165
+ end
166
+
167
+ def test_fullfilled_model
168
+ tag = TaskModelTag.new
169
+ klass = Class.new(SimpleTask) do
170
+ include tag
171
+ end
172
+
173
+ p1, p2, child = prepare_plan :add => 3, :model => klass
174
+
175
+ p1.depends_on child, :model => [SimpleTask, { :id => "discover-3" }]
176
+ p2.depends_on child, :model => Roby::Task
177
+ assert_equal([[SimpleTask], {:id => 'discover-3'}], child.fullfilled_model)
178
+ p1.remove_child(child)
179
+ assert_equal([[Roby::Task], {}], child.fullfilled_model)
180
+ p1.depends_on child, :model => tag
181
+ assert_equal([[Roby::Task, tag], {}], child.fullfilled_model)
182
+ p2.remove_child(child)
183
+ p2.depends_on child, :model => [klass, { :id => 'discover-3' }]
184
+ assert_equal([[klass, tag], {:id => 'discover-3'}], child.fullfilled_model)
185
+ end
186
+
187
+ def test_fullfilled_model_transaction
188
+ tag = TaskModelTag.new
189
+ klass = Class.new(SimpleTask) do
190
+ include tag
191
+ end
192
+
193
+ p1, p2, child = prepare_plan :add => 3, :model => Class.new(klass)
194
+ trsc = Transaction.new(plan)
195
+
196
+ p1.depends_on child, :model => [SimpleTask, { :id => "discover-3" }]
197
+ p2.depends_on child, :model => klass
198
+
199
+ t_child = trsc[child]
200
+ assert_equal([[klass], {:id => "discover-3"}], t_child.fullfilled_model)
201
+ t_p2 = trsc[p2]
202
+ assert_equal([[klass], {:id => "discover-3"}], t_child.fullfilled_model)
203
+ t_p2.remove_child(t_child)
204
+ assert_equal([[SimpleTask], { :id => 'discover-3' }], t_child.fullfilled_model)
205
+ t_p2.depends_on t_child, :model => klass
206
+ assert_equal([[klass], { :id => 'discover-3' }], t_child.fullfilled_model)
207
+ trsc.remove_object(t_p2)
208
+ assert_equal([[SimpleTask], { :id => 'discover-3' }], t_child.fullfilled_model)
209
+ end
210
+
211
+ def test_first_children
212
+ p, c1, c2 = prepare_plan :add => 3, :model => SimpleTask
213
+ p.depends_on c1
214
+ p.depends_on c2
215
+ assert_equal([c1, c2].to_value_set, p.first_children)
216
+
217
+ c1.signals(:start, c2, :start)
218
+ assert_equal([c1].to_value_set, p.first_children)
219
+ end
220
+
221
+ def test_remove_finished_children
222
+ p, c1, c2 = prepare_plan :add => 3, :model => SimpleTask
223
+ plan.add_permanent(p)
224
+ p.depends_on c1
225
+ p.depends_on c2
226
+
227
+ p.start!
228
+ c1.start!
229
+ c1.success!
230
+ p.remove_finished_children
231
+ process_events
232
+ assert(!plan.include?(c1))
233
+ assert(plan.include?(c2))
234
+ end
235
+
236
+ def test_role_definition
237
+ plan.add(parent = SimpleTask.new)
238
+
239
+ child = SimpleTask.new
240
+ parent.depends_on child, :role => 'child1'
241
+ assert_equal(['child1'].to_set, parent.roles_of(child))
242
+
243
+ child = SimpleTask.new
244
+ parent.depends_on child, :roles => ['child1', 'child2']
245
+ assert_equal(['child1', 'child2'].to_set, parent.roles_of(child))
246
+ end
247
+
248
+ def setup_merging_test
249
+ plan.add(parent = SimpleTask.new)
250
+ tag = TaskModelTag.new
251
+ intermediate = Class.new(SimpleTask)
252
+ intermediate.include tag
253
+ child_model = Class.new(intermediate)
254
+ child = child_model.new(:id => 'child')
255
+ parent.depends_on child, :role => 'child1', :model => Task, :success => [], :failure => []
256
+
257
+ expected_info = { :remove_when_done=>true,
258
+ :model => [Roby::Task, {}],
259
+ :roles => ['child1'].to_set,
260
+ :success=>[],
261
+ :failure=>[] }
262
+ assert_equal expected_info, parent[child, Dependency]
263
+
264
+ return parent, child, expected_info, child_model, tag
265
+ end
266
+
267
+ def test_merging_events
268
+ parent, child, info, child_model, _ = setup_merging_test
269
+ parent.depends_on child, :success => []
270
+ info[:model] = [child_model, {:id => 'child'}]
271
+ assert_equal info, parent[child, Dependency]
272
+
273
+ parent.depends_on child, :success => [:success]
274
+ info[:success] = [:success]
275
+ assert_equal info, parent[child, Dependency]
276
+
277
+ assert_raises(ModelViolation) { parent.depends_on child, :failure => [:success] }
278
+ assert_equal info, parent[child, Dependency]
279
+
280
+ parent.depends_on child, :failure => [:stop]
281
+ info[:failure] = [:stop]
282
+ assert_equal info, parent[child, Dependency]
283
+ end
284
+
285
+ def test_merging_remove_when_done_cannot_change
286
+ parent, child, info, _ = setup_merging_test
287
+ assert_raises(ModelViolation) { parent.depends_on child, :remove_when_done => false }
288
+ parent.depends_on child, :model => info[:model], :remove_when_done => true, :success => []
289
+ assert_equal info, parent[child, Dependency]
290
+ end
291
+
292
+ def test_merging_models
293
+ parent, child, info, child_model, tag = setup_merging_test
294
+
295
+ # Test that models are "upgraded"
296
+ parent.depends_on child, :model => SimpleTask, :success => []
297
+ info[:model][0] = SimpleTask
298
+ assert_equal info, parent[child, Dependency]
299
+ parent.depends_on child, :model => Roby::Task, :remove_when_done => true, :success => []
300
+ assert_equal info, parent[child, Dependency]
301
+
302
+ # Test that arguments are merged
303
+ parent.depends_on child, :model => [SimpleTask, {:id => 'child'}], :success => []
304
+ info[:model][1] = {:id => 'child'}
305
+ assert_equal info, parent[child, Dependency]
306
+ # note: arguments can't be changed on the task *and* #depends_on
307
+ # validates them, so we don't need to test that.
308
+
309
+ # Test model/tag handling: #depends_on should find the most generic
310
+ # model matching +task+ that includes all required models
311
+ parent.depends_on child, :model => tag, :success => []
312
+ info[:model][0] = child_model.superclass
313
+ assert_equal info, parent[child, Dependency]
314
+ end
315
+
316
+ def test_merging_roles
317
+ parent, child, info, _ = setup_merging_test
318
+
319
+ parent.depends_on child, :model => Roby::Task, :role => 'child2', :success => []
320
+ info[:roles] << 'child2'
321
+ assert_equal info, parent[child, Dependency]
322
+ end
323
+ end
324
+
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
1
+ $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), File.dirname(__FILE__))
2
2
  require 'roby/test/common'
3
3
  require 'flexmock'
4
4
 
@@ -8,7 +8,7 @@ class TC_EnsuredEvent < Test::Unit::TestCase
8
8
  def test_ensure
9
9
  setup = lambda do |mock|
10
10
  e1, e2 = EventGenerator.new(true), Roby::EventGenerator.new(true)
11
- plan.discover [e1, e2]
11
+ plan.add [e1, e2]
12
12
  e1.ensure e2
13
13
  e1.on { mock.e1 }
14
14
  e2.on { mock.e2 }
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
1
+ $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), File.dirname(__FILE__))
2
2
  require 'roby/test/common'
3
3
  require 'roby/test/tasks/simple_task'
4
4
  require 'flexmock'
@@ -10,9 +10,13 @@ class TC_ExecutedBy < Test::Unit::TestCase
10
10
  event :ready
11
11
  forward :start => :ready
12
12
  end
13
+ class SecondExecutionModel < SimpleTask
14
+ event :ready
15
+ forward :start => :ready
16
+ end
13
17
 
14
18
  def test_relationships
15
- plan.discover(task = SimpleTask.new)
19
+ plan.add(task = SimpleTask.new)
16
20
  exec_task = ExecutionAgentModel.new
17
21
 
18
22
  task.executed_by exec_task
@@ -21,15 +25,15 @@ class TC_ExecutedBy < Test::Unit::TestCase
21
25
 
22
26
  def test_inherits_execution_model
23
27
  model = Class.new(Roby::Task) do
24
- executed_by ExecutionAgentModel
28
+ executed_by ExecutionAgentModel, :id => 20
25
29
  end
26
30
  submodel = Class.new(model)
27
31
 
28
- assert_equal(ExecutionAgentModel, submodel.execution_agent)
32
+ assert_equal([ExecutionAgentModel, {:id => 20}], submodel.execution_agent)
29
33
  end
30
34
 
31
35
  def test_nominal
32
- plan.discover(task = SimpleTask.new)
36
+ plan.add(task = SimpleTask.new)
33
37
  task.executed_by(ExecutionAgentModel.new)
34
38
  task.executed_by(exec = ExecutionAgentModel.new)
35
39
 
@@ -49,7 +53,7 @@ class TC_ExecutedBy < Test::Unit::TestCase
49
53
  end
50
54
 
51
55
  def test_agent_fails
52
- plan.discover(task = SimpleTask.new)
56
+ plan.add(task = SimpleTask.new)
53
57
  exec = ExecutionAgentModel.new
54
58
  task.executed_by exec
55
59
  task.start!
@@ -63,10 +67,10 @@ class TC_ExecutedBy < Test::Unit::TestCase
63
67
  end
64
68
 
65
69
  def test_agent_start_failed
66
- plan.insert(task = SimpleTask.new)
70
+ plan.add_mission(task = SimpleTask.new)
67
71
  exec = Class.new(SimpleTask) do
68
72
  event :ready
69
- on :start => :failed
73
+ signal :start => :failed
70
74
  end.new
71
75
  task.executed_by exec
72
76
 
@@ -76,23 +80,94 @@ class TC_ExecutedBy < Test::Unit::TestCase
76
80
  assert(exec.finished?)
77
81
  end
78
82
 
79
- def test_agent_model
83
+ def test_agent_model_spawns
80
84
  task_model = Class.new(SimpleTask)
81
85
 
82
- task_model.executed_by ExecutionAgentModel
83
- plan.insert(task = task_model.new)
86
+ task_model.executed_by ExecutionAgentModel, :id => 10
87
+ plan.add_mission(task = task_model.new)
84
88
  assert(task.execution_agent)
85
- assert(ExecutionAgentModel, task.execution_agent.class)
89
+ assert_equal(10, task.execution_agent.arguments[:id])
90
+ assert_kind_of(ExecutionAgentModel, task.execution_agent)
91
+
92
+ task.start!
93
+ assert(task.running?)
94
+ assert(task.execution_agent.running?)
95
+ end
96
+
97
+ def test_agent_model_reuses
98
+ plan.add_permanent(agent = ExecutionAgentModel.new)
99
+
100
+ task_model = Class.new(SimpleTask)
101
+ task_model.executed_by ExecutionAgentModel
102
+
103
+ plan.add_mission(task = task_model.new)
104
+ assert_same(agent, task.execution_agent)
86
105
 
87
106
  task.start!
88
107
  assert(task.running?)
89
108
  assert(task.execution_agent.running?)
90
109
  end
91
110
 
111
+ def test_agent_model_reuses_running_agent
112
+ plan.add_permanent(agent = ExecutionAgentModel.new)
113
+ agent.start!
114
+
115
+ task_model = Class.new(SimpleTask)
116
+ task_model.executed_by ExecutionAgentModel
117
+
118
+ plan.add_mission(task = task_model.new)
119
+ assert_same(agent, task.execution_agent)
120
+
121
+ task.start!
122
+ assert(task.running?)
123
+ end
124
+
125
+ def test_agent_model_arguments
126
+ plan.add_permanent(agent1 = ExecutionAgentModel.new(:id => 1))
127
+ plan.add_permanent(agent2 = ExecutionAgentModel.new(:id => 2))
128
+
129
+ task_model = Class.new(SimpleTask)
130
+ task_model.executed_by ExecutionAgentModel, :id => 2
131
+
132
+ plan.add_mission(task = task_model.new)
133
+ assert_same(agent2, task.execution_agent)
134
+
135
+ task.start!
136
+ assert(task.running?)
137
+ assert(task.execution_agent.running?)
138
+ end
139
+
140
+ def test_task_has_wrong_agent
141
+ task_model = Class.new(SimpleTask)
142
+ task_model.executed_by ExecutionAgentModel, :id => 2
143
+
144
+ plan.add_mission(task = task_model.new)
145
+
146
+ # Wrong agent type
147
+ plan.remove_object(task.execution_agent)
148
+ task.executed_by SecondExecutionModel.new(:id => 2)
149
+ assert_raises(Roby::CommandFailed) { task.start! }
150
+
151
+ # Wrong agent arguments
152
+ plan.remove_object(task.execution_agent)
153
+ task.executed_by ExecutionAgentModel.new(:id => 3)
154
+ assert_raises(Roby::CommandFailed) { task.start! }
155
+ end
156
+
157
+ def test_model_requires_agent_but_none_exists
158
+ task_model = Class.new(SimpleTask)
159
+ task_model.executed_by ExecutionAgentModel, :id => 2
160
+
161
+ plan.add_mission(task = task_model.new)
162
+ plan.remove_object(task.execution_agent)
163
+
164
+ assert_raises(Roby::CommandFailed) { task.start! }
165
+ end
166
+
92
167
  def test_respawn
93
168
  task_model = Class.new(SimpleTask)
94
169
  task_model.executed_by ExecutionAgentModel
95
- first, second = prepare_plan :discover => 2, :model => task_model
170
+ first, second = prepare_plan :add => 2, :model => task_model
96
171
  assert(first.execution_agent)
97
172
  assert(ExecutionAgentModel, first.execution_agent.class)
98
173
  assert(second.execution_agent)
@@ -104,7 +179,7 @@ class TC_ExecutedBy < Test::Unit::TestCase
104
179
  first_agent = first.execution_agent
105
180
  assert(first_agent.running?)
106
181
 
107
- plan.discover(third = task_model.new)
182
+ plan.add(third = task_model.new)
108
183
  assert_equal(first.execution_agent, third.execution_agent)
109
184
 
110
185
  first.execution_agent.stop!
@@ -115,7 +190,7 @@ class TC_ExecutedBy < Test::Unit::TestCase
115
190
  end
116
191
 
117
192
  def test_cannot_respawn
118
- plan.insert(task = Class.new(SimpleTask).new)
193
+ plan.add_mission(task = Class.new(SimpleTask).new)
119
194
  task.executed_by(agent = ExecutionAgentModel.new)
120
195
 
121
196
  agent.start!
@@ -127,14 +202,14 @@ class TC_ExecutedBy < Test::Unit::TestCase
127
202
  agent = Class.new(SimpleTask) do
128
203
  event :ready, :command => true
129
204
  end.new
130
- task, (init1, init2) = prepare_plan :missions => 1, :discover => 2, :model => SimpleTask
205
+ task, (init1, init2) = prepare_plan :missions => 1, :add => 2, :model => SimpleTask
131
206
  task.executed_by agent
132
207
  init1.executed_by agent
133
208
  init2.executed_by agent
134
209
 
135
- agent.realized_by(init = (init1 + init2))
136
- agent.on(:start, init, :start)
137
- init.forward(:success, agent, :ready)
210
+ agent.depends_on(init = (init1 + init2))
211
+ agent.signals(:start, init, :start)
212
+ init.forward_to(:success, agent, :ready)
138
213
 
139
214
  task.start!
140
215
  assert(!task.running?)