roby 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. data/.gitignore +29 -0
  2. data/History.txt +4 -0
  3. data/License-fr.txt +519 -0
  4. data/License.txt +515 -0
  5. data/Manifest.txt +245 -0
  6. data/NOTES +4 -0
  7. data/README.txt +163 -0
  8. data/Rakefile +161 -0
  9. data/TODO.txt +146 -0
  10. data/app/README.txt +24 -0
  11. data/app/Rakefile +8 -0
  12. data/app/config/ROBOT.rb +5 -0
  13. data/app/config/app.yml +91 -0
  14. data/app/config/init.rb +7 -0
  15. data/app/config/roby.yml +3 -0
  16. data/app/controllers/.gitattributes +0 -0
  17. data/app/controllers/ROBOT.rb +2 -0
  18. data/app/data/.gitattributes +0 -0
  19. data/app/planners/ROBOT/main.rb +6 -0
  20. data/app/planners/main.rb +5 -0
  21. data/app/scripts/distributed +3 -0
  22. data/app/scripts/generate/bookmarks +3 -0
  23. data/app/scripts/replay +3 -0
  24. data/app/scripts/results +3 -0
  25. data/app/scripts/run +3 -0
  26. data/app/scripts/server +3 -0
  27. data/app/scripts/shell +3 -0
  28. data/app/scripts/test +3 -0
  29. data/app/tasks/.gitattributes +0 -0
  30. data/app/tasks/ROBOT/.gitattributes +0 -0
  31. data/bin/roby +210 -0
  32. data/bin/roby-log +168 -0
  33. data/bin/roby-shell +25 -0
  34. data/doc/images/event_generalization.png +0 -0
  35. data/doc/images/exception_propagation_1.png +0 -0
  36. data/doc/images/exception_propagation_2.png +0 -0
  37. data/doc/images/exception_propagation_3.png +0 -0
  38. data/doc/images/exception_propagation_4.png +0 -0
  39. data/doc/images/exception_propagation_5.png +0 -0
  40. data/doc/images/replay_handler_error.png +0 -0
  41. data/doc/images/replay_handler_error_0.png +0 -0
  42. data/doc/images/replay_handler_error_1.png +0 -0
  43. data/doc/images/roby_cycle_overview.png +0 -0
  44. data/doc/images/roby_replay_02.png +0 -0
  45. data/doc/images/roby_replay_03.png +0 -0
  46. data/doc/images/roby_replay_04.png +0 -0
  47. data/doc/images/roby_replay_event_representation.png +0 -0
  48. data/doc/images/roby_replay_first_state.png +0 -0
  49. data/doc/images/roby_replay_relations.png +0 -0
  50. data/doc/images/roby_replay_startup.png +0 -0
  51. data/doc/images/task_event_generalization.png +0 -0
  52. data/doc/papers.rdoc +11 -0
  53. data/doc/styles/allison.css +314 -0
  54. data/doc/styles/allison.js +316 -0
  55. data/doc/styles/allison.rb +276 -0
  56. data/doc/styles/jamis.rb +593 -0
  57. data/doc/tutorials/01-GettingStarted.rdoc +86 -0
  58. data/doc/tutorials/02-GoForward.rdoc +220 -0
  59. data/doc/tutorials/03-PlannedPath.rdoc +268 -0
  60. data/doc/tutorials/04-EventPropagation.rdoc +236 -0
  61. data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
  62. data/doc/tutorials/06-Overview.rdoc +40 -0
  63. data/doc/videos.rdoc +69 -0
  64. data/ext/droby/dump.cc +175 -0
  65. data/ext/droby/extconf.rb +3 -0
  66. data/ext/graph/algorithm.cc +746 -0
  67. data/ext/graph/extconf.rb +7 -0
  68. data/ext/graph/graph.cc +529 -0
  69. data/ext/graph/graph.hh +183 -0
  70. data/ext/graph/iterator_sequence.hh +102 -0
  71. data/ext/graph/undirected_dfs.hh +226 -0
  72. data/ext/graph/undirected_graph.hh +421 -0
  73. data/lib/roby.rb +41 -0
  74. data/lib/roby/app.rb +870 -0
  75. data/lib/roby/app/rake.rb +56 -0
  76. data/lib/roby/app/run.rb +14 -0
  77. data/lib/roby/app/scripts/distributed.rb +13 -0
  78. data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
  79. data/lib/roby/app/scripts/replay.rb +31 -0
  80. data/lib/roby/app/scripts/results.rb +15 -0
  81. data/lib/roby/app/scripts/run.rb +26 -0
  82. data/lib/roby/app/scripts/server.rb +18 -0
  83. data/lib/roby/app/scripts/shell.rb +88 -0
  84. data/lib/roby/app/scripts/test.rb +40 -0
  85. data/lib/roby/basic_object.rb +151 -0
  86. data/lib/roby/config.rb +5 -0
  87. data/lib/roby/control.rb +747 -0
  88. data/lib/roby/decision_control.rb +17 -0
  89. data/lib/roby/distributed.rb +32 -0
  90. data/lib/roby/distributed/base.rb +440 -0
  91. data/lib/roby/distributed/communication.rb +871 -0
  92. data/lib/roby/distributed/connection_space.rb +592 -0
  93. data/lib/roby/distributed/distributed_object.rb +206 -0
  94. data/lib/roby/distributed/drb.rb +62 -0
  95. data/lib/roby/distributed/notifications.rb +539 -0
  96. data/lib/roby/distributed/peer.rb +550 -0
  97. data/lib/roby/distributed/protocol.rb +529 -0
  98. data/lib/roby/distributed/proxy.rb +343 -0
  99. data/lib/roby/distributed/subscription.rb +311 -0
  100. data/lib/roby/distributed/transaction.rb +498 -0
  101. data/lib/roby/event.rb +897 -0
  102. data/lib/roby/exceptions.rb +234 -0
  103. data/lib/roby/executives/simple.rb +30 -0
  104. data/lib/roby/graph.rb +166 -0
  105. data/lib/roby/interface.rb +390 -0
  106. data/lib/roby/log.rb +3 -0
  107. data/lib/roby/log/chronicle.rb +303 -0
  108. data/lib/roby/log/console.rb +72 -0
  109. data/lib/roby/log/data_stream.rb +197 -0
  110. data/lib/roby/log/dot.rb +279 -0
  111. data/lib/roby/log/event_stream.rb +151 -0
  112. data/lib/roby/log/file.rb +340 -0
  113. data/lib/roby/log/gui/basic_display.ui +83 -0
  114. data/lib/roby/log/gui/chronicle.rb +26 -0
  115. data/lib/roby/log/gui/chronicle_view.rb +40 -0
  116. data/lib/roby/log/gui/chronicle_view.ui +70 -0
  117. data/lib/roby/log/gui/data_displays.rb +172 -0
  118. data/lib/roby/log/gui/data_displays.ui +155 -0
  119. data/lib/roby/log/gui/notifications.rb +26 -0
  120. data/lib/roby/log/gui/relations.rb +248 -0
  121. data/lib/roby/log/gui/relations.ui +123 -0
  122. data/lib/roby/log/gui/relations_view.rb +185 -0
  123. data/lib/roby/log/gui/relations_view.ui +149 -0
  124. data/lib/roby/log/gui/replay.rb +327 -0
  125. data/lib/roby/log/gui/replay_controls.rb +200 -0
  126. data/lib/roby/log/gui/replay_controls.ui +259 -0
  127. data/lib/roby/log/gui/runtime.rb +130 -0
  128. data/lib/roby/log/hooks.rb +185 -0
  129. data/lib/roby/log/logger.rb +202 -0
  130. data/lib/roby/log/notifications.rb +244 -0
  131. data/lib/roby/log/plan_rebuilder.rb +470 -0
  132. data/lib/roby/log/relations.rb +1056 -0
  133. data/lib/roby/log/server.rb +550 -0
  134. data/lib/roby/log/sqlite.rb +47 -0
  135. data/lib/roby/log/timings.rb +164 -0
  136. data/lib/roby/plan-object.rb +247 -0
  137. data/lib/roby/plan.rb +762 -0
  138. data/lib/roby/planning.rb +13 -0
  139. data/lib/roby/planning/loops.rb +302 -0
  140. data/lib/roby/planning/model.rb +906 -0
  141. data/lib/roby/planning/task.rb +151 -0
  142. data/lib/roby/propagation.rb +562 -0
  143. data/lib/roby/query.rb +619 -0
  144. data/lib/roby/relations.rb +583 -0
  145. data/lib/roby/relations/conflicts.rb +70 -0
  146. data/lib/roby/relations/ensured.rb +20 -0
  147. data/lib/roby/relations/error_handling.rb +23 -0
  148. data/lib/roby/relations/events.rb +9 -0
  149. data/lib/roby/relations/executed_by.rb +193 -0
  150. data/lib/roby/relations/hierarchy.rb +239 -0
  151. data/lib/roby/relations/influence.rb +10 -0
  152. data/lib/roby/relations/planned_by.rb +63 -0
  153. data/lib/roby/robot.rb +7 -0
  154. data/lib/roby/standard_errors.rb +218 -0
  155. data/lib/roby/state.rb +5 -0
  156. data/lib/roby/state/events.rb +221 -0
  157. data/lib/roby/state/information.rb +55 -0
  158. data/lib/roby/state/pos.rb +110 -0
  159. data/lib/roby/state/shapes.rb +32 -0
  160. data/lib/roby/state/state.rb +353 -0
  161. data/lib/roby/support.rb +92 -0
  162. data/lib/roby/task-operations.rb +182 -0
  163. data/lib/roby/task.rb +1618 -0
  164. data/lib/roby/test/common.rb +399 -0
  165. data/lib/roby/test/distributed.rb +214 -0
  166. data/lib/roby/test/tasks/empty_task.rb +9 -0
  167. data/lib/roby/test/tasks/goto.rb +36 -0
  168. data/lib/roby/test/tasks/simple_task.rb +23 -0
  169. data/lib/roby/test/testcase.rb +519 -0
  170. data/lib/roby/test/tools.rb +160 -0
  171. data/lib/roby/thread_task.rb +87 -0
  172. data/lib/roby/transactions.rb +462 -0
  173. data/lib/roby/transactions/proxy.rb +292 -0
  174. data/lib/roby/transactions/updates.rb +139 -0
  175. data/plugins/fault_injection/History.txt +4 -0
  176. data/plugins/fault_injection/README.txt +37 -0
  177. data/plugins/fault_injection/Rakefile +18 -0
  178. data/plugins/fault_injection/TODO.txt +0 -0
  179. data/plugins/fault_injection/app.rb +52 -0
  180. data/plugins/fault_injection/fault_injection.rb +89 -0
  181. data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
  182. data/plugins/subsystems/README.txt +40 -0
  183. data/plugins/subsystems/Rakefile +18 -0
  184. data/plugins/subsystems/app.rb +171 -0
  185. data/plugins/subsystems/test/app/README +24 -0
  186. data/plugins/subsystems/test/app/Rakefile +8 -0
  187. data/plugins/subsystems/test/app/config/app.yml +71 -0
  188. data/plugins/subsystems/test/app/config/init.rb +9 -0
  189. data/plugins/subsystems/test/app/config/roby.yml +3 -0
  190. data/plugins/subsystems/test/app/planners/main.rb +20 -0
  191. data/plugins/subsystems/test/app/scripts/distributed +3 -0
  192. data/plugins/subsystems/test/app/scripts/replay +3 -0
  193. data/plugins/subsystems/test/app/scripts/results +3 -0
  194. data/plugins/subsystems/test/app/scripts/run +3 -0
  195. data/plugins/subsystems/test/app/scripts/server +3 -0
  196. data/plugins/subsystems/test/app/scripts/shell +3 -0
  197. data/plugins/subsystems/test/app/scripts/test +3 -0
  198. data/plugins/subsystems/test/app/tasks/services.rb +15 -0
  199. data/plugins/subsystems/test/test_subsystems.rb +71 -0
  200. data/test/distributed/test_communication.rb +178 -0
  201. data/test/distributed/test_connection.rb +282 -0
  202. data/test/distributed/test_execution.rb +373 -0
  203. data/test/distributed/test_mixed_plan.rb +341 -0
  204. data/test/distributed/test_plan_notifications.rb +238 -0
  205. data/test/distributed/test_protocol.rb +516 -0
  206. data/test/distributed/test_query.rb +102 -0
  207. data/test/distributed/test_remote_plan.rb +491 -0
  208. data/test/distributed/test_transaction.rb +463 -0
  209. data/test/mockups/tasks.rb +27 -0
  210. data/test/planning/test_loops.rb +380 -0
  211. data/test/planning/test_model.rb +427 -0
  212. data/test/planning/test_task.rb +106 -0
  213. data/test/relations/test_conflicts.rb +42 -0
  214. data/test/relations/test_ensured.rb +38 -0
  215. data/test/relations/test_executed_by.rb +149 -0
  216. data/test/relations/test_hierarchy.rb +158 -0
  217. data/test/relations/test_planned_by.rb +54 -0
  218. data/test/suite_core.rb +24 -0
  219. data/test/suite_distributed.rb +9 -0
  220. data/test/suite_planning.rb +3 -0
  221. data/test/suite_relations.rb +8 -0
  222. data/test/test_bgl.rb +508 -0
  223. data/test/test_control.rb +399 -0
  224. data/test/test_event.rb +894 -0
  225. data/test/test_exceptions.rb +592 -0
  226. data/test/test_interface.rb +37 -0
  227. data/test/test_log.rb +114 -0
  228. data/test/test_log_server.rb +132 -0
  229. data/test/test_plan.rb +584 -0
  230. data/test/test_propagation.rb +210 -0
  231. data/test/test_query.rb +266 -0
  232. data/test/test_relations.rb +180 -0
  233. data/test/test_state.rb +414 -0
  234. data/test/test_support.rb +16 -0
  235. data/test/test_task.rb +938 -0
  236. data/test/test_testcase.rb +122 -0
  237. data/test/test_thread_task.rb +73 -0
  238. data/test/test_transactions.rb +569 -0
  239. data/test/test_transactions_proxy.rb +198 -0
  240. metadata +570 -0
