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,54 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/tasks/simple_task'
4
+
5
+ class TC_PlannedBy < Test::Unit::TestCase
6
+ include Roby::Test
7
+
8
+ PlannedBy = Roby::TaskStructure::PlannedBy
9
+ SimpleTask = Roby::Test::SimpleTask
10
+ def test_replace
11
+ task, p1, p2 = prepare_plan :discover => 3
12
+ task.planned_by p1
13
+
14
+ assert_raises(ArgumentError) { task.planned_by p2 }
15
+ assert(task.child_object?(p1, PlannedBy))
16
+ assert(!task.child_object?(p2, PlannedBy))
17
+
18
+ assert_nothing_raised { task.planned_by p2, :replace => true }
19
+ assert(!task.child_object?(p1, PlannedBy))
20
+ assert(task.child_object?(p2, PlannedBy))
21
+ end
22
+
23
+ def test_check
24
+ task = Roby::Task.new
25
+ planner = Roby::Test::SimpleTask.new
26
+ task.planned_by planner
27
+ plan.permanent(task)
28
+
29
+ assert_equal([], PlannedBy.check_planning(plan))
30
+ planner.start!
31
+ assert_equal([], PlannedBy.check_planning(plan))
32
+ planner.success!
33
+ assert_equal([], PlannedBy.check_planning(plan))
34
+
35
+ task.remove_planning_task planner
36
+ planner = Roby::Test::SimpleTask.new
37
+ task.planned_by planner
38
+
39
+ assert_equal([], PlannedBy.check_planning(plan))
40
+ planner.start!
41
+ assert_equal([], PlannedBy.check_planning(plan))
42
+ planner.failed!
43
+
44
+ error = *PlannedBy.check_planning(plan)
45
+ assert_kind_of(Roby::PlanningFailedError, error)
46
+ assert_equal(planner, error.failed_task)
47
+ assert_equal(task, error.planned_task)
48
+ assert_equal(planner.terminal_event, error.failed_event)
49
+
50
+ # Clear the planned task to make test teardown happy
51
+ plan.remove_object(task)
52
+ end
53
+ end
54
+
@@ -0,0 +1,24 @@
1
+ require 'test_support'
2
+
3
+ require 'test_bgl'
4
+ require 'test_relations'
5
+ require 'test_event'
6
+ require 'test_task'
7
+ require 'test_state'
8
+
9
+ require 'test_propagation'
10
+ require 'test_exceptions'
11
+
12
+
13
+ require 'test_plan'
14
+ require 'test_query'
15
+ require 'test_transactions'
16
+ require 'test_transactions_proxy'
17
+
18
+ require 'suite_planning'
19
+ require 'suite_relations'
20
+
21
+ require 'test_control'
22
+ require 'test_interface'
23
+ require 'test_log'
24
+
@@ -0,0 +1,9 @@
1
+ require 'distributed/test_communication'
2
+ require 'distributed/test_connection'
3
+ require 'distributed/test_execution'
4
+ require 'distributed/test_mixed_plan'
5
+ require 'distributed/test_plan_notifications'
6
+ require 'distributed/test_protocol'
7
+ require 'distributed/test_query'
8
+ require 'distributed/test_remote_plan'
9
+ require 'distributed/test_transaction'
@@ -0,0 +1,3 @@
1
+ require 'planning/test_model'
2
+ require 'planning/test_task'
3
+ require 'planning/test_loops'
@@ -0,0 +1,8 @@
1
+ require 'test_relations'
2
+ require 'relations/test_hierarchy'
3
+ require 'relations/test_executed_by'
4
+ require 'relations/test_planned_by'
5
+ require 'relations/test_conflicts'
6
+
7
+ require 'relations/test_ensured'
8
+
data/test/test_bgl.rb ADDED
@@ -0,0 +1,508 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'enumerator'
4
+ require 'flexmock'
5
+
6
+ class TC_BGL < Test::Unit::TestCase
7
+ include Roby::Test
8
+ class Vertex
9
+ include BGL::Vertex
10
+ end
11
+ Graph = BGL::Graph
12
+
13
+ def test_vertex_graph_list
14
+ graph = Graph.new
15
+ v = Vertex.new
16
+ graph.insert v
17
+ assert_equal([graph], v.enum_for(:each_graph).to_a)
18
+
19
+ graph.remove v
20
+ assert_equal([], v.enum_for(:each_graph).to_a)
21
+ end
22
+
23
+ def setup_graph(vertex_count)
24
+ graph = Graph.new
25
+ vertices = (1..vertex_count).map do
26
+ graph.insert(v = Vertex.new)
27
+ v
28
+ end
29
+ [graph, vertices]
30
+ end
31
+
32
+ def test_graph_views
33
+ g = Graph.new
34
+ r = g.reverse
35
+ assert_kind_of(Graph::Reverse, r)
36
+ assert_equal(r.object_id, g.reverse.object_id)
37
+
38
+ u = g.undirected
39
+ assert_kind_of(Graph::Undirected, u)
40
+ assert_equal(u.object_id, g.undirected.object_id)
41
+ end
42
+
43
+ def test_vertex_objects
44
+ graph = Graph.new
45
+
46
+ v1 = Vertex.new
47
+ graph.insert v1
48
+ assert(graph.include?(v1))
49
+ assert_equal([v1], graph.enum_for(:each_vertex).to_a)
50
+
51
+ graph.remove v1
52
+ assert(!graph.include?(v1))
53
+ assert_equal([], graph.enum_for(:each_vertex).to_a)
54
+
55
+ g1, g2 = Graph.new, Graph.new
56
+ g1.insert(v1)
57
+ g2.insert(v1)
58
+ v1.clear_vertex
59
+ assert(!g1.include?(v1))
60
+ assert(!g2.include?(v1))
61
+ end
62
+
63
+ def test_replace
64
+ graph = Graph.new
65
+
66
+ v1, v2, v3 = (1..3).map { Vertex.new }
67
+ graph.link(v1, v2, 1)
68
+ graph.link(v2, v3, 2)
69
+
70
+ v4 = Vertex.new
71
+ graph.replace_vertex(v2, v4)
72
+ assert(! graph.linked?(v1, v2))
73
+ assert(! graph.linked?(v2, v3))
74
+ assert_equal(1, v1[v4, graph])
75
+ assert_equal(2, v4[v3, graph])
76
+ end
77
+
78
+ def test_edge_objects
79
+ g1, g2 = Graph.new, Graph.new
80
+
81
+ v1, v2, v3 = Vertex.new, Vertex.new, Vertex.new
82
+ g1.link v1, v2, 1
83
+ assert(g1.include?(v1))
84
+ assert(g1.include?(v2))
85
+ assert(g1.linked?(v1, v2))
86
+ assert(!g1.linked?(v2, v1))
87
+
88
+ g2.link v3, v2, 2
89
+ assert_raises(ArgumentError) { g2.link v3, v2, 2 }
90
+ assert_equal(2, v3[v2, g2])
91
+ v3[v2, g2] = 3
92
+ assert_equal(3, v3[v2, g2])
93
+
94
+ g2.link v1, v2, 3
95
+ assert(g1.linked?(v1, v2))
96
+ assert_equal(3, v1[v2, g2])
97
+
98
+ assert_raises(ArgumentError) { v2[v1, g1] }
99
+ assert_raises(ArgumentError) { v3[v1, g1] }
100
+ assert_raises(ArgumentError) { v1[v3, g1] }
101
+
102
+ # Test enumerators
103
+ assert_equal([[v1, v2, 1]], g1.enum_for(:each_edge).to_a)
104
+ assert_equal([v2], v1.enum_for(:each_child_vertex).to_a)
105
+
106
+ assert_equal([v1, v3].to_set, v2.enum_for(:each_parent_vertex).to_set)
107
+ assert_equal([v1, v3].to_set, v2.enum_for(:each_parent_vertex, g2).to_set)
108
+ assert_equal([v1].to_set, v2.enum_for(:each_parent_vertex, g1).to_set)
109
+
110
+ assert_equal([v2], v3.enum_for(:each_child_vertex).to_a)
111
+ assert_equal([v2], v3.enum_for(:each_child_vertex, g2).to_a)
112
+ assert_equal([], v3.enum_for(:each_child_vertex, g1).to_a)
113
+
114
+ # Test predicates
115
+ # .... on all graphs
116
+ assert(!v1.parent_vertex?(v2))
117
+ assert(v2.parent_vertex?(v1))
118
+ assert(!v2.child_vertex?(v1))
119
+ assert(v1.child_vertex?(v2))
120
+ assert(v1.related_vertex?(v2))
121
+ assert(v2.related_vertex?(v1))
122
+ assert(v3.child_vertex?(v2))
123
+ assert(v2.parent_vertex?(v3))
124
+
125
+ # .... on a specific subgraph
126
+ assert(!v2.parent_vertex?(v3, g1))
127
+ assert(v2.parent_vertex?(v3, g2))
128
+ end
129
+
130
+ def test_end_predicates
131
+ g1, g2 = Graph.new, Graph.new
132
+
133
+ v1, v2, v3, v4 = Vertex.new, Vertex.new, Vertex.new, Vertex.new
134
+ g1.link v1, v2, nil
135
+ g2.link v2, v1, nil
136
+ assert( !v1.root? )
137
+ assert( !v1.leaf? )
138
+ assert( v1.root?(g1) )
139
+ assert( v2.leaf?(g1) )
140
+
141
+ g1.link(v3, v1, nil)
142
+ assert(v3.root?)
143
+ g2.link(v3, v2, nil)
144
+ assert(v3.root?)
145
+
146
+ g1.link(v1, v4, nil)
147
+ assert(v4.leaf?)
148
+ g2.link(v2, v4, nil)
149
+ assert(v4.leaf?)
150
+ end
151
+
152
+ def assert_components(expected, found)
153
+ # Equality of set-of-set does not work, don't know why
154
+ assert_equal(expected.map { |c| c.sort_by { |e| e.object_id } }.to_set,
155
+ found.map { |c| c.sort_by { |e| e.object_id } }.to_set)
156
+ end
157
+
158
+ def test_graph_components
159
+ graph = Graph.new
160
+
161
+ vertices = (1..5).map { Vertex.new }
162
+ v5 = vertices.pop
163
+ v1, v2, v3, v4 = *vertices
164
+ vertices.each { |v| graph.insert(v) }
165
+
166
+ graph.link v1, v2, nil
167
+ assert_components([[v1, v2], [v3], [v4]], graph.components)
168
+ assert_raises(ArgumentError) { graph.components(nil, false) }
169
+ assert_components([[v1, v2]], graph.components([v1].to_value_set))
170
+ assert_components([[v5]], graph.components([v5].to_value_set))
171
+ assert_components([], graph.components([v5].to_value_set, false))
172
+ assert_components([[v2, v1]], graph.generated_subgraphs([v1].to_value_set))
173
+ assert_components([[v2, v1]], graph.generated_subgraphs([v1].to_value_set, false))
174
+ assert_components([[v2]], graph.generated_subgraphs([v2].to_value_set))
175
+ assert_components([], graph.generated_subgraphs([v2].to_value_set, false))
176
+ assert_components([[v2], [v5]], graph.generated_subgraphs([v2, v5].to_value_set))
177
+
178
+ assert_components([], graph.generated_subgraphs([v2].to_value_set, false))
179
+ assert_components([], graph.generated_subgraphs([v2].to_value_set, false))
180
+ assert_components([], graph.generated_subgraphs([v2, v5].to_value_set, false))
181
+ assert_components([[v1, v2]], graph.reverse.generated_subgraphs([v2].to_value_set))
182
+ assert_components([[v4]], graph.components([v4].to_value_set))
183
+ assert_components([], graph.components([v4].to_value_set, false))
184
+
185
+ graph.link v4, v3, nil
186
+ assert_components([[v1, v2], [v4, v3]], graph.components)
187
+ assert_components([[v2], [v3]], graph.generated_subgraphs([v2, v3].to_value_set))
188
+ assert_components([], graph.generated_subgraphs([v3, v2].to_value_set, false))
189
+ assert_components([[v1, v2], [v4, v3]], graph.reverse.generated_subgraphs([v2, v3].to_value_set))
190
+ assert_components([[v1, v2], [v4, v3]], graph.reverse.generated_subgraphs([v2, v3].to_value_set, false))
191
+ assert_components([[v3, v4]], graph.generated_subgraphs([v4].to_value_set))
192
+ assert_components([[v3, v4]], graph.generated_subgraphs([v4].to_value_set, false))
193
+
194
+ graph.link v1, v3, nil
195
+ assert_components([[v1, v2, v3, v4]], graph.components)
196
+ assert_components([[v1, v2, v3, v4]], graph.components([v1].to_value_set))
197
+
198
+ g2 = Graph.new
199
+ graph.unlink v4, v3
200
+ g2.link v4, v3, nil
201
+ assert_components([[v4]], graph.components([v4].to_value_set))
202
+ # assert_components([], graph.components([v4], false))
203
+ assert_components([[v4, v3]], g2.components([v3].to_value_set))
204
+
205
+ v5 = Vertex.new
206
+ # Check that we get a singleton component even if v5 is not in the graph
207
+ assert_components([[v5]], graph.components([v5].to_value_set))
208
+ # assert_components([], graph.components([v5], false))
209
+ end
210
+
211
+ def test_vertex_component
212
+ graph = Graph.new
213
+
214
+ vertices = (1..4).map { Vertex.new }
215
+ v1, v2, v3, v4 = *vertices
216
+ vertices.each { |v| graph.insert(v) }
217
+
218
+ graph.link v1, v2, nil
219
+ graph.link v3, v2, nil
220
+ graph.link v3, v4, nil
221
+ graph.link v2, v4, nil
222
+ assert_components([[v1, v2, v3, v4]], graph.components([v1].to_value_set))
223
+ assert_components([[v1, v2, v3, v4]], graph.components([v2].to_value_set))
224
+
225
+ g2 = Graph.new
226
+ g2.link v4, v3, nil
227
+ assert_components([[v4, v3]], g2.components([v4].to_value_set))
228
+ end
229
+
230
+ def test_dup
231
+ graph = Graph.new
232
+
233
+ vertices = (1..4).map { Vertex.new }
234
+ v1, v2, v3, v4 = *vertices
235
+ vertices.each { |v| graph.insert(v) }
236
+
237
+ graph.link v1, v2, nil
238
+ graph.link v3, v2, nil
239
+ graph.link v3, v4, nil
240
+ graph.link v2, v4, nil
241
+
242
+ copy = graph.dup
243
+ assert_not_same(copy, graph)
244
+ assert(copy.same_graph?(graph))
245
+
246
+ vertices.each do |v|
247
+ assert( [graph, copy].to_set, v.enum_for(:each_graph).to_set )
248
+ end
249
+ end
250
+
251
+ def assert_bfs_trace(expected, sets, trace)
252
+ trace = trace.to_a
253
+ current_index = 0
254
+ sets.each do |s|
255
+ s = (s..s) if Fixnum === s
256
+ range_size = s.to_a.size
257
+ assert_equal(expected[s].to_set, trace[current_index, range_size].to_set)
258
+ current_index += range_size
259
+ end
260
+ end
261
+
262
+ def test_each_bfs
263
+ graph = Graph.new
264
+
265
+ vertices = (1..4).map { Vertex.new }
266
+ v1, v2, v3, v4 = *vertices
267
+ vertices.each { |v| graph.insert(v) }
268
+
269
+ graph.link v1, v2, 1
270
+ graph.link v1, v3, 2
271
+ graph.link v2, v3, 3
272
+ graph.link v3, v4, 4
273
+ graph.link v4, v2, 5
274
+
275
+ #
276
+ # v1 ----->v3--->v4
277
+ # |-->v2--^ |
278
+ # ^---------|
279
+
280
+ trace = [
281
+ [v1, v2, 1, Graph::TREE],
282
+ [v1, v3, 2, Graph::TREE],
283
+ [v2, v3, 3, Graph::NON_TREE],
284
+ [v3, v4, 4, Graph::TREE],
285
+ [v4, v2, 5, Graph::NON_TREE]
286
+ ]
287
+ assert_bfs_trace(trace, [0..1, 2..3, 4], graph.enum_for(:each_bfs, v1, Graph::ALL))
288
+ assert_bfs_trace(trace, [0..1, 3], graph.enum_for(:each_bfs, v1, Graph::TREE))
289
+ assert_bfs_trace(trace, [2, 4], graph.enum_for(:each_bfs, v1, Graph::NON_TREE))
290
+ assert_raises(ArgumentError) { graph.each_bfs(v1, Graph::FORWARD_OR_CROSS) {} }
291
+ assert_raises(ArgumentError) { graph.each_bfs(v1, Graph::BACK) {} }
292
+ end
293
+
294
+ def assert_dfs_trace(branches, graph, enum, root, filter, check_kind = true)
295
+ branches = branches.map do |b|
296
+ b.find_all { |e| e[3] & filter != 0 }
297
+ end
298
+ trace = graph.enum_for(enum, root, filter).to_a
299
+ if !check_kind
300
+ trace.map! { |edge| edge[0..-2] }
301
+ end
302
+
303
+ begin
304
+ assert( branches.find { |b| b == trace } ) #, trace )
305
+ rescue
306
+ #pp trace
307
+ raise
308
+ end
309
+ end
310
+
311
+ def setup_test_graph(reverse)
312
+ graph = Graph.new
313
+
314
+ vertices = (1..5).map { Vertex.new }
315
+ v1, v2, v3, v4, v5 = *vertices
316
+ vertices.each { |v| graph.insert(v) }
317
+
318
+ links = [[v1, v2, 1],
319
+ [v2, v3, 2],
320
+ [v3, v4, 3],
321
+ [v4, v2, 4],
322
+ [v1, v5, 5],
323
+ [v5, v2, 6]]
324
+
325
+ links.each do |edge|
326
+ if reverse
327
+ edge[0], edge[1] = edge[1], edge[0]
328
+ end
329
+ graph.link(*edge)
330
+ end
331
+
332
+ [graph, vertices]
333
+ end
334
+
335
+ def test_linked_p
336
+ graph, vertices = setup_test_graph(false)
337
+ v1, v2, v3, v4, v5 = *vertices
338
+ assert( graph.linked?(v1, v2) )
339
+ assert( graph.linked?(v2, v3) )
340
+ assert( graph.linked?(v3, v4) )
341
+ assert( graph.linked?(v4, v2) )
342
+ assert( graph.linked?(v1, v5) )
343
+ assert( graph.linked?(v5, v2) )
344
+ assert( !graph.linked?(v2, v1) )
345
+ assert( !graph.linked?(v3, v2) )
346
+ assert( !graph.linked?(v4, v3) )
347
+ assert( !graph.linked?(v2, v4) )
348
+ assert( !graph.linked?(v5, v1) )
349
+ assert( !graph.linked?(v2, v5) )
350
+ end
351
+
352
+ def check_dfs(graph, vertices)
353
+ v1, v2, v3, v4, v5 = *vertices
354
+
355
+ traces = []
356
+ traces << [
357
+ [v1, v5, 5, Graph::TREE],
358
+ [v5, v2, 6, Graph::TREE],
359
+ [v2, v3, 2, Graph::TREE],
360
+ [v3, v4, 3, Graph::TREE],
361
+ [v4, v2, 4, Graph::BACK],
362
+ [v1, v2, 1, Graph::FORWARD_OR_CROSS]
363
+ ]
364
+ traces << [
365
+ [v1, v2, 1, Graph::TREE],
366
+ [v2, v3, 2, Graph::TREE],
367
+ [v3, v4, 3, Graph::TREE],
368
+ [v4, v2, 4, Graph::BACK],
369
+ [v1, v5, 5, Graph::TREE],
370
+ [v5, v2, 6, Graph::FORWARD_OR_CROSS]
371
+ ]
372
+ assert_dfs_trace(traces, graph, :each_dfs, v1, Graph::ALL)
373
+ assert_dfs_trace(traces, graph, :each_dfs, v1, Graph::TREE)
374
+ assert_dfs_trace(traces, graph, :each_dfs, v1, Graph::FORWARD_OR_CROSS)
375
+ assert_dfs_trace(traces, graph, :each_dfs, v1, Graph::BACK)
376
+ end
377
+
378
+ def test_each_dfs
379
+ # v1---->v2-->v3-->v4
380
+ # | ^---------|
381
+ # |-->v5--^
382
+ graph, vertices = setup_test_graph(false)
383
+ check_dfs(graph, vertices)
384
+ end
385
+ def test_reverse_each_dfs
386
+ # Build a graph so that doing #each_dfs on #reverse should yield the same result
387
+ # than in test_each_dfs
388
+ graph, vertices = setup_test_graph(true)
389
+ check_dfs(graph.reverse, vertices)
390
+ end
391
+
392
+ def test_dfs_prune
393
+ graph = Graph.new
394
+ vertices = (1..5).map { Vertex.new }
395
+ v1, v2, v3 = *vertices
396
+ vertices.each { |v| graph.insert(v) }
397
+
398
+ graph.link v1, v2, 1
399
+ graph.link v2, v3, 2
400
+ graph.link v1, v3, 1
401
+
402
+ FlexMock.use do |mock|
403
+ mock.should_receive(:found).with(v1, v2).once
404
+ mock.should_receive(:found).with(v1, v3).once
405
+ graph.each_dfs(v1, Graph::ALL) do |s, t, _, _|
406
+ mock.found(s, t)
407
+ graph.prune
408
+ end
409
+ end
410
+ end
411
+
412
+ #def test_undirected_dfs
413
+ # # v1---->v2-->v3-->v4
414
+ # # | ^---------|
415
+ # # |-->v5--^
416
+ # graph, vertices = setup_test_graph(false)
417
+ # v1, v2, v3, v4, v5 = *vertices
418
+ #
419
+ # # Do instead
420
+ # # v1---->v2
421
+ # # | ^
422
+ # # |-->v5--^
423
+ # graph.unlink(v2, v3)
424
+ # graph.unlink(v4, v2)
425
+
426
+ # traces = []
427
+ # traces << [ [v1, v2, 1], [v2, v5, 6], [v5, v1, 5] ]
428
+ # traces << [ [v1, v5, 5], [v5, v2, 6], [v2, v1, 1] ]
429
+ # assert_dfs_trace(traces, graph.undirected, :each_dfs, v2, Graph::ALL, false)
430
+ #end
431
+
432
+ def test_topological_sort
433
+ graph, (v1, v2, v3, v4) = setup_graph(4)
434
+ graph.link v1, v2, nil
435
+ graph.link v2, v3, nil
436
+ graph.link v1, v3, nil
437
+ graph.link v3, v4, nil
438
+
439
+ sort = graph.topological_sort
440
+ assert_equal([v1, v2, v3, v4], sort)
441
+
442
+ sort = [v3, v4, v2]
443
+ graph.topological_sort(sort)
444
+ assert_equal([v1, v2, v3, v4], sort)
445
+
446
+ graph.link(v4, v1, nil)
447
+ assert_raises(ArgumentError) { graph.topological_sort }
448
+ end
449
+
450
+ def test_neighborhood
451
+ # v1---->v2-->v3-->v4
452
+ # | ^---------|
453
+ # |-->v5--^
454
+ graph, vertices = setup_test_graph(false)
455
+ v1, v2, v3, v4, v5 = *vertices
456
+
457
+ neigh1 = [[v1, v2, 1], [v1, v5, 5]]
458
+ assert_equal(neigh1.to_set, graph.neighborhood(v1, 1).to_set)
459
+ neigh2 = neigh1 + [[v4, v2, 4], [v2, v3, 2], [v5, v2, 6]]
460
+ assert_equal(neigh2.to_set, graph.neighborhood(v1, 2).to_set)
461
+ neigh3 = neigh2 + [[v3, v4, 3]]
462
+ assert_equal(neigh3.to_set, graph.neighborhood(v1, 3).to_set)
463
+ end
464
+
465
+ def test_vertex_singleton
466
+ v1, v2, v3 = (1..3).map { Vertex.new }
467
+ g1, g2 = Graph.new, Graph.new
468
+
469
+ assert(v1.singleton_vertex?)
470
+ assert(v2.singleton_vertex?)
471
+ assert(v3.singleton_vertex?)
472
+ g1.link(v1, v2, nil)
473
+ assert(!v1.singleton_vertex?)
474
+ assert(!v2.singleton_vertex?)
475
+ assert(v3.singleton_vertex?)
476
+ g2.link(v1, v3, nil)
477
+ assert(!v3.singleton_vertex?)
478
+
479
+ g1.unlink(v1, v2)
480
+ assert(!v1.singleton_vertex?)
481
+ assert(v2.singleton_vertex?)
482
+ g1.link(v1, v3, nil)
483
+ g2.unlink(v1, v3)
484
+ assert(!v1.singleton_vertex?)
485
+ assert(!v3.singleton_vertex?)
486
+ g1.unlink(v1, v3)
487
+ assert(v1.singleton_vertex?)
488
+ assert(v3.singleton_vertex?)
489
+ end
490
+
491
+ def test_graph_reachable
492
+ v1, v2, v3 = (1..3).map { Vertex.new }
493
+ g = Graph.new
494
+ assert(!g.reachable?(v1, v3))
495
+ g.link v1, v2, nil
496
+ assert(!g.reachable?(v1, v3))
497
+ g.link v2, v3, nil
498
+ assert(g.reachable?(v1, v2))
499
+ assert(g.reachable?(v1, v3))
500
+ assert(!g.reachable?(v3, v1))
501
+ assert(!g.reachable?(v2, v1))
502
+
503
+ g.link(v3, v1, nil)
504
+ assert(g.reachable?(v2, v1))
505
+ assert(g.reachable?(v3, v1))
506
+ end
507
+ end
508
+