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,463 @@
1
+ $LOAD_PATH.unshift File.expand_path('../..', File.dirname(__FILE__))
2
+ require 'roby/test/distributed'
3
+ require 'roby/test/tasks/simple_task'
4
+
5
+ class TC_DistributedTransaction < Test::Unit::TestCase
6
+ include Roby::Distributed::Test
7
+
8
+ def test_marshal_transactions
9
+ peer2peer(true) do |remote|
10
+ PeerServer.class_eval do
11
+ attr_reader :plan
12
+ def transaction
13
+ @plan ||= Plan.new
14
+ Roby::Transaction.new(plan)
15
+ end
16
+ def d_transaction
17
+ @plan ||= Plan.new
18
+ Roby::Distributed::Transaction.new(plan)
19
+ end
20
+ end
21
+ end
22
+
23
+ trsc = remote_peer.call(:transaction)
24
+ assert_kind_of(Plan::DRoby, trsc)
25
+ assert_equal(local.plan, remote_peer.local_object(trsc))
26
+
27
+ dtrsc = remote_peer.call(:d_transaction)
28
+ assert_kind_of(Distributed::Transaction::DRoby, dtrsc)
29
+ assert_raises(InvalidRemoteOperation) { remote_peer.local_object(dtrsc) }
30
+ end
31
+
32
+ def test_transaction_create
33
+ peer2peer(true) do |remote|
34
+ PeerServer.class_eval do
35
+ include Test::Unit::Assertions
36
+ def check_transaction(marshalled_trsc, trsc_drbobject)
37
+ assert(trsc = peer.local_object(marshalled_trsc))
38
+ assert_equal(trsc_drbobject, trsc.remote_siblings[peer])
39
+ assert_equal([peer, Roby::Distributed], trsc.owners)
40
+ assert(!trsc.first_editor?)
41
+ assert(!trsc.editor?)
42
+ assert(trsc.conflict_solver.kind_of?(Roby::SolverIgnoreUpdate))
43
+
44
+ assert(trsc.subscribed?)
45
+ assert(trsc.update_on?(peer))
46
+ assert(trsc.updated_by?(peer))
47
+ trsc
48
+ end
49
+ end
50
+ end
51
+ trsc = Distributed::Transaction.new(plan, :conflict_solver => SolverIgnoreUpdate.new)
52
+ assert(trsc.self_owned?)
53
+ assert(trsc.first_editor?)
54
+ assert(trsc.editor?)
55
+
56
+ remote_peer.create_sibling(trsc)
57
+ trsc.add_owner remote_peer
58
+ assert_equal([Distributed, remote_peer], trsc.owners)
59
+ remote_peer.call(:check_transaction, trsc, trsc.remote_id)
60
+ assert(trsc.subscribed?)
61
+ assert(trsc.update_on?(remote_peer))
62
+ assert(trsc.updated_by?(remote_peer))
63
+
64
+ assert(trsc.editor?)
65
+ end
66
+
67
+ def test_transaction_proxies
68
+ peer2peer(true) do |remote|
69
+ PeerServer.class_eval do
70
+ include Test::Unit::Assertions
71
+ def marshalled_transaction_proxy(trsc, task)
72
+ task = peer.local_object(task)
73
+ trsc = peer.local_object(trsc)
74
+ proxy = trsc[task]
75
+
76
+ assert(proxy.update_on?(peer))
77
+ assert(proxy.updated_by?(peer))
78
+ proxy
79
+ end
80
+ end
81
+ end
82
+ trsc = Distributed::Transaction.new(plan)
83
+ remote_peer.create_sibling(trsc)
84
+
85
+ # Check that marshalling the remote view of a local transaction proxy
86
+ # returns the local proxy itself
87
+ plan.insert(task = Task.new)
88
+ assert(!plan.update_on?(remote_peer))
89
+ assert(trsc.update_on?(remote_peer))
90
+ assert(!task.update_on?(remote_peer))
91
+
92
+ proxy = trsc[task]
93
+ assert(task.update_on?(remote_peer))
94
+ assert(proxy.update_on?(remote_peer))
95
+ assert(proxy.updated_by?(remote_peer))
96
+ process_events
97
+
98
+ assert(marshalled_remote = remote_peer.call(:marshalled_transaction_proxy, trsc, task))
99
+ assert_equal(proxy, remote_peer.local_object(marshalled_remote))
100
+ end
101
+
102
+ # Checks that if we discover a set of tasks, then their relations are updated as well
103
+ def test_discover
104
+ peer2peer(true) do |remote|
105
+ def remote.add_tasks(trsc)
106
+ trsc = local_peer.local_object(trsc)
107
+
108
+ trsc.edit do
109
+ t1 = SimpleTask.new :id => 'root'
110
+ t1.realized_by(t2 = SimpleTask.new(:id => 'child'))
111
+ t1.on(:start, t2, :start)
112
+ t2.realized_by(t3 = SimpleTask.new(:id => 'grandchild'))
113
+ t3.on(:failed, t2, :failed)
114
+
115
+ trsc.insert(t1)
116
+ end
117
+ end
118
+ end
119
+
120
+ trsc = Distributed::Transaction.new(plan)
121
+ trsc.add_owner remote_peer
122
+ trsc.propose(remote_peer)
123
+
124
+ trsc.release(false)
125
+ remote.add_tasks(Distributed.format(trsc))
126
+ trsc.edit
127
+ assert(t1 = trsc.find_tasks.with_arguments(:id => 'root').to_a.first)
128
+ assert(t2 = trsc.find_tasks.with_arguments(:id => 'child').to_a.first)
129
+ assert(t3 = trsc.find_tasks.with_arguments(:id => 'grandchild').to_a.first)
130
+
131
+ assert(t1.child_object?(t2, TaskStructure::Hierarchy))
132
+ assert(t2.child_object?(t3, TaskStructure::Hierarchy))
133
+ end
134
+
135
+ def test_edition
136
+ peer2peer(true) do |remote|
137
+ class << remote
138
+ include Test::Unit::Assertions
139
+ def edit_transaction(trsc)
140
+ trsc = local_peer.local_object(trsc)
141
+ trsc.edit
142
+ assert_equal(local_peer, trsc.next_editor)
143
+ assert(trsc.editor?)
144
+ end
145
+ def give_back(trsc)
146
+ trsc = local_peer.local_object(trsc)
147
+ assert(trsc.editor?)
148
+ trsc.release(false)
149
+ end
150
+ end
151
+ end
152
+
153
+ trsc = Distributed::Transaction.new(plan)
154
+ remote_trsc = remote_peer.create_sibling(trsc)
155
+ trsc.edit
156
+
157
+ assert(trsc.editor?)
158
+ assert(!trsc.release(false))
159
+
160
+ trsc.add_owner remote_peer
161
+ assert_equal(remote_peer, trsc.next_editor)
162
+ assert(trsc.release(true))
163
+
164
+ assert_doesnt_timeout(5) do
165
+ remote.edit_transaction(Distributed.format(trsc))
166
+ end
167
+ assert_raises(NotEditor) { trsc.commit_transaction }
168
+ remote.give_back(Distributed.format(trsc))
169
+
170
+ assert_doesnt_timeout(5) do
171
+ trsc.edit
172
+ end
173
+ assert(trsc.edition_reloop)
174
+ assert_raises(NotReady) { trsc.commit_transaction }
175
+ end
176
+
177
+ def test_ownership
178
+ peer2peer(true) do |remote|
179
+ remote.plan.insert(Task.new(:id => 1))
180
+ def remote.add_owner_local(trsc)
181
+ trsc = local_peer.local_object(trsc)
182
+ trsc.add_owner local_peer
183
+ nil
184
+ end
185
+ end
186
+
187
+ # Create a transaction for the plan
188
+ trsc = Roby::Distributed::Transaction.new(plan)
189
+ remote_peer.create_sibling(trsc)
190
+ assert(Distributed.owns?(trsc))
191
+ assert(!remote_peer.owns?(trsc))
192
+
193
+ trsc.add_owner remote_peer
194
+ assert(remote_peer.owns?(trsc))
195
+ trsc.remove_owner remote_peer
196
+ assert(!remote_peer.owns?(trsc))
197
+
198
+ r_task = subscribe_task(:id => 1)
199
+ assert(!Distributed.owns?(r_task))
200
+ assert(remote_peer.owns?(r_task))
201
+ assert_raises(OwnershipError) { t_task = trsc[r_task] }
202
+ # Check we still can remove the peer from the transaction owners
203
+ trsc.add_owner(remote_peer)
204
+ t_task = trsc[r_task]
205
+
206
+ assert_raises(OwnershipError) { trsc.remove_owner(remote_peer) }
207
+ trsc.self_owned = false
208
+
209
+ task = Task.new
210
+ assert_raises(OwnershipError) { t_task.realized_by task }
211
+ assert_raises(OwnershipError) { task.realized_by t_task }
212
+ assert_raises(OwnershipError) { task.event(:start).on t_task.event(:start) }
213
+ assert_raises(OwnershipError) { trsc.discard_transaction }
214
+ assert_raises(OwnershipError) { trsc.commit_transaction }
215
+ assert(! task.plan)
216
+ assert_nothing_raised { t_task.event(:start).on task.event(:start) }
217
+
218
+ remote.add_owner_local(Distributed.format(trsc))
219
+
220
+ assert_nothing_raised { t_task.realized_by task }
221
+ assert_nothing_raised { t_task.remove_child task }
222
+ assert_nothing_raised { t_task.event(:start).remove_signal task.event(:start) }
223
+ assert_nothing_raised { task.realized_by t_task }
224
+ assert_nothing_raised { task.event(:start).on t_task.event(:start) }
225
+ assert_raises(OwnershipError) { trsc.remove_owner remote_peer }
226
+ assert_raises(OwnershipError) { trsc.self_owned = false }
227
+ assert_nothing_raised { trsc.discard_transaction }
228
+ end
229
+
230
+ def test_executed_by
231
+ peer2peer(true) do |remote|
232
+ task = Task.new(:id => 1)
233
+ exec = Class.new(Task) do
234
+ event :ready, :command => true
235
+ end.new(:id => 'exec')
236
+ task.executed_by exec
237
+ remote.plan.insert(task)
238
+
239
+ remote.singleton_class.class_eval do
240
+ include Test::Unit::Assertions
241
+ define_method(:check_execution_agent) do
242
+ remote_connection_tasks = plan.find_tasks.
243
+ with_model(ConnectionTask).
244
+ with_arguments(:peer => Roby::Distributed).
245
+ to_a
246
+ assert(remote_connection_tasks.empty?)
247
+ assert_equal(exec, task.execution_agent)
248
+ end
249
+ end
250
+ end
251
+ r_task = remote_task(:id => 1)
252
+ assert_equal(remote_peer.task, r_task.execution_agent)
253
+
254
+ trsc = Roby::Distributed::Transaction.new(plan)
255
+ trsc.add_owner remote_peer
256
+ trsc.self_owned
257
+ r_task = subscribe_task(:id => 1)
258
+ assert(!trsc[remote_peer.task].distribute?)
259
+ assert_equal(trsc[remote_peer.task], trsc[r_task].execution_agent)
260
+ trsc.propose(remote_peer)
261
+ trsc.commit_transaction
262
+
263
+ assert_equal(remote_peer.task, r_task.execution_agent)
264
+ remote.check_execution_agent
265
+ end
266
+
267
+ class ArgumentUpdateTest < Roby::Task
268
+ arguments :foo
269
+ end
270
+
271
+ def test_argument_updates
272
+ peer2peer(true) do |remote|
273
+ remote.plan.insert(ArgumentUpdateTest.new(:id => 2))
274
+ def remote.set_argument(task)
275
+ task = local_peer.local_object(task)
276
+ task.plan.edit
277
+ task.arguments[:foo] = :bar
278
+ task.plan.release(false)
279
+ nil
280
+ end
281
+ end
282
+ r_task = remote_task(:id => 2, :permanent => true)
283
+ assert_raises(OwnershipError, r_task.owners) { r_task.arguments[:foo] = :bar }
284
+
285
+ trsc = Roby::Distributed::Transaction.new(plan)
286
+ trsc.add_owner remote_peer
287
+ trsc.self_owned
288
+ trsc.propose(remote_peer)
289
+
290
+ t_task = trsc[r_task]
291
+ trsc.release(false)
292
+ assert_nothing_raised { remote.set_argument(Distributed.format(t_task)) }
293
+
294
+ trsc.edit
295
+ assert_equal(:bar, t_task.arguments[:foo], t_task.name)
296
+ assert(!t_task.arguments.writable?(:foo))
297
+ assert_raises(ArgumentError) { t_task.arguments[:foo] = :blo }
298
+ trsc.commit_transaction
299
+ assert_equal(:bar, r_task.arguments[:foo])
300
+ end
301
+
302
+ def build_transaction(trsc)
303
+
304
+ # Now, add a task of our own and link the remote and the local
305
+ task = SimpleTask.new :id => 'local'
306
+ trsc.discover(task)
307
+
308
+ parent = subscribe_task(:id => 'remote-1')
309
+ child = subscribe_task(:id => 'remote-2')
310
+
311
+ # Check some properties
312
+ assert((trsc[parent].owners - trsc.owners).empty?)
313
+ assert(trsc[parent].read_write?)
314
+ assert(task.read_write?)
315
+ assert(trsc[parent].event(:start).read_write?)
316
+ assert(trsc[parent].event(:stop).read_write?)
317
+ assert(task.event(:start).read_write?)
318
+ assert(task.event(:stop).read_write?)
319
+
320
+ # Add relations
321
+ trsc[parent].realized_by task
322
+ task.realized_by trsc[child]
323
+ trsc[parent].event(:start).on task.event(:start)
324
+ task.event(:stop).on trsc[child].event(:stop)
325
+
326
+ [task, parent]
327
+ end
328
+
329
+ # Checks that +plan+ looks like the result of #build_transaction
330
+ def check_resulting_plan(plan)
331
+ #assert_equal(4, plan.known_tasks.size)
332
+ r_task = plan.known_tasks.find { |t| t.arguments[:id] == 'remote-1' }
333
+ task = plan.known_tasks.find { |t| t.arguments[:id] == 'local' }
334
+ c_task = plan.known_tasks.find { |t| t.arguments[:id] == 'remote-2' }
335
+
336
+ assert_equal(2, r_task.children.to_a.size, r_task.children)
337
+ assert(r_task.child_object?(task, Roby::TaskStructure::Hierarchy))
338
+ assert_equal([task.event(:start)], r_task.event(:start).child_objects(Roby::EventStructure::Signal).to_a)
339
+ assert_equal([c_task], task.children.to_a)
340
+ assert_equal([c_task.event(:stop)], task.event(:stop).child_objects(Roby::EventStructure::Signal).to_a)
341
+ assert(r_task.child_object?(c_task, Roby::TaskStructure::Hierarchy))
342
+ end
343
+
344
+ # Commit the transaction and checks the result
345
+ def check_transaction_commit(trsc)
346
+ # Commit the transaction
347
+ assert(trsc.commit_transaction)
348
+ remote_peer.call(:check_plan)
349
+ check_resulting_plan(local.plan)
350
+ end
351
+
352
+ def test_propose_commit
353
+ peer2peer(true) do |remote|
354
+ testcase = self
355
+ remote.plan.insert(root = SimpleTask.new(:id => 'remote-1'))
356
+ root.realized_by(child = SimpleTask.new(:id => 'remote-2'))
357
+
358
+ PeerServer.class_eval do
359
+ include Test::Unit::Assertions
360
+ define_method(:check_transaction) do |trsc|
361
+ trsc = peer.local_object(trsc)
362
+ testcase.check_resulting_plan(trsc)
363
+ end
364
+ define_method(:check_plan) do
365
+ testcase.check_resulting_plan(plan)
366
+ end
367
+ end
368
+ end
369
+ trsc = Roby::Distributed::Transaction.new(plan)
370
+ trsc.add_owner remote_peer
371
+ trsc.self_owned
372
+
373
+ task, r_task = build_transaction(trsc)
374
+
375
+ # Send the transaction to remote_peer and commit it
376
+ trsc.propose(remote_peer)
377
+
378
+ remote_peer.call(:check_transaction, trsc)
379
+ check_resulting_plan(trsc)
380
+
381
+ check_transaction_commit(trsc)
382
+ end
383
+
384
+ def test_synchronization
385
+ peer2peer(true) do |remote|
386
+ testcase = self
387
+ remote.plan.insert(root = SimpleTask.new(:id => 'remote-1'))
388
+ root.realized_by SimpleTask.new(:id => 'remote-2')
389
+
390
+ PeerServer.class_eval do
391
+ define_method(:check_transaction) do |trsc|
392
+ testcase.check_resulting_plan(peer.local_object(trsc))
393
+ end
394
+ define_method(:check_plan) { testcase.check_resulting_plan(remote.plan) }
395
+ end
396
+ end
397
+
398
+ # Create a transaction for the plan and send it right away
399
+ trsc = Roby::Distributed::Transaction.new(plan)
400
+ trsc.self_owned
401
+ trsc.add_owner remote_peer
402
+ trsc.propose(remote_peer)
403
+
404
+ task, r_task = build_transaction(trsc)
405
+
406
+ check_resulting_plan(trsc)
407
+ process_events
408
+ remote_peer.call(:check_transaction, trsc)
409
+
410
+ # Commit the transaction
411
+ check_transaction_commit(trsc)
412
+ end
413
+
414
+ def test_create_remote_tasks
415
+ peer2peer(true) do |remote|
416
+ def remote.arguments_of(t)
417
+ t = local_peer.local_object(t)
418
+ t.arguments
419
+ end
420
+
421
+ def remote.check_ownership(t)
422
+ t = local_peer.local_object(t)
423
+ t.self_owned?
424
+ end
425
+
426
+ def remote.check_mission(t)
427
+ t = local_peer.local_object(t)
428
+ plan.mission?(t)
429
+ end
430
+ end
431
+
432
+ trsc = Roby::Distributed::Transaction.new(plan)
433
+ trsc.add_owner remote_peer
434
+ trsc.propose(remote_peer)
435
+
436
+ local_task = SimpleTask.new(:id => 'local')
437
+ trsc.insert(local_task)
438
+
439
+ t = SimpleTask.new(:arg => 10, :id => 0)
440
+ t.extend DistributedObject
441
+ local_task.realized_by t
442
+ trsc.insert(t)
443
+ t.owner = remote_peer
444
+
445
+ assert(trsc.task_index.by_owner[remote_peer].include?(t))
446
+ assert(!trsc.task_index.by_owner[Roby::Distributed].include?(t))
447
+
448
+ assert(!t.self_owned?)
449
+ assert(remote.check_ownership(Distributed.format(t)))
450
+
451
+ trsc.commit_transaction
452
+ assert(plan.include?(t))
453
+ assert(!plan.mission?(t))
454
+ assert(!t.self_owned?)
455
+ assert(plan.task_index.by_owner[remote_peer].include?(t), plan.task_index.by_owner)
456
+ assert(!plan.task_index.by_owner[Roby::Distributed].include?(t))
457
+ assert(remote.check_mission(Distributed.format(t)))
458
+ assert(remote.check_ownership(Distributed.format(t)))
459
+ assert(local_task.children.include?(t))
460
+ assert_equal({ :arg => 10, :id => 0 }, remote.arguments_of(Distributed.format(t)))
461
+ end
462
+ end
463
+