@@ -0,0 +1,210 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'flexmock'
4
+ require 'roby/test/tasks/simple_task'
5
+
6
+ class TC_Propagation < Test::Unit::TestCase
7
+ include Roby::Test
8
+
9
+ def test_gather_propagation
10
+ e1, e2, e3 = EventGenerator.new(true), EventGenerator.new(true), EventGenerator.new(true)
11
+ plan.discover [e1, e2, e3]
12
+
13
+ set = Propagation.gather_propagation do
14
+ e1.call(1)
15
+ e1.call(4)
16
+ e2.emit(2)
17
+ e2.emit(3)
18
+ e3.call(5)
19
+ e3.emit(6)
20
+ end
21
+ assert_equal({ e1 => [nil, [nil, [1], nil, nil, [4], nil]], e2 => [[nil, [2], nil, nil, [3], nil], nil], e3 => [[nil, [6], nil], [nil, [5], nil]] }, set)
22
+ end
23
+
24
+ def test_prepare_propagation
25
+ g1, g2 = EventGenerator.new(true), EventGenerator.new(true)
26
+ ev = Event.new(g2, 0, nil)
27
+
28
+ step = [nil, [1], nil, nil, [4], nil]
29
+ source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
30
+ assert_equal(ValueSet.new, source_events)
31
+ assert_equal(ValueSet.new, source_generators)
32
+ assert_equal([1, 4], context)
33
+
34
+ step = [nil, [], nil, nil, [4], nil]
35
+ source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
36
+ assert_equal(ValueSet.new, source_events)
37
+ assert_equal(ValueSet.new, source_generators)
38
+ assert_equal([4], context)
39
+
40
+ step = [g1, [], nil, ev, [], nil]
41
+ source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
42
+ assert_equal([g1, g2].to_value_set, source_generators)
43
+ assert_equal([ev].to_value_set, source_events)
44
+ assert_equal(nil, context)
45
+
46
+ step = [g2, [], nil, ev, [], nil]
47
+ source_events, source_generators, context = Propagation.prepare_propagation(nil, false, step)
48
+ assert_equal([g2].to_value_set, source_generators)
49
+ assert_equal([ev].to_value_set, source_events)
50
+ assert_equal(nil, context)
51
+ end
52
+
53
+ def test_precedence_graph
54
+ e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
55
+ Propagation.event_ordering << :bla
56
+ Roby.plan.discover e1
57
+ Roby.plan.discover e2
58
+ assert(Propagation.event_ordering.empty?)
59
+
60
+ task = Roby::Task.new
61
+ Roby.plan.discover(task)
62
+ assert(Propagation.event_ordering.empty?)
63
+ assert(EventStructure::Precedence.linked?(task.event(:start), task.event(:updated_data)))
64
+
65
+ e1.signal e2
66
+ assert(EventStructure::Precedence.linked?(e1, e2))
67
+ assert(Propagation.event_ordering.empty?)
68
+
69
+ Propagation.event_ordering << :bla
70
+ e1.remove_signal e2
71
+ assert(Propagation.event_ordering.empty?)
72
+ assert(!EventStructure::Precedence.linked?(e1, e2))
73
+ end
74
+
75
+ def test_next_step
76
+ # For the test to be valid, we need +pending+ to have a deterministic ordering
77
+ # Fix that here
78
+ e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
79
+ plan.discover [e1, e2]
80
+ pending = [ [e1, [true, nil, nil, nil]], [e2, [false, nil, nil, nil]] ]
81
+ def pending.each_key; each { |(k, v)| yield(k) } end
82
+ def pending.delete(ev); delete_if { |(k, v)| k == ev } end
83
+
84
+ e1.add_precedence e2
85
+ assert_equal(e1, Propagation.next_event(pending).first)
86
+
87
+ e1.remove_precedence e2
88
+ e2.add_precedence e1
89
+ assert_equal(e2, Propagation.next_event(pending).first)
90
+ end
91
+
92
+ def test_delay
93
+ plan.insert(t = SimpleTask.new)
94
+ e = EventGenerator.new(true)
95
+ t.event(:start).on e, :delay => 0.1
96
+ Control.once { t.start! }
97
+ process_events
98
+ assert(!e.happened?)
99
+ sleep(0.5)
100
+ process_events
101
+ assert(e.happened?)
102
+ end
103
+
104
+ def test_duplicate_signals
105
+ plan.insert(t = SimpleTask.new)
106
+
107
+ FlexMock.use do |mock|
108
+ t.on(:start) { |event| t.emit(:success, *event.context) }
109
+ t.on(:start) { |event| t.emit(:success, *event.context) }
110
+
111
+ t.on(:success) { |event| mock.success(event.context) }
112
+ t.on(:stop) { |event| mock.stop(event.context) }
113
+ mock.should_receive(:success).with([42, 42]).once.ordered
114
+ mock.should_receive(:stop).with([42, 42]).once.ordered
115
+ t.start!(42)
116
+ end
117
+ end
118
+ def test_diamond_structure
119
+ a = Class.new(SimpleTask) do
120
+ event :child_success
121
+ event :child_stop
122
+ forward :child_success => :child_stop
123
+ end.new(:id => 'a')
124
+
125
+ plan.insert(a)
126
+ a.realized_by(b = SimpleTask.new(:id => 'b'))
127
+
128
+ b.forward(:success, a, :child_success)
129
+ b.forward(:stop, a, :child_stop)
130
+
131
+ FlexMock.use do |mock|
132
+ a.on(:child_stop) { mock.stopped }
133
+ mock.should_receive(:stopped).once.ordered
134
+ a.start!
135
+ b.start!
136
+ b.success!
137
+ end
138
+ end
139
+
140
+ def test_signal_forward
141
+ forward = EventGenerator.new(true)
142
+ signal = EventGenerator.new(true)
143
+ plan.discover [forward, signal]
144
+
145
+ FlexMock.use do |mock|
146
+ sink = EventGenerator.new do |context|
147
+ mock.command_called(context)
148
+ sink.emit(42)
149
+ end
150
+ sink.on { |event| mock.handler_called(event.context) }
151
+
152
+ forward.forward sink
153
+ signal.signal sink
154
+
155
+ seed = lambda do
156
+ forward.call(24)
157
+ signal.call(42)
158
+ end
159
+ mock.should_receive(:command_called).with([42]).once.ordered
160
+ mock.should_receive(:handler_called).with([42, 24]).once.ordered
161
+ Propagation.propagate_events([seed])
162
+ end
163
+ end
164
+
165
+ module LogEventGathering
166
+ class << self
167
+ attr_accessor :mockup
168
+ def handle(name, obj)
169
+ mockup.send(name, obj, Roby::Propagation.sources) if mockup
170
+ end
171
+ end
172
+
173
+ def signalling(event, to)
174
+ super if defined? super
175
+ LogEventGathering.handle(:signalling, self)
176
+ end
177
+ def forwarding(event, to)
178
+ super if defined? super
179
+ LogEventGathering.handle(:forwarding, self)
180
+ end
181
+ def emitting(context)
182
+ super if defined? super
183
+ LogEventGathering.handle(:emitting, self)
184
+ end
185
+ def calling(context)
186
+ super if defined? super
187
+ LogEventGathering.handle(:calling, self)
188
+ end
189
+ end
190
+ EventGenerator.include LogEventGathering
191
+
192
+ def test_log_events
193
+ FlexMock.use do |mock|
194
+ LogEventGathering.mockup = mock
195
+ dst = EventGenerator.new { }
196
+ src = EventGenerator.new { dst.call }
197
+ plan.discover [src, dst]
198
+
199
+ mock.should_receive(:signalling).never
200
+ mock.should_receive(:forwarding).never
201
+ mock.should_receive(:calling).with(src, [].to_value_set).once
202
+ mock.should_receive(:calling).with(dst, [src].to_value_set).once
203
+ src.call
204
+ end
205
+
206
+ ensure
207
+ LogEventGathering.mockup = nil
208
+ end
209
+ end
210
+
@@ -0,0 +1,266 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/tasks/simple_task'
4
+ require 'flexmock'
5
+
6
+ class TC_Query < Test::Unit::TestCase
7
+ include Roby::Test
8
+
9
+ def check_matches_fullfill(task_model, plan, t0, t1, t2)
10
+ result = TaskMatcher.new.enum_for(:each, plan).to_set
11
+ assert_equal([t1, t2, t0].to_set, result)
12
+ result = TaskMatcher.new.with_model(Roby::Task).enum_for(:each, plan).to_set
13
+ assert_equal([t1, t2, t0].to_set, result, plan.task_index.by_model)
14
+
15
+ result = TaskMatcher.which_fullfills(task_model).enum_for(:each, plan).to_set
16
+ assert_equal([t1, t2].to_set, result)
17
+
18
+ result = TaskMatcher.with_model(task_model).enum_for(:each, plan).to_set
19
+ assert_equal([t1, t2].to_set, result)
20
+ result = TaskMatcher.with_arguments(:value => 1).enum_for(:each, plan).to_set
21
+ assert_equal([t0, t1].to_set, result)
22
+
23
+ result = TaskMatcher.which_fullfills(task_model, :value => 1).enum_for(:each, plan).to_set
24
+ assert_equal([t1].to_set, result)
25
+
26
+ result = plan.find_tasks.which_fullfills(task_model, :value => 2).to_set
27
+ assert_equal([t2].to_set, result)
28
+ # Try the shortcut of find_tasks(model, args) for find_tasks.which_fullfills(model, args)
29
+ result = plan.find_tasks(task_model, :value => 2).to_set
30
+ assert_equal([t2].to_set, result)
31
+ result = plan.find_tasks(task_model).to_set
32
+ assert_equal([t1, t2].to_set, result)
33
+
34
+ assert_marshallable(TaskMatcher.new.which_fullfills(task_model, :value => 2))
35
+ end
36
+
37
+ def test_match_task_fullfills
38
+ task_model = Class.new(Task) do
39
+ argument :value
40
+ end
41
+
42
+ t0 = Roby::Task.new(:value => 1)
43
+ t1 = task_model.new(:value => 1)
44
+ t2 = task_model.new(:value => 2)
45
+
46
+ plan.insert(t0)
47
+ plan.insert(t1)
48
+ plan.insert(t2)
49
+
50
+ check_matches_fullfill(task_model, plan, t0, t1, t2)
51
+ end
52
+
53
+ def test_match_proxy_fullfills
54
+ task_model = Class.new(Task) do
55
+ argument :value
56
+ end
57
+
58
+ t0 = Roby::Task.new(:value => 1)
59
+ t1 = task_model.new(:value => 1)
60
+ t2 = task_model.new(:value => 2)
61
+
62
+ plan.insert(t0)
63
+ plan.insert(t1)
64
+ plan.insert(t2)
65
+
66
+ trsc = Transaction.new(plan)
67
+ check_matches_fullfill(task_model, trsc, trsc[t0], trsc[t1], trsc[t2])
68
+ end
69
+
70
+ def test_query_information
71
+ t1 = Class.new(Task) do
72
+ needs :source_info
73
+ improves :other_info
74
+ end.new
75
+ t2 = Class.new(Task) do
76
+ needs :source_info
77
+ improves :yet_another_info
78
+ end.new
79
+
80
+ plan.discover [t1, t2]
81
+ result = TaskMatcher.which_needs(:source_info).enum_for(:each, plan).to_set
82
+ assert_equal([t1, t2].to_set, result)
83
+ result = TaskMatcher.which_needs(:foo_bar).enum_for(:each, plan).to_set
84
+ assert_equal(Set.new, result)
85
+ result = TaskMatcher.which_improves(:foo_bar).enum_for(:each, plan).to_set
86
+ assert_equal(Set.new, result)
87
+ result = TaskMatcher.which_improves(:other_info).enum_for(:each, plan).to_set
88
+ assert_equal([t1].to_set, result)
89
+ result = TaskMatcher.which_needs(:source_info).
90
+ which_improves(:yet_another_info).
91
+ enum_for(:each, plan).to_set
92
+
93
+ assert_equal([t2].to_set, result)
94
+ end
95
+
96
+ def assert_query_finds_tasks(task_set)
97
+ assert_equal(task_set.to_set, yield.enum_for(:each).to_set)
98
+ end
99
+
100
+ def assert_finds_tasks(task_set, msg = "")
101
+ assert_equal(task_set.to_set, yield.enum_for(:each, plan).to_set, msg)
102
+ end
103
+
104
+ def test_query_predicates
105
+ t1 = Class.new(SimpleTask) { argument :fake }.new
106
+ t2 = Roby::Task.new
107
+ plan.discover [t1, t2]
108
+
109
+ assert_finds_tasks([]) { TaskMatcher.executable }
110
+ assert_finds_tasks([t1,t2]) { TaskMatcher.not_executable }
111
+ assert_finds_tasks([t2]) { TaskMatcher.abstract }
112
+ assert_finds_tasks([t1]) { TaskMatcher.partially_instanciated }
113
+ assert_finds_tasks([t2]) { TaskMatcher.fully_instanciated }
114
+ t1.arguments[:fake] = 2
115
+ assert_finds_tasks([t1, t2]) { TaskMatcher.fully_instanciated }
116
+ assert_finds_tasks([t2]) { TaskMatcher.fully_instanciated.abstract }
117
+
118
+ assert_finds_tasks([t1, t2]) { TaskMatcher.pending }
119
+ t1.start!
120
+ assert_finds_tasks([t2]) { TaskMatcher.pending }
121
+ assert_finds_tasks([t1, t2]) { TaskMatcher.not_failed }
122
+ assert_finds_tasks([t1, t2]) { TaskMatcher.not_success }
123
+ assert_finds_tasks([t1, t2]) { TaskMatcher.not_finished }
124
+
125
+ assert_finds_tasks([t1]) { TaskMatcher.running }
126
+ t1.success!
127
+ assert_finds_tasks([t1], plan.task_index.by_state) { TaskMatcher.success }
128
+ assert_finds_tasks([t1]) { TaskMatcher.finished }
129
+ assert_finds_tasks([t1, t2]) { TaskMatcher.not_failed }
130
+ assert_finds_tasks([t2]) { TaskMatcher.not_finished }
131
+
132
+ plan.remove_object(t1)
133
+
134
+ t1 = SimpleTask.new
135
+ plan.discover(t1)
136
+ t1.start!
137
+ t1.failed!
138
+ assert_finds_tasks([t1]) { TaskMatcher.failed }
139
+ assert_finds_tasks([t1]) { TaskMatcher.finished }
140
+ assert_finds_tasks([t1]) { TaskMatcher.finished.not_success }
141
+ end
142
+
143
+ def test_query_plan_predicates
144
+ t1, t2, t3 = prepare_plan :missions => 1, :discover => 1, :tasks => 1
145
+ plan.permanent(t3)
146
+ assert_query_finds_tasks([t1]) { plan.find_tasks.mission }
147
+ assert_query_finds_tasks([t2, t3]) { plan.find_tasks.not_mission }
148
+ assert_query_finds_tasks([t3]) { plan.find_tasks.permanent }
149
+ assert_query_finds_tasks([t1, t2]) { plan.find_tasks.not_permanent }
150
+ end
151
+
152
+ def test_negate
153
+ t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
154
+ t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
155
+ t3 = Roby::Task.new
156
+ plan.discover [t1, t2, t3]
157
+
158
+ assert_finds_tasks([t3]) { (TaskMatcher.with_arguments(:id => 1) | TaskMatcher.with_arguments(:id => 2)).negate }
159
+ end
160
+
161
+ def test_or
162
+ t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
163
+ t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
164
+ t3 = Roby::Task.new
165
+ plan.discover [t1, t2, t3]
166
+
167
+ assert_finds_tasks([t1, t2]) { TaskMatcher.with_arguments(:id => 1) | TaskMatcher.with_arguments(:id => 2) }
168
+ end
169
+
170
+ def test_and
171
+ t1 = Class.new(SimpleTask) { argument :id }.new(:id => 1)
172
+ t2 = Class.new(SimpleTask) { argument :id }.new(:id => 2)
173
+ t3 = Roby::Task.new
174
+ plan.discover [t1, t2, t3]
175
+
176
+ assert_finds_tasks([t1, t2]) { TaskMatcher.fully_instanciated & TaskMatcher.executable }
177
+ assert_finds_tasks([t1]) { (TaskMatcher.fully_instanciated & TaskMatcher.executable).with_arguments(:id => 1) }
178
+ assert_finds_tasks([t3]) { TaskMatcher.fully_instanciated & TaskMatcher.abstract }
179
+ end
180
+
181
+ def test_merged_generated_subgraphs
182
+ (d1, d2, d3, d4, d5, d6), t1 = prepare_plan :discover => 6, :tasks => 1
183
+
184
+ trsc = Transaction.new(plan)
185
+ d1.realized_by d2
186
+ d2.realized_by d3
187
+ d4.realized_by d5
188
+ d5.realized_by d6
189
+
190
+ # Add a new relation which connects two components. Beware that
191
+ # modifying trsc[d3] and trsc[d4] makes d2 and d5 proxies to be
192
+ # discovered
193
+ trsc[d3].realized_by t1
194
+ t1.realized_by trsc[d4]
195
+ plan_set, trsc_set = trsc.merged_generated_subgraphs(TaskStructure::Hierarchy, [d1], [])
196
+ assert_equal([trsc[d3], trsc[d4], t1].to_value_set, trsc_set)
197
+ assert_equal([d1, d2, d5, d6].to_value_set, plan_set)
198
+
199
+ # Remove the relation and check the result
200
+ trsc[d3].remove_child t1
201
+ plan_set, trsc_set = trsc.merged_generated_subgraphs(TaskStructure::Hierarchy, [d1], [])
202
+ assert_equal([d1, d2].to_value_set, plan_set)
203
+ assert_equal([trsc[d3]].to_value_set, trsc_set)
204
+ plan_set, trsc_set = trsc.merged_generated_subgraphs(TaskStructure::Hierarchy, [], [t1])
205
+ assert_equal([d5, d6].to_value_set, plan_set)
206
+ assert_equal([t1, trsc[d4]].to_value_set, trsc_set)
207
+
208
+ # Remove a plan relation inside the transaction, and check it is taken into account
209
+ trsc[d2].remove_child trsc[d3]
210
+ plan_set, trsc_set = trsc.merged_generated_subgraphs(TaskStructure::Hierarchy, [d1], [])
211
+ assert_equal([d1].to_value_set, plan_set)
212
+ assert_equal([trsc[d2]].to_value_set, trsc_set)
213
+ end
214
+
215
+ def test_roots
216
+ (t1, t2, t3), (tr1, tr2, tr3) = prepare_plan :discover => 3, :tasks => 3
217
+ trsc = Transaction.new(plan)
218
+ [tr1, tr2, tr3].each { |t| trsc.discover(t) }
219
+
220
+ assert_equal([t1, t2, t3].to_value_set, plan.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
221
+ t1.realized_by t2
222
+ assert_equal([t1, t3].to_value_set, plan.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
223
+
224
+ tr1.realized_by tr2
225
+ trsc[t3].realized_by tr3
226
+ assert_equal([trsc[t1], trsc[t3], tr1].to_value_set, trsc.find_tasks.roots(TaskStructure::Hierarchy).to_value_set)
227
+ end
228
+
229
+ def test_transactions_simple
230
+ model = Class.new(Roby::Task) do
231
+ argument :id
232
+ end
233
+ t1, t2, t3 = (1..3).map { |i| model.new(:id => i) }
234
+ t1.realized_by t2
235
+ plan.discover(t1)
236
+
237
+ trsc = Transaction.new(plan)
238
+ 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])
242
+
243
+ result = trsc.find_tasks.which_fullfills(model, :id => 1).to_a
244
+ assert_equal([trsc[t1]], result)
245
+ assert(!trsc[t2, false])
246
+ assert(!trsc[t3, false])
247
+
248
+ # Now that the proxy is in the transaction, check that it is still
249
+ # found by the query
250
+ result = trsc.find_tasks.which_fullfills(model, :id => 1).to_a
251
+ assert_equal([trsc[t1]], result)
252
+
253
+ trsc.discover(t3)
254
+ result = trsc.find_tasks.which_fullfills(model, :id => 3).to_a
255
+ assert_equal([t3], result)
256
+
257
+ # Commit the transaction and check that the tasks are added to the plan
258
+ # index
259
+ trsc.commit_transaction
260
+ result = plan.find_tasks.which_fullfills(model, :id => 3).to_a
261
+ assert_equal([t3], result)
262
+ end
263
+ end
264
+
265
+
266
+