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,6 +1,7 @@
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
+ require 'roby/state/information'
4
5
  require 'flexmock'
5
6
 
6
7
  class TC_Query < Test::Unit::TestCase
@@ -43,13 +44,30 @@ class TC_Query < Test::Unit::TestCase
43
44
  t1 = task_model.new(:value => 1)
44
45
  t2 = task_model.new(:value => 2)
45
46
 
46
- plan.insert(t0)
47
- plan.insert(t1)
48
- plan.insert(t2)
47
+ plan.add_mission(t0)
48
+ plan.add_mission(t1)
49
+ plan.add_mission(t2)
49
50
 
50
51
  check_matches_fullfill(task_model, plan, t0, t1, t2)
51
52
  end
52
53
 
54
+ def test_match_tag
55
+ tag = TaskModelTag.new
56
+ tag.argument :id
57
+ task_model = Class.new(SimpleTask)
58
+ task_model.include tag
59
+
60
+ plan.add(task = task_model.new(:id => 3))
61
+ assert(Task.match(tag) === task)
62
+ assert(Task.match(tag, :id => 3) === task)
63
+ assert(! (Task.match(tag, :id => 2) === task))
64
+
65
+ plan.add(task = SimpleTask.new)
66
+ assert(! (Task.match(tag) === task))
67
+ assert(! (Task.match(tag, :id => 3) === task))
68
+ assert(! (Task.match(tag, :id => 2) === task))
69
+ end
70
+
53
71
  def test_match_proxy_fullfills
54
72
  task_model = Class.new(Task) do
55
73
  argument :value
@@ -59,9 +77,9 @@ class TC_Query < Test::Unit::TestCase
59
77
  t1 = task_model.new(:value => 1)
60
78
  t2 = task_model.new(:value => 2)
61
79
 
62
- plan.insert(t0)
63
- plan.insert(t1)
64
- plan.insert(t2)
80
+ plan.add_mission(t0)
81
+ plan.add_mission(t1)
82
+ plan.add_mission(t2)
65
83
 
66
84
  trsc = Transaction.new(plan)
67
85
  check_matches_fullfill(task_model, trsc, trsc[t0], trsc[t1], trsc[t2])
@@ -77,7 +95,7 @@ class TC_Query < Test::Unit::TestCase
77
95
  improves :yet_another_info
78
96
  end.new
79
97
 
80
- plan.discover [t1, t2]
98
+ plan.add [t1, t2]
81
99
  result = TaskMatcher.which_needs(:source_info).enum_for(:each, plan).to_set
82
100
  assert_equal([t1, t2].to_set, result)
83
101
  result = TaskMatcher.which_needs(:foo_bar).enum_for(:each, plan).to_set
@@ -104,7 +122,7 @@ class TC_Query < Test::Unit::TestCase
104
122
  def test_query_predicates
105
123
  t1 = Class.new(SimpleTask) { argument :fake }.new
106
124
  t2 = Roby::Task.new
107
- plan.discover [t1, t2]
125
+ plan.add [t1, t2]
108
126
 
109
127
  assert_finds_tasks([]) { TaskMatcher.executable }
110
128
  assert_finds_tasks([t1,t2]) { TaskMatcher.not_executable }
@@ -132,7 +150,7 @@ class TC_Query < Test::Unit::TestCase
132
150
  plan.remove_object(t1)
133
151
 
134
152
  t1 = SimpleTask.new
135
- plan.discover(t1)
153
+ plan.add(t1)
136
154
  t1.start!
137
155
  t1.failed!
138
156
  assert_finds_tasks([t1]) { TaskMatcher.failed }
@@ -141,8 +159,8 @@ class TC_Query < Test::Unit::TestCase
141
159
  end
142
160
 
143
161
  def test_query_plan_predicates
144
- t1, t2, t3 = prepare_plan :missions => 1, :discover => 1, :tasks => 1
145
- plan.permanent(t3)
162
+ t1, t2, t3 = prepare_plan :missions => 1, :add => 1, :tasks => 1
163
+ plan.add_permanent(t3)
146
164
  assert_query_finds_tasks([t1]) { plan.find_tasks.mission }
