roby 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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?)