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,122 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/testcase'
4
+ require 'roby/test/tasks/simple_task'
5
+ require 'flexmock'
6
+
7
+ class TC_Test_TestCase < Test::Unit::TestCase
8
+ include Roby::Test
9
+ include Roby::Test::Assertions
10
+
11
+ def test_assert_any_event
12
+ plan.discover(t = SimpleTask.new)
13
+ t.start!
14
+ assert_nothing_raised do
15
+ assert_any_event(t.event(:start))
16
+ end
17
+
18
+ t.success!
19
+ assert_nothing_raised do
20
+ assert_any_event(t.event(:start))
21
+ assert_any_event([t.event(:success)], [t.event(:stop)])
22
+ end
23
+
24
+ plan.discover(t = SimpleTask.new)
25
+ t.start!
26
+ t.failed!
27
+ assert_raises(Test::Unit::AssertionFailedError) do
28
+ assert_any_event([t.event(:success)], [t.event(:stop)])
29
+ end
30
+
31
+ Roby.logger.level = Logger::FATAL
32
+ Roby.control.run :detach => true
33
+ plan.insert(t = SimpleTask.new)
34
+ assert_any_event(t.event(:success)) do
35
+ t.start!
36
+ t.success!
37
+ end
38
+
39
+ # Make control quit and check that we get ControlQuitError
40
+ plan.insert(t = SimpleTask.new)
41
+ assert_raises(Test::Unit::AssertionFailedError) do
42
+ assert_any_event(t.event(:success)) do
43
+ t.start!
44
+ t.failed!
45
+ end
46
+ end
47
+
48
+ ## Same test, but check that the assertion succeeds since we *are*
49
+ ## checking that +failed+ happens
50
+ Roby.control.run :detach => true
51
+ plan.insert(t = SimpleTask.new)
52
+ assert_nothing_raised do
53
+ assert_any_event(t.event(:failed)) do
54
+ t.start!
55
+ t.failed!
56
+ end
57
+ end
58
+ end
59
+
60
+ def test_assert_succeeds
61
+ Roby.control.run :detach => true
62
+
63
+ task = Class.new(SimpleTask) do
64
+ forward :start => :success
65
+ end.new
66
+ assert_nothing_raised do
67
+ assert_succeeds(task)
68
+ end
69
+
70
+ task = Class.new(SimpleTask) do
71
+ forward :start => :failed
72
+ end.new
73
+ assert_raises(Test::Unit::AssertionFailedError) do
74
+ assert_succeeds(task)
75
+ end
76
+ end
77
+
78
+ def test_sampling
79
+ Roby.control.run :cycle => 0.1, :detach => true
80
+
81
+ i = 0
82
+ samples = Roby::Test.sampling(1, 0.1, :time_test, :index, :dummy) do
83
+ i += 1
84
+ [Roby.control.cycle_start, rand / 10 - 0.05 + i, rand / 10 + 0.95]
85
+ end
86
+ cur_size = samples.size
87
+
88
+ # Check the result
89
+ samples.each { |a| assert_equal(a.time_test, a.t) }
90
+ samples.each_with_index do |a, i|
91
+ next if i == 0
92
+ assert(a.dt)
93
+ assert_in_delta(0.1, a.dt, 0.01)
94
+ end
95
+ samples.each_with_index do |a, b|
96
+ assert_in_delta(b + 1, a.index, 0.05)
97
+ end
98
+
99
+ # Check that the handler has been removed
100
+ assert_equal(cur_size, samples.size)
101
+
102
+ samples
103
+ end
104
+
105
+ def test_stats
106
+ samples = test_sampling
107
+ stats = Roby::Test.stats(samples, :dummy => :absolute)
108
+ assert_in_delta(1, stats.index.mean, 0.05)
109
+ assert_in_delta(0.025, stats.index.stddev, 0.026)
110
+ assert_in_delta(1, stats.dummy.mean, 0.05)
111
+ assert_in_delta(0.025, stats.dummy.stddev, 0.026)
112
+ assert_in_delta(0.1, stats.dt.mean, 0.001, stats.dt)
113
+ assert_in_delta(0, stats.dt.stddev, 0.001)
114
+
115
+ stats = Roby::Test.stats(samples, :index => :rate, :dummy => :absolute_rate)
116
+ assert_in_delta(10, stats.index.mean, 1)
117
+ assert_in_delta(0.25, stats.index.stddev, 0.25)
118
+ assert_in_delta(10, stats.dummy.mean, 1)
119
+ assert_in_delta(0.25, stats.dummy.stddev, 0.25)
120
+ end
121
+ end
122
+
@@ -0,0 +1,73 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/thread_task'
4
+ require 'roby/test/tasks/simple_task'
5
+ require 'roby/test/tasks/empty_task'
6
+
7
+ class TC_ThreadTask < Test::Unit::TestCase
8
+ include Roby::Test
9
+
10
+ def test_normal
11
+ model = Class.new(Roby::ThreadTask) do
12
+ implementation do
13
+ 1
14
+ end
15
+ end
16
+
17
+ plan.insert(task = model.new)
18
+ task.start!
19
+ while task.thread
20
+ process_events
21
+ sleep 0.1
22
+ end
23
+
24
+ assert task.success?
25
+ assert_equal 1, task.result
26
+ end
27
+
28
+ def test_implementation_fails
29
+ Thread.abort_on_exception = false
30
+ Roby.control.abort_on_exception = false
31
+ model = Class.new(Roby::ThreadTask) do
32
+ implementation do
33
+ raise ArgumentError, "blaaaaaaaaah"
34
+ end
35
+ end
36
+
37
+ plan.discover(task = model.new)
38
+ task.start!
39
+ while task.thread
40
+ process_events
41
+ sleep 0.1
42
+ end
43
+
44
+ assert task.failed?
45
+ assert_kind_of ArgumentError, task.event(:failed).last.context.first
46
+ assert_equal nil, task.result
47
+ end
48
+
49
+ def test_interruptible
50
+ Thread.abort_on_exception = false
51
+ model = Class.new(Roby::ThreadTask) do
52
+ interruptible
53
+ implementation do
54
+ loop do
55
+ interruption_point
56
+ sleep 0.1
57
+ end
58
+ end
59
+ end
60
+
61
+ plan.discover(task = model.new)
62
+ task.start!
63
+ while task.thread
64
+ process_events
65
+ sleep 0.1
66
+ end
67
+
68
+ assert task.failed?
69
+ assert_kind_of Interrupt, task.event(:failed).last.context.first
70
+ assert_equal nil, task.result
71
+ end
72
+ end
73
+
@@ -0,0 +1,569 @@
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
+ require 'test/test_plan'
7
+
8
+ # Check that a transaction behaves like a plan
9
+ class TC_TransactionAsPlan < Test::Unit::TestCase
10
+ include TC_PlanStatic
11
+ include Roby::Test
12
+
13
+ alias :real_plan :plan
14
+ attr_reader :plan
15
+ def setup
16
+ @plan = Transaction.new(real_plan)
17
+ super
18
+ end
19
+ def teardown
20
+ @plan.discard_transaction
21
+ real_plan.clear
22
+ super
23
+ end
24
+ end
25
+
26
+ module TC_TransactionBehaviour
27
+ include Roby::Transactions
28
+
29
+ Hierarchy = Roby::TaskStructure::Hierarchy
30
+ PlannedBy = Roby::TaskStructure::PlannedBy
31
+ Signal = Roby::EventStructure::Signal
32
+ Forwarding = Roby::EventStructure::Forwarding
33
+
34
+ SimpleTask = Roby::Test::SimpleTask
35
+
36
+ def transaction_op(plan, op, *needed_proxies)
37
+ trsc = Roby::Transaction.new(plan)
38
+ proxies = needed_proxies.map do |o|
39
+ plan.discover(o) unless o.plan
40
+
41
+ p = trsc[o]
42
+ assert_not_equal(p, o)
43
+ p
44
+ end
45
+ yield(trsc, *proxies)
46
+
47
+ # Check that no task in trsc are in plan, and that no task of plan are in trsc
48
+ assert( (trsc.known_tasks & plan.known_tasks).empty?, (trsc.known_tasks & plan.known_tasks))
49
+
50
+ plan = trsc.plan
51
+ trsc.send(op)
52
+ assert(!trsc.plan)
53
+ assert(plan.transactions.empty?)
54
+
55
+ # Check that there is no proxy left in the graph
56
+ [[Roby::TaskStructure, Roby::Task], [Roby::EventStructure, Roby::EventGenerator]].each do |structure, klass|
57
+ structure.each_relation do |rel|
58
+ rel.each_vertex do |v|
59
+ assert_kind_of(klass, v)
60
+ end
61
+ end
62
+ end
63
+ plan.known_tasks.each do |t|
64
+ assert_kind_of(Roby::Task, t, t.class.ancestors.inspect)
65
+ end
66
+
67
+ rescue
68
+ trsc.discard_transaction rescue nil
69
+ raise
70
+ end
71
+
72
+ def transaction_commit(plan, *needed_proxies, &block)
73
+ transaction_op(plan, :commit_transaction, *needed_proxies, &block)
74
+ end
75
+ def transaction_discard(plan, *needed_proxies, &block)
76
+ transaction_op(plan, :discard_transaction, *needed_proxies, &block)
77
+ end
78
+
79
+ # Checks that model-level task relations are kept if a task is modified by a transaction
80
+ def test_commit_task
81
+ t = prepare_plan :tasks => 1
82
+ transaction_commit(plan, t) do |trsc, p|
83
+ trsc.discover(p)
84
+ assert(p.event(:start).child_object?(p.event(:updated_data), Roby::EventStructure::Precedence))
85
+ assert(p.event(:failed).child_object?(p.event(:stop), Roby::EventStructure::Forwarding))
86
+ end
87
+ assert(t.event(:start).child_object?(t.event(:updated_data), Roby::EventStructure::Precedence))
88
+ assert(t.event(:failed).child_object?(t.event(:stop), Roby::EventStructure::Forwarding))
89
+
90
+ t = prepare_plan :discover => 1
91
+ transaction_commit(plan, t) do |trsc, p|
92
+ trsc.insert(p)
93
+ end
94
+ assert(t.event(:start).child_object?(t.event(:updated_data), Roby::EventStructure::Precedence))
95
+ assert(t.event(:failed).child_object?(t.event(:stop), Roby::EventStructure::Forwarding))
96
+ end
97
+
98
+ def test_commit_arguments
99
+ (t1, t2), t = prepare_plan :discover => 2, :tasks => 1
100
+ t1.arguments[:first] = 10
101
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
102
+ p1.arguments[:first] = 20
103
+ p1.arguments[:second] = p2
104
+ trsc.discover(t)
105
+ t.arguments[:task] = p2
106
+ end
107
+
108
+ assert_equal(20, t1.arguments[:first])
109
+ assert_equal(t2, t1.arguments[:second])
110
+ assert_equal(t2, t.arguments[:task])
111
+
112
+ transaction_discard(plan, t1, t2) do |trsc, p1, p2|
113
+ p1.arguments[:first] = 10
114
+ assert_equal(p2, p1.arguments[:second])
115
+ end
116
+
117
+ assert_equal(20, t1.arguments[:first])
118
+ assert_equal(t2, t1.arguments[:second])
119
+ end
120
+
121
+ # Tests insertion and removal of tasks
122
+ def test_commit_plan_tasks
123
+ t1, (t2, t3) = prepare_plan(:missions => 1, :tasks => 2)
124
+
125
+ transaction_commit(plan, t1) do |trsc, p1|
126
+ assert(trsc.include?(p1))
127
+ assert(trsc.mission?(p1))
128
+ end
129
+
130
+ transaction_commit(plan) do |trsc|
131
+ assert(!trsc.include?(t3))
132
+ trsc.discover(t3)
133
+ assert(trsc.include?(t3))
134
+ assert(!trsc.mission?(t3))
135
+ assert(!plan.include?(t3))
136
+ assert(!plan.mission?(t3))
137
+ end
138
+ assert(plan.include?(t3))
139
+ assert(!plan.mission?(t3))
140
+
141
+ transaction_commit(plan) do |trsc|
142
+ assert(!trsc.include?(t2))
143
+ trsc.insert(t2)
144
+ assert(trsc.include?(t2))
145
+ assert(trsc.mission?(t2))
146
+ assert(!plan.include?(t2))
147
+ assert(!plan.mission?(t2))
148
+ end
149
+ assert(plan.include?(t2))
150
+ assert(plan.mission?(t2))
151
+
152
+ transaction_commit(plan, t2) do |trsc, p2|
153
+ assert(trsc.mission?(p2))
154
+ trsc.discard(p2)
155
+ assert(trsc.include?(p2))
156
+ assert(!trsc.mission?(p2))
157
+ assert(plan.include?(t2))
158
+ assert(plan.mission?(t2))
159
+ end
160
+ assert(plan.include?(t2))
161
+ assert(!plan.mission?(t2))
162
+
163
+ transaction_commit(plan, t3) do |trsc, p3|
164
+ assert(trsc.include?(p3))
165
+ trsc.remove_object(p3)
166
+ assert(!trsc.include?(p3))
167
+ assert(!trsc.wrap(t3, false))
168
+ assert(!trsc.include?(t3))
169
+ assert(plan.include?(t3))
170
+ end
171
+ assert(!plan.include?(t3))
172
+ assert(!plan.mission?(t3))
173
+
174
+ plan.permanent(t3 = Roby::Task.new)
175
+ transaction_commit(plan, t3) do |trsc, p3|
176
+ assert(trsc.permanent?(p3))
177
+ trsc.auto(t3)
178
+ assert(!trsc.permanent?(p3))
179
+ assert(plan.permanent?(t3))
180
+ end
181
+ assert(!plan.permanent?(t3))
182
+
183
+ transaction_commit(plan, t3) do |trsc, p3|
184
+ trsc.permanent(p3)
185
+ assert(trsc.permanent?(p3))
186
+ assert(!plan.permanent?(t3))
187
+ end
188
+ assert(plan.permanent?(t3))
189
+ end
190
+
191
+ def test_commit_task_relations
192
+ (t1, t2), (t3, t4) = prepare_plan(:missions => 2, :tasks => 2)
193
+ t1.realized_by t2
194
+
195
+ transaction_commit(plan) do |trsc|
196
+ trsc.discover t3
197
+ trsc.discover t4
198
+ t3.planned_by t4
199
+ end
200
+ assert(PlannedBy.linked?(t3, t4))
201
+
202
+ t = Roby::Task.new
203
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
204
+ t.realized_by p1
205
+ assert(Hierarchy.linked?(t, p1))
206
+ assert(!Hierarchy.linked?(t, t1))
207
+ end
208
+ assert(Hierarchy.linked?(t, t1))
209
+
210
+ t = Roby::Task.new
211
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
212
+ p2.realized_by t
213
+ assert(Hierarchy.linked?(p2, t))
214
+ assert(!Hierarchy.linked?(t2, t))
215
+ end
216
+ assert(Hierarchy.linked?(t2, t))
217
+
218
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
219
+ p1.remove_child_object(p2, Hierarchy)
220
+ assert(!Hierarchy.linked?(p1, p2))
221
+ assert(Hierarchy.linked?(t1, t2))
222
+ end
223
+ assert(!Hierarchy.linked?(t1, t2))
224
+
225
+ transaction_commit(plan, t3, t4) do |trsc, p3, p4|
226
+ trsc.remove_task(p3)
227
+ assert(!trsc.include?(p3))
228
+ assert(!PlannedBy.linked?(p3, p4))
229
+ assert(PlannedBy.linked?(t3, t4))
230
+ end
231
+ assert(!PlannedBy.linked?(t3, t4))
232
+ end
233
+
234
+ def test_commit_event_relations
235
+ (t1, t2), (t3, t4) = prepare_plan :missions => 2, :tasks => 2,
236
+ :model => SimpleTask
237
+ t1.on(:start, t2, :success)
238
+
239
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
240
+ trsc.discover t3
241
+ t3.event(:stop).on p2.event(:start)
242
+ assert(Signal.linked?(t3.event(:stop), p2.event(:start)))
243
+ assert(!Signal.linked?(t3.event(:stop), t2.event(:start)))
244
+ end
245
+ assert(Signal.linked?(t3.event(:stop), t2.event(:start)))
246
+
247
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
248
+ p1.event(:stop).on p2.event(:start)
249
+ assert(Signal.linked?(p1.event(:stop), p2.event(:start)))
250
+ assert(!Signal.linked?(t1.event(:stop), t2.event(:start)))
251
+ end
252
+ assert(Signal.linked?(t1.event(:stop), t2.event(:start)))
253
+
254
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
255
+ trsc.discover t4
256
+ p1.event(:stop).on t4.event(:start)
257
+ assert(Signal.linked?(p1.event(:stop), t4.event(:start)))
258
+ end
259
+ assert(Signal.linked?(t1.event(:stop), t4.event(:start)))
260
+
261
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
262
+ p1.event(:start).remove_child_object(p2.event(:success), Signal)
263
+ assert(!Signal.linked?(p1.event(:start), p2.event(:success)))
264
+ assert(Signal.linked?(t1.event(:start), t2.event(:success)))
265
+ end
266
+ assert(!Signal.linked?(t1.event(:start), t2.event(:success)))
267
+ end
268
+
269
+ def test_commit_replace
270
+ task, (planned, mission, child, r) = prepare_plan :missions => 1, :tasks => 4, :model => SimpleTask
271
+ mission.realized_by task
272
+ planned.planned_by task
273
+ task.realized_by child
274
+ task.on(:stop, mission, :stop)
275
+ task.forward(:stop, planned, :success)
276
+ task.on(:start, child, :start)
277
+
278
+ transaction_commit(plan, mission, planned, task, child) do |trsc, pm, pp, pt, pc|
279
+ trsc.replace(pt, r)
280
+
281
+ assert([r], trsc.missions.to_a)
282
+ assert(Hierarchy.linked?(pm, r))
283
+ assert(!Hierarchy.linked?(mission, r))
284
+ assert(!Hierarchy.linked?(r, pc))
285
+ assert(PlannedBy.linked?(pp, r))
286
+ assert(!PlannedBy.linked?(planned, r))
287
+
288
+ assert(Signal.linked?(r.event(:stop), pm.event(:stop)))
289
+ assert(!Signal.linked?(r.event(:stop), mission.event(:stop)))
290
+ assert(Forwarding.linked?(r.event(:stop), pp.event(:success)))
291
+ assert(!Forwarding.linked?(r.event(:stop), planned.event(:success)))
292
+ assert(!Signal.linked?(r.event(:stop), pc.event(:stop)))
293
+ assert(!Signal.linked?(r.event(:stop), mission.event(:stop)))
294
+ end
295
+ assert(Hierarchy.linked?(mission, r))
296
+ assert(!Hierarchy.linked?(mission, task))
297
+ assert(PlannedBy.linked?(planned, r))
298
+ assert(!PlannedBy.linked?(planned, task))
299
+ assert(Hierarchy.linked?(task, child))
300
+ assert(!Hierarchy.linked?(r, child))
301
+ assert(Signal.linked?(r.event(:stop), mission.event(:stop)))
302
+ assert(!Signal.linked?(task.event(:stop), mission.event(:stop)))
303
+ assert(Forwarding.linked?(r.event(:stop), planned.event(:success)))
304
+ assert(!Forwarding.linked?(task.event(:stop), planned.event(:success)))
305
+ assert(Signal.linked?(task.event(:start), child.event(:start)))
306
+ assert(!Signal.linked?(r.event(:start), child.event(:start)))
307
+ assert_equal([r], plan.missions.to_a)
308
+ end
309
+
310
+ def test_relation_validation
311
+ t1, t2 = prepare_plan :tasks => 2
312
+ transaction_commit(plan, t1) do |trsc, p1|
313
+ trsc.insert(t2)
314
+ assert_equal(plan, t1.plan)
315
+ assert_equal(trsc, p1.plan)
316
+ assert_equal(trsc, t2.plan)
317
+ assert_raises(RuntimeError) { t1.realized_by t2 }
318
+ assert_equal(plan, t1.event(:start).plan)
319
+ assert_equal(trsc, p1.event(:start).plan)
320
+ assert_equal(trsc, t2.event(:start).plan)
321
+ assert_raises(RuntimeError) { t1.event(:start).on t2.event(:start) }
322
+ end
323
+ end
324
+
325
+ def test_discard_modifications
326
+ t1, t2, t3 = prepare_plan :missions => 1, :discover => 1, :tasks => 1
327
+ t1.realized_by t2
328
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
329
+ p1.realized_by(t3)
330
+ trsc.remove_object(p1)
331
+ trsc.discard_modifications(t1)
332
+ end
333
+ assert(plan.include?(t1))
334
+ assert_equal([t2], t1.children.to_a)
335
+
336
+ t3 = SimpleTask.new
337
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
338
+ p1.realized_by t3
339
+ p1.remove_child p2
340
+ trsc.discard_modifications(t1)
341
+ end
342
+ assert(plan.include?(t1))
343
+ assert_equal([t2], t1.children.to_a)
344
+ end
345
+
346
+ def test_plan_finalized_task
347
+ t1, t2, t3 = prepare_plan :missions => 1, :discover => 1
348
+ t1.realized_by t2
349
+
350
+ t3 = SimpleTask.new
351
+ assert_raises(Roby::InvalidTransaction) do
352
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
353
+ p1.realized_by(t3)
354
+ assert(trsc.wrap(t1, false))
355
+ plan.remove_object(t1)
356
+ assert(trsc.invalid?)
357
+ assert(!trsc.wrap(t1, false))
358
+ end
359
+ end
360
+ end
361
+
362
+ def test_plan_add_remove_invalidate
363
+ t1 = prepare_plan :discover => 1
364
+ assert_raises(Roby::InvalidTransaction) do
365
+ transaction_commit(plan, t1) do |trsc, p1|
366
+ trsc.conflict_solver = :invalidate
367
+ plan.remove_object(t1)
368
+ assert(trsc.invalid?)
369
+ end
370
+ end
371
+
372
+ t1 = prepare_plan :discover => 1
373
+ assert_nothing_raised do
374
+ transaction_commit(plan, t1) do |trsc, p1|
375
+ trsc.conflict_solver = :invalidate
376
+ trsc.remove_object(p1)
377
+ plan.remove_object(t1)
378
+ assert(!trsc.invalid?)
379
+ end
380
+ end
381
+ end
382
+
383
+ def test_plan_relation_update_invalidate
384
+ t1, t2 = prepare_plan :discover => 2
385
+
386
+ t1.realized_by t2
387
+ assert_raises(Roby::InvalidTransaction) do
388
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
389
+ trsc.conflict_solver = :invalidate
390
+ assert(p1.child_object?(p2, Roby::TaskStructure::Hierarchy))
391
+ t1.remove_child t2
392
+ assert(trsc.invalid?)
393
+ end
394
+ end
395
+
396
+ t1.realized_by t2
397
+ assert_nothing_raised do
398
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
399
+ trsc.conflict_solver = :invalidate
400
+ p1.remove_child p2
401
+ t1.remove_child t2
402
+ assert(!trsc.invalid?)
403
+ end
404
+ end
405
+
406
+ t1.remove_child t2
407
+ assert_raises(Roby::InvalidTransaction) do
408
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
409
+ trsc.conflict_solver = :invalidate
410
+ t1.realized_by(t2)
411
+ assert(trsc.invalid?)
412
+ end
413
+ end
414
+
415
+ t1.remove_child t2
416
+ assert_nothing_raised do
417
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
418
+ trsc.conflict_solver = :invalidate
419
+ p1.realized_by p2
420
+ t1.realized_by t2
421
+ assert(!trsc.invalid?)
422
+ end
423
+ end
424
+ end
425
+
426
+ def test_plan_relation_update_solver
427
+ solver = Roby::SolverIgnoreUpdate.new
428
+
429
+ t1, t2, t3 = (1..3).map { SimpleTask.new }
430
+ t1.realized_by t2
431
+ plan.insert(t1)
432
+
433
+ assert_nothing_raised do
434
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
435
+ trsc.conflict_solver = solver
436
+ p1.realized_by(t3)
437
+ t1.remove_child(t2)
438
+ assert(!trsc.invalid?)
439
+ end
440
+ end
441
+
442
+ t3 = SimpleTask.new
443
+ t1.remove_child t2
444
+ assert_nothing_raised do
445
+ transaction_commit(plan, t1) do |trsc, p1|
446
+ trsc.conflict_solver = solver
447
+ p1.realized_by(t3)
448
+ t1.realized_by(t2)
449
+ assert(!trsc.invalid?)
450
+ end
451
+ end
452
+ end
453
+
454
+ def test_plan_relation_update_update
455
+ t1, t2, t3 = (1..3).map { SimpleTask.new }
456
+ t1.realized_by t2
457
+ plan.insert(t1)
458
+
459
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
460
+ trsc.conflict_solver = :update
461
+ p1.realized_by(t3)
462
+ assert(p1.child_object?(p2))
463
+ t1.remove_child(t2)
464
+ assert(!trsc.invalid?)
465
+ assert(!p1.child_object?(p2))
466
+ end
467
+
468
+ t3 = SimpleTask.new
469
+ t1.remove_child t2
470
+ transaction_commit(plan, t1, t2) do |trsc, p1, p2|
471
+ trsc.conflict_solver = :update
472
+ p1.realized_by(t3)
473
+ assert(!p1.child_object?(p2))
474
+
475
+ t1.realized_by(t2)
476
+ assert(p1.child_object?(p2))
477
+ assert(!trsc.invalid?)
478
+ end
479
+ end
480
+
481
+ end
482
+
483
+ class TC_Transactions < Test::Unit::TestCase
484
+ include TC_TransactionBehaviour
485
+ include Roby::Test
486
+
487
+ def test_and_event_aggregator
488
+ t1, t2, t3 = (1..3).map { SimpleTask.new }
489
+ transaction_commit(plan, t1) do |trsc, p1|
490
+ trsc.insert(t2)
491
+ trsc.insert(t3)
492
+ and_generator = (p1.event(:start) & t2.event(:start))
493
+ assert_equal(trsc, and_generator.plan)
494
+ and_generator.on t3.event(:start)
495
+ end
496
+
497
+ t1.start!
498
+ assert(!t3.running?)
499
+ t2.start!
500
+ assert(t3.running?)
501
+ end
502
+
503
+ def test_or_event_aggregator
504
+ t1, t2, t3 = (1..3).map { SimpleTask.new }
505
+ transaction_commit(plan, t1) do |trsc, p1|
506
+ trsc.insert(t2)
507
+ trsc.insert(t3)
508
+ (p1.event(:start) | t2.event(:start)).on t3.event(:start)
509
+ end
510
+
511
+ t1.start!
512
+ assert(t3.running?)
513
+ assert_nothing_raised { t2.start! }
514
+ end
515
+
516
+ def test_commit_event_handlers
517
+ plan.discover(e = Roby::EventGenerator.new(true))
518
+ def e.called_by_handler(mock)
519
+ mock.called_by_handler
520
+ end
521
+
522
+ FlexMock.use do |mock|
523
+ transaction_commit(plan, e) do |trsc, pe|
524
+ pe.on { mock.handler_called }
525
+ pe.on { pe.called_by_handler(mock) }
526
+ end
527
+
528
+ mock.should_receive(:handler_called).once
529
+ mock.should_receive(:called_by_handler).once
530
+ e.call(nil)
531
+ end
532
+ end
533
+
534
+ def test_forwarder_behaviour
535
+ t1, t2, t3 = (1..3).map { SimpleTask.new }
536
+
537
+ ev = nil
538
+ transaction_commit(plan, t1) do |trsc, p1|
539
+ ev = EventGenerator.new do
540
+ p1.forward(:start, t2, :start)
541
+ p1.on(:start, t3, :start)
542
+ end
543
+ trsc.discover(ev)
544
+ ev
545
+ end
546
+ ev.call
547
+
548
+ assert(t1.event(:start).child_object?(t2.event(:start), Roby::EventStructure::Forwarding))
549
+ assert(t1.event(:start).child_object?(t3.event(:start), Roby::EventStructure::Signal))
550
+ end
551
+ end
552
+
553
+ class TC_RecursiveTransaction < Test::Unit::TestCase
554
+ include TC_TransactionBehaviour
555
+ include Roby::Test
556
+
557
+ alias :real_plan :plan
558
+ attr_reader :plan
559
+ def setup
560
+ @plan = Roby::Transaction.new(real_plan)
561
+ super
562
+ end
563
+ def teardown
564
+ plan.discard_transaction
565
+ real_plan.clear
566
+ super
567
+ end
568
+ end
569
+