147
165
  assert_query_finds_tasks([t2, t3]) { plan.find_tasks.not_mission }
148
166
  assert_query_finds_tasks([t3]) { plan.find_tasks.permanent }
@@ -153,7 +171,7 @@ class TC_Query < Test::Unit::TestCase
153
171
  t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
154
172
  t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
155
173
  t3 = Roby::Task.new
156
- plan.discover [t1, t2, t3]
174
+ plan.add [t1, t2, t3]
157
175
 
158
176
  assert_finds_tasks([t3]) { (TaskMatcher.with_arguments(:id => 1) | TaskMatcher.with_arguments(:id => 2)).negate }
159
177
  end
@@ -162,7 +180,7 @@ class TC_Query < Test::Unit::TestCase
162
180
  t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
163
181
  t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
164
182
  t3 = Roby::Task.new
165
- plan.discover [t1, t2, t3]
183
+ plan.add [t1, t2, t3]
166
184
 
167
185
  assert_finds_tasks([t1, t2]) { TaskMatcher.with_arguments(:id => 1) | TaskMatcher.with_arguments(:id => 2) }
168
186
  end
@@ -171,7 +189,7 @@ class TC_Query < Test::Unit::TestCase
171
189
  t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
172
190
  t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
173
191
  t3 = Roby::Task.new
174
- plan.discover [t1, t2, t3]
192
+ plan.add [t1, t2, t3]
175
193
 
176
194
  assert_finds_tasks([t1, t2]) { TaskMatcher.fully_instanciated & TaskMatcher.executable }
177
195
  assert_finds_tasks([t1]) { (TaskMatcher.fully_instanciated & TaskMatcher.executable).with_arguments(:id => 1) }
@@ -179,19 +197,19 @@ class TC_Query < Test::Unit::TestCase
179
197
  end
180
198
 
181
199
  def test_merged_generated_subgraphs
182
- (d1, d2, d3, d4, d5, d6), t1 = prepare_plan :discover => 6, :tasks => 1
200
+ (d1, d2, d3, d4, d5, d6), t1 = prepare_plan :add => 6, :tasks => 1
183
201
 
184
202
  trsc = Transaction.new(plan)
185
- d1.realized_by d2
186
- d2.realized_by d3
187
- d4.realized_by d5
188
- d5.realized_by d6
203
+ d1.depends_on d2
204
+ d2.depends_on d3
205
+ d4.depends_on d5
206
+ d5.depends_on d6
189
207
 
190
208
  # Add a new relation which connects two components. Beware that
191
209
  # modifying trsc[d3] and trsc[d4] makes d2 and d5 proxies to be
192
210
  # discovered
193
- trsc[d3].realized_by t1
194
- t1.realized_by trsc[d4]
211
+ trsc[d3].depends_on t1
212
+ t1.depends_on trsc[d4]
195
213
  plan_set, trsc_set = trsc.merged_generated_subgraphs(TaskStructure::Hierarchy, [d1], [])
196
214
  assert_equal([trsc[d3], trsc[d4], t1].to_value_set, trsc_set)
197
215
  assert_equal([d1, d2, d5, d6].to_value_set, plan_set)
@@ -213,44 +231,184 @@ class TC_Query < Test::Unit::TestCase
213
231
  end
214
232
 
215
233
  def test_roots
216
- (t1, t2, t3), (tr1, tr2, tr3) = prepare_plan :discover => 3, :tasks => 3
234
+ (t1, t2, t3), (tr1, tr2, tr3) = prepare_plan :add => 3, :tasks => 3
217
235
  trsc = Transaction.new(plan)
218
- [tr1, tr2, tr3].each { |t| trsc.discover(t) }
236
+ [tr1, tr2, tr3].each { |t| trsc.add(t) }
219
237
 
220
238
  assert_equal([t1, t2, t3].to_value_set, plan.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
221
- t1.realized_by t2
239
+ t1.depends_on t2
222
240
  assert_equal([t1, t3].to_value_set, plan.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
223
241
 
224
- tr1.realized_by tr2
225
- trsc[t3].realized_by tr3
242
+ tr1.depends_on tr2
243
+ trsc[t3].depends_on tr3
226
244
  assert_equal([trsc[t1], trsc[t3], tr1].to_value_set, trsc.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
227
245
  end
228
246
 
247
+ def test_child_match
248
+ plan.add(t1 = SimpleTask.new(:id => 1))
249
+ t2 = Class.new(SimpleTask).new(:id => '2')
250
+ tag = TaskModelTag.new do
251
+ argument :tag_id
252
+ end
253
+ t3_model = Class.new(SimpleTask)
254
+ t3_model.include tag
255
+ t3 = t3_model.new(:id => 3, :tag_id => 3)
256
+ t1.depends_on t2
257
+ t2.depends_on t3
258
+ t1.depends_on t3
259
+
260
+ # t1 SimpleTask :id => 1
261
+ # t2 t2_model < SimpleTask :id => '2'
262
+ # t3 t3_model < tag < SimpleTask :id => 3
263
+ # t1 -> t2 -> t3
264
+ # t1 -> t3
265
+
266
+ assert_equal(3, plan.find_tasks(t1.model).to_a.size)
267
+
268
+ child_match = TaskMatcher.which_fullfills(SimpleTask, :id => 1)
269
+ assert_equal([], plan.find_tasks(t1.model).
270
+ with_child(child_match).to_a)
271
+
272
+ assert_equal([t1, t2].to_set, plan.find_tasks(SimpleTask).
273
+ with_child(SimpleTask).to_set)
274
+ assert_equal([t1].to_set, plan.find_tasks(SimpleTask).
275
+ with_child(SimpleTask, :id => '2').to_set)
276
+ assert_equal([t1].to_set, plan.find_tasks(SimpleTask).
277
+ with_child(t2.model).with_child(t3.model).to_set)
278
+ assert_equal([t1, t2].to_set, plan.find_tasks(SimpleTask).
279
+ with_child(t3.model).to_set)
280
+ assert_equal([t1, t2].to_set, plan.find_tasks(SimpleTask).
281
+ with_child(tag, :id => 3).to_set)
282
+ # :id is not an argument of +tag+, so the following should match, but
283
+ # the next one not.
284
+ assert_equal([t1, t2].to_set, plan.find_tasks(SimpleTask).
285
+ with_child(tag, :id => 2).to_set)
286
+ assert_equal([].to_set, plan.find_tasks(SimpleTask).
287
+ with_child(tag, :tag_id => 2).to_set)
288
+ assert_equal([], plan.find_tasks(t1.model).
289
+ with_child(SimpleTask, TaskStructure::PlannedBy).to_a)
290
+
291
+ t1.planned_by t2
292
+ assert_equal([t1], plan.find_tasks(t1.model).
293
+ with_child(SimpleTask, TaskStructure::PlannedBy).to_a)
294
+ assert_equal([t1], plan.find_tasks(t1.model).
295
+ with_child(SimpleTask, :relation => TaskStructure::PlannedBy).to_a)
296
+ assert_equal([], plan.find_tasks(t1.model).
297
+ with_child(SimpleTask, :id => 42, :relation => TaskStructure::PlannedBy).to_a)
298
+ assert_equal([], plan.find_tasks(t1.model).
299
+ with_child(SimpleTask, TaskStructure::PlannedBy, :an_argument => :which_is_set).to_a)
300
+ t1.remove_child_object(t2, TaskStructure::PlannedBy)
301
+
302
+ child_match = TaskMatcher.which_fullfills(SimpleTask, :id => t2.arguments[:id])
303
+ assert_equal([t1].to_set, plan.find_tasks(t1.model).
304
+ with_child(child_match).to_set)
305
+ assert_equal([], plan.find_tasks(t1.model).
306
+ with_child(SimpleTask, TaskStructure::PlannedBy).to_a)
307
+ end
308
+
309
+ def test_child_in_transactions
310
+ (t1, t2), t3 = prepare_plan :add => 2, :tasks => 1, :model => SimpleTask
311
+ t1.depends_on t2
312
+ trsc = Transaction.new(plan)
313
+ trsc[t2].depends_on t3
314
+
315
+ assert_equal(3, trsc.find_tasks(t1.model).to_a.size)
316
+ child_match = TaskMatcher.which_fullfills(SimpleTask, :id => 1)
317
+ assert_equal([], trsc.find_tasks(t1.model).
318
+ with_child(child_match).to_a)
319
+
320
+ child_match = TaskMatcher.which_fullfills(SimpleTask)
321
+ assert_equal([trsc[t1], trsc[t2]].to_set, trsc.find_tasks(t1.model).
322
+ with_child(child_match).to_set)
323
+
324
+ child_match = TaskMatcher.which_fullfills(SimpleTask, :id => t2.arguments[:id])
325
+ assert_equal([trsc[t1]].to_set, trsc.find_tasks(t1.model).
326
+ with_child(child_match).to_set)
327
+ end
328
+
329
+ def test_parent_match
330
+ plan.add(t1 = SimpleTask.new(:id => 1))
331
+ t2 = Class.new(SimpleTask).new(:id => 2)
332
+ t3 = Class.new(SimpleTask).new(:id => 3)
333
+ t3.depends_on t2
334
+ t3.depends_on t1
335
+ t2.depends_on t1
336
+
337
+ assert_equal(3, plan.find_tasks(SimpleTask).to_a.size)
338
+
339
+ parent_match = TaskMatcher.which_fullfills(SimpleTask, :id => 1)
340
+ assert_equal([], plan.find_tasks(SimpleTask).
341
+ with_parent(parent_match).to_a)
342
+
343
+ assert_equal([t1, t2].to_set, plan.find_tasks(SimpleTask).
344
+ with_parent(SimpleTask).to_set)
345
+ assert_equal([t1].to_set, plan.find_tasks(SimpleTask).
346
+ with_parent(t3.model).with_parent(t2.model).to_set)
347
+ assert_equal([], plan.find_tasks(SimpleTask).
348
+ with_parent(SimpleTask, TaskStructure::PlannedBy).to_a)
349
+ t2.planned_by t1
350
+ assert_equal([t1], plan.find_tasks(t1.model).
351
+ with_parent(SimpleTask, TaskStructure::PlannedBy).to_a)
352
+ assert_equal([t1], plan.find_tasks(t1.model).
353
+ with_parent(SimpleTask, :relation => TaskStructure::PlannedBy).to_a)
354
+ assert_equal([], plan.find_tasks(t1.model).
355
+ with_parent(SimpleTask, :id => 42, :relation => TaskStructure::PlannedBy).to_a)
356
+ assert_equal([], plan.find_tasks(t1.model).
357
+ with_parent(SimpleTask, TaskStructure::PlannedBy, :an_argument => :which_is_set).to_a)
358
+ t2.remove_child_object(t1, TaskStructure::PlannedBy)
359
+
360
+ assert_equal([t1].to_set, plan.find_tasks(SimpleTask).
361
+ with_parent(SimpleTask, :id => t2.arguments[:id]).to_set)
362
+ assert_equal([], plan.find_tasks(SimpleTask).
363
+ with_parent(SimpleTask, :id => t2.arguments[:id], :relation => TaskStructure::PlannedBy).to_a)
364
+ end
365
+
366
+ def test_parent_in_transaction
367
+ (t1, t2), t3 = prepare_plan :add => 2, :tasks => 1, :model => SimpleTask
368
+ t1.depends_on t2
369
+ trsc = Transaction.new(plan)
370
+ trsc[t2].depends_on t3
371
+
372
+ assert_equal(3, trsc.find_tasks(SimpleTask).to_a.size)
373
+
374
+ parent_match = TaskMatcher.which_fullfills(SimpleTask, :id => 1)
375
+ assert_equal([], trsc.find_tasks(SimpleTask).
376
+ with_parent(parent_match).to_a)
377
+
378
+ parent_match = TaskMatcher.which_fullfills(SimpleTask)
379
+ assert_equal([trsc[t2], t3].to_set, trsc.find_tasks(SimpleTask).
380
+ with_parent(parent_match).to_set)
381
+
382
+ parent_match = TaskMatcher.which_fullfills(SimpleTask, :id => t2.arguments[:id])
383
+ assert_equal([t3].to_set, trsc.find_tasks(SimpleTask).
384
+ with_parent(parent_match).to_set)
385
+ end
386
+
229
387
  def test_transactions_simple
230
388
  model = Class.new(Roby::Task) do
231
389
  argument :id
232
390
  end
233
391
  t1, t2, t3 = (1..3).map { |i| model.new(:id => i) }
234
- t1.realized_by t2
235
- plan.discover(t1)
392
+ t1.depends_on t2
393
+ plan.add(t1)
236
394
 
237
395
  trsc = Transaction.new(plan)
238
396
  assert(trsc.find_tasks.which_fullfills(SimpleTask).to_a.empty?)
239
- assert(!trsc[t1, false])
240
- assert(!trsc[t2, false])
241
- assert(!trsc[t3, false])
397
+ assert(!trsc.include?(t1))
398
+ assert(!trsc.include?(t2))
399
+ assert(!trsc.include?(t3))
242
400
 
243
401
  result = trsc.find_tasks.which_fullfills(model, :id => 1).to_a
244
402
  assert_equal([trsc[t1]], result)
245
- assert(!trsc[t2, false])
246
- assert(!trsc[t3, false])
403
+ assert(!trsc.include?(t2))
404
+ assert(!trsc.include?(t3))
247
405
 
248
406
  # Now that the proxy is in the transaction, check that it is still
249
407
  # found by the query
250
408
  result = trsc.find_tasks.which_fullfills(model, :id => 1).to_a
251
409
  assert_equal([trsc[t1]], result)
252
410
 
253
- trsc.discover(t3)
411
+ trsc.add(t3)
254
412
  result = trsc.find_tasks.which_fullfills(model, :id => 3).to_a
255
413
  assert_equal([t3], result)
256
414
 
@@ -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
 
@@ -16,6 +16,7 @@ class TC_Relations < Test::Unit::TestCase
16
16
 
17
17
  n = klass.new
18
18
  assert_equal(r2, space.constant('R2s'))
19
+ assert(r2.embeds_info?)
19
20
  assert( n.respond_to?(:each_child) )
20
21
  assert( n.respond_to?(:add_child) )
21
22
  assert( n.respond_to?(:remove_child) )
@@ -24,7 +25,63 @@ class TC_Relations < Test::Unit::TestCase
24
25
  assert( n.respond_to?(:add_child) )
25
26
  end
26
27
 
27
- def test_directed_relation
28
+ def test_relation_info
29
+ klass = Class.new { include DirectedRelationSupport }
30
+
31
+ space = Roby::RelationSpace(klass)
32
+ r2 = space.relation :R2
33
+ r1 = space.relation :R1, :subsets => [r2]
34
+ assert(r1.embeds_info?)
35
+ assert(r2.embeds_info?)
36
+
37
+ r3 = space.relation :R3, :noinfo => true
38
+ r1.superset_of r3
39
+ assert(!r3.embeds_info?)
40
+
41
+ n1, n2 = 2.enum_for(:times).map { klass.new }
42
+ n1.add_child_object(n2, r2)
43
+ assert_equal(nil, n1[n2, r2])
44
+ # Updating from nil to non-nil is allowed
45
+ n1.add_child_object(n2, r2, false)
46
+ assert_equal(false, n1[n2, r2])
47
+ # But changing a non-nil value is not allowed
48
+ assert_raises(ArgumentError) { n1.add_child_object(n2, r2, true) }
49
+
50
+ def r2.merge_info(from, to, old, new)
51
+ 2
52
+ end
53
+ # Changing a non-nil value should yield the return value of merge_info
54
+ n1.add_child_object(n2, r2, true)
55
+ assert_equal 2, n1[n2, r2]
56
+ end
57
+
58
+ def test_relation_info_in_subgraphs
59
+ klass = Class.new { include DirectedRelationSupport }
60
+ space = Roby::RelationSpace(klass)
61
+ r2 = space.relation :R2
62
+ r1 = space.relation :R1, :subsets => [r2]
63
+
64
+ n1, n2 = 2.enum_for(:times).map { klass.new }
65
+ n1.add_child_object(n2, r2, obj = Hash.new)
66
+ assert_equal(obj, n1[n2, r2])
67
+ assert_equal(nil, n1[n2, r1])
68
+ n1.add_child_object(n2, r1, other_obj = Hash.new)
69
+ assert_equal(obj, n1[n2, r2])
70
+ assert_equal(other_obj, n1[n2, r1])
71
+
72
+ n1.remove_child_object(n2, r2)
73
+
74
+ # Check that it works as well if we are updating a nil value
75
+ n1.add_child_object(n2, r2, nil)
76
+ n1.add_child_object(n2, r2, obj = Hash.new)
77
+ assert_equal(obj, n1[n2, r2])
78
+ assert_equal(nil, n1[n2, r1])
79
+ n1.add_child_object(n2, r1, other_obj = Hash.new)
80
+ assert_equal(obj, n1[n2, r2])
81
+ assert_equal(other_obj, n1[n2, r1])
82
+ end
83
+
84
+ def test_add_remove_relations
28
85
  klass = Class.new { include DirectedRelationSupport }
29
86
 
30
87
  r1, r2 = nil
@@ -33,12 +90,7 @@ class TC_Relations < Test::Unit::TestCase
33
90
  r2 = space.relation :Child, :parent_name => :parent
34
91
 
35
92
  n1, n2, n3, n4 = 4.enum_for(:times).map { klass.new }
36
- n1.add_child_object(n2, r1)
37
- assert_nothing_raised { n1.add_child_object(n2, r1, false) }
38
- assert_raises(ArgumentError) { n1.add_child_object(n2, r1, true) }
39
- n1.remove_child_object n2, r1
40
- assert_nothing_raised { n1.add_child_object(n2, r1) }
41
- assert_nothing_raised { n1.add_child_object(n2, r1, true) }
93
+ n1.add_child_object(n2, r1, true)
42
94
  assert_equal([n2], n1.child_objects(r1).to_a)
43
95
  assert_equal([n1], n2.parent_objects(r1).to_a)
44
96
 
@@ -176,5 +228,33 @@ class TC_Relations < Test::Unit::TestCase
176
228
  parent.remove_r1(child)
177
229
  assert_equal(nil, parent.r1)
178
230
  end
231
+
232
+ def test_relations
233
+ klass = Class.new { include DirectedRelationSupport }
234
+ space = Roby::RelationSpace(klass)
235
+ r1 = space.relation :R1
236
+ assert_equal [r1], space.relations
237
+ end
238
+
239
+ def test_child_enumeration_without_info
240
+ klass = Class.new { include DirectedRelationSupport }
241
+ space = Roby::RelationSpace(klass)
242
+ r1 = space.relation :R1, :child_name => 'child', :noinfo => true
243
+
244
+ v1, v2 = klass.new, klass.new
245
+ v1.add_child(v2, :test => true)
246
+
247
+ assert_equal([v2], v1.each_child.to_a)
248
+ end
249
+ def test_child_enumeration_with_info
250
+ klass = Class.new { include DirectedRelationSupport }
251
+ space = Roby::RelationSpace(klass)
252
+ r1 = space.relation :R1, :child_name => 'child'
253
+
254
+ v1, v2 = klass.new, klass.new
255
+ v1.add_child(v2, :test => true)
256
+
257
+ assert_equal([[v2, {:test => true}]], v1.each_child.to_a)
258
+ end
179
259
  end
180
260