roby 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +7 -5
- data/Manifest.txt +91 -16
- data/README.txt +24 -24
- data/Rakefile +92 -64
- data/app/config/app.yml +42 -43
- data/app/config/init.rb +26 -0
- data/benchmark/alloc_misc.rb +123 -0
- data/benchmark/discovery_latency.rb +67 -0
- data/benchmark/garbage_collection.rb +48 -0
- data/benchmark/genom.rb +31 -0
- data/benchmark/transactions.rb +62 -0
- data/bin/roby +1 -1
- data/bin/roby-log +16 -6
- data/doc/guide/.gitignore +2 -0
- data/doc/guide/config.yaml +34 -0
- data/doc/guide/ext/init.rb +14 -0
- data/doc/guide/ext/previous_next.rb +40 -0
- data/doc/guide/ext/rdoc_links.rb +33 -0
- data/doc/guide/index.rdoc +16 -0
- data/doc/guide/overview.rdoc +62 -0
- data/doc/guide/plan_modifications.rdoc +67 -0
- data/doc/guide/src/abstraction/achieve_with.page +8 -0
- data/doc/guide/src/abstraction/forwarding.page +8 -0
- data/doc/guide/src/abstraction/hierarchy.page +19 -0
- data/doc/guide/src/abstraction/index.page +28 -0
- data/doc/guide/src/abstraction/task_models.page +13 -0
- data/doc/guide/src/basics.template +6 -0
- data/doc/guide/src/basics/app.page +139 -0
- data/doc/guide/src/basics/code_examples.page +33 -0
- data/doc/guide/src/basics/dry.page +69 -0
- data/doc/guide/src/basics/errors.page +443 -0
- data/doc/guide/src/basics/events.page +179 -0
- data/doc/guide/src/basics/hierarchy.page +275 -0
- data/doc/guide/src/basics/index.page +11 -0
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/basics/plan_objects.page +71 -0
- data/doc/guide/src/basics/relations_display.page +203 -0
- data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
- data/doc/guide/src/basics/shell.page +102 -0
- data/doc/guide/src/basics/summary.page +32 -0
- data/doc/guide/src/basics/tasks.page +357 -0
- data/doc/guide/src/basics_shell_header.txt +16 -0
- data/doc/guide/src/cycle/cycle-overview.png +0 -0
- data/doc/guide/src/cycle/cycle-overview.svg +208 -0
- data/doc/guide/src/cycle/error_handling.page +168 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
- data/doc/guide/src/cycle/garbage_collection.page +10 -0
- data/doc/guide/src/cycle/index.page +23 -0
- data/doc/guide/src/cycle/propagation.page +154 -0
- data/doc/guide/src/cycle/propagation_diamond.png +0 -0
- data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
- data/doc/guide/src/default.css +319 -0
- data/doc/guide/src/default.template +74 -0
- data/doc/guide/src/htmldoc.metainfo +20 -0
- data/doc/guide/src/htmldoc.virtual +18 -0
- data/doc/guide/src/images/bodybg.png +0 -0
- data/doc/guide/src/images/contbg.png +0 -0
- data/doc/guide/src/images/footerbg.png +0 -0
- data/doc/guide/src/images/gradient1.png +0 -0
- data/doc/guide/src/images/gradient2.png +0 -0
- data/doc/guide/src/index.page +7 -0
- data/doc/guide/src/introduction/index.page +29 -0
- data/doc/guide/src/introduction/install.page +133 -0
- data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
- data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
- data/doc/guide/src/plugins/fault_tolerance.page +44 -0
- data/doc/guide/src/plugins/index.page +11 -0
- data/doc/guide/src/plugins/subsystems.page +45 -0
- data/doc/guide/src/relations/dependency.page +89 -0
- data/doc/guide/src/relations/index.page +12 -0
- data/doc/misc/update_github +24 -0
- data/doc/tutorials/02-GoForward.rdoc +3 -3
- data/ext/graph/graph.cc +46 -0
- data/lib/roby.rb +57 -22
- data/lib/roby/app.rb +132 -112
- data/lib/roby/app/plugins/rake.rb +21 -0
- data/lib/roby/app/rake.rb +0 -7
- data/lib/roby/app/run.rb +1 -1
- data/lib/roby/app/scripts/distributed.rb +1 -2
- data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
- data/lib/roby/app/scripts/results.rb +2 -1
- data/lib/roby/app/scripts/run.rb +6 -2
- data/lib/roby/app/scripts/shell.rb +11 -11
- data/lib/roby/config.rb +1 -1
- data/lib/roby/decision_control.rb +62 -3
- data/lib/roby/distributed.rb +4 -0
- data/lib/roby/distributed/base.rb +8 -0
- data/lib/roby/distributed/communication.rb +12 -8
- data/lib/roby/distributed/connection_space.rb +61 -44
- data/lib/roby/distributed/distributed_object.rb +1 -1
- data/lib/roby/distributed/notifications.rb +22 -30
- data/lib/roby/distributed/peer.rb +13 -8
- data/lib/roby/distributed/proxy.rb +5 -5
- data/lib/roby/distributed/subscription.rb +4 -4
- data/lib/roby/distributed/transaction.rb +3 -3
- data/lib/roby/event.rb +176 -110
- data/lib/roby/exceptions.rb +12 -4
- data/lib/roby/execution_engine.rb +1604 -0
- data/lib/roby/external_process_task.rb +225 -0
- data/lib/roby/graph.rb +0 -6
- data/lib/roby/interface.rb +221 -137
- data/lib/roby/log/console.rb +5 -3
- data/lib/roby/log/data_stream.rb +94 -16
- data/lib/roby/log/dot.rb +8 -8
- data/lib/roby/log/event_stream.rb +13 -3
- data/lib/roby/log/file.rb +43 -18
- data/lib/roby/log/gui/basic_display_ui.rb +89 -0
- data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
- data/lib/roby/log/gui/data_displays.rb +4 -5
- data/lib/roby/log/gui/data_displays_ui.rb +146 -0
- data/lib/roby/log/gui/relations.rb +18 -18
- data/lib/roby/log/gui/relations_ui.rb +120 -0
- data/lib/roby/log/gui/relations_view_ui.rb +144 -0
- data/lib/roby/log/gui/replay.rb +41 -13
- data/lib/roby/log/gui/replay_controls.rb +3 -0
- data/lib/roby/log/gui/replay_controls.ui +133 -110
- data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
- data/lib/roby/log/hooks.rb +19 -18
- data/lib/roby/log/logger.rb +7 -6
- data/lib/roby/log/notifications.rb +4 -4
- data/lib/roby/log/plan_rebuilder.rb +20 -22
- data/lib/roby/log/relations.rb +44 -16
- data/lib/roby/log/server.rb +1 -4
- data/lib/roby/log/timings.rb +88 -19
- data/lib/roby/plan-object.rb +135 -11
- data/lib/roby/plan.rb +408 -224
- data/lib/roby/planning/loops.rb +32 -25
- data/lib/roby/planning/model.rb +157 -51
- data/lib/roby/planning/task.rb +47 -20
- data/lib/roby/query.rb +128 -92
- data/lib/roby/relations.rb +254 -136
- data/lib/roby/relations/conflicts.rb +6 -9
- data/lib/roby/relations/dependency.rb +358 -0
- data/lib/roby/relations/ensured.rb +0 -1
- data/lib/roby/relations/error_handling.rb +0 -1
- data/lib/roby/relations/events.rb +0 -2
- data/lib/roby/relations/executed_by.rb +26 -11
- data/lib/roby/relations/planned_by.rb +14 -14
- data/lib/roby/robot.rb +46 -0
- data/lib/roby/schedulers/basic.rb +34 -0
- data/lib/roby/standalone.rb +4 -0
- data/lib/roby/standard_errors.rb +21 -15
- data/lib/roby/state/events.rb +5 -4
- data/lib/roby/support.rb +107 -6
- data/lib/roby/task-operations.rb +23 -19
- data/lib/roby/task.rb +522 -148
- data/lib/roby/task_index.rb +80 -0
- data/lib/roby/test/common.rb +283 -44
- data/lib/roby/test/distributed.rb +53 -37
- data/lib/roby/test/testcase.rb +9 -204
- data/lib/roby/test/tools.rb +3 -3
- data/lib/roby/transactions.rb +154 -111
- data/lib/roby/transactions/proxy.rb +40 -7
- data/manifest.xml +20 -0
- data/plugins/fault_injection/README.txt +0 -3
- data/plugins/fault_injection/Rakefile +2 -8
- data/plugins/fault_injection/app.rb +1 -1
- data/plugins/fault_injection/fault_injection.rb +3 -3
- data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
- data/plugins/subsystems/README.txt +0 -3
- data/plugins/subsystems/Rakefile +2 -7
- data/plugins/subsystems/app.rb +27 -16
- data/plugins/subsystems/test/app/config/init.rb +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +1 -1
- data/plugins/subsystems/test/app/tasks/services.rb +1 -1
- data/plugins/subsystems/test/test_subsystems.rb +23 -16
- data/test/distributed/test_communication.rb +32 -15
- data/test/distributed/test_connection.rb +28 -26
- data/test/distributed/test_execution.rb +59 -54
- data/test/distributed/test_mixed_plan.rb +34 -34
- data/test/distributed/test_plan_notifications.rb +26 -26
- data/test/distributed/test_protocol.rb +57 -48
- data/test/distributed/test_query.rb +11 -7
- data/test/distributed/test_remote_plan.rb +71 -71
- data/test/distributed/test_transaction.rb +50 -47
- data/test/mockups/external_process +28 -0
- data/test/planning/test_loops.rb +163 -119
- data/test/planning/test_model.rb +3 -3
- data/test/planning/test_task.rb +27 -7
- data/test/relations/test_conflicts.rb +3 -3
- data/test/relations/test_dependency.rb +324 -0
- data/test/relations/test_ensured.rb +2 -2
- data/test/relations/test_executed_by.rb +94 -19
- data/test/relations/test_planned_by.rb +11 -9
- data/test/suite_core.rb +6 -3
- data/test/suite_distributed.rb +1 -0
- data/test/suite_planning.rb +1 -0
- data/test/suite_relations.rb +2 -2
- data/test/tasks/test_external_process.rb +126 -0
- data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
- data/test/test_bgl.rb +21 -1
- data/test/test_event.rb +229 -155
- data/test/test_exceptions.rb +79 -80
- data/test/test_execution_engine.rb +987 -0
- data/test/test_gui.rb +1 -1
- data/test/test_interface.rb +11 -5
- data/test/test_log.rb +18 -7
- data/test/test_log_server.rb +1 -0
- data/test/test_plan.rb +229 -395
- data/test/test_query.rb +193 -35
- data/test/test_relations.rb +88 -8
- data/test/test_state.rb +55 -37
- data/test/test_support.rb +1 -1
- data/test/test_task.rb +371 -218
- data/test/test_testcase.rb +32 -16
- data/test/test_transactions.rb +211 -170
- data/test/test_transactions_proxy.rb +37 -19
- metadata +169 -71
- data/.gitignore +0 -29
- data/doc/styles/allison.css +0 -314
- data/doc/styles/allison.js +0 -316
- data/doc/styles/allison.rb +0 -276
- data/doc/styles/jamis.rb +0 -593
- data/lib/roby/control.rb +0 -746
- data/lib/roby/executives/simple.rb +0 -30
- data/lib/roby/propagation.rb +0 -562
- data/lib/roby/relations/hierarchy.rb +0 -239
- data/lib/roby/transactions/updates.rb +0 -139
- data/test/relations/test_hierarchy.rb +0 -158
- data/test/test_control.rb +0 -399
- data/test/test_propagation.rb +0 -210
|
@@ -10,7 +10,6 @@ module Roby
|
|
|
10
10
|
def setup
|
|
11
11
|
super
|
|
12
12
|
|
|
13
|
-
save_collection Distributed.new_neighbours_observers
|
|
14
13
|
@old_distributed_logger_level = Distributed.logger.level
|
|
15
14
|
|
|
16
15
|
timings[:setup] = Time.now
|
|
@@ -32,7 +31,7 @@ module Roby
|
|
|
32
31
|
super
|
|
33
32
|
|
|
34
33
|
unless Distributed.peers.empty?
|
|
35
|
-
Roby.warn " still referencing #{Distributed.peers.keys}"
|
|
34
|
+
Roby::Distributed.warn " still referencing #{Distributed.peers.keys}"
|
|
36
35
|
Distributed.peers.clear
|
|
37
36
|
end
|
|
38
37
|
|
|
@@ -44,9 +43,13 @@ module Roby
|
|
|
44
43
|
@__droby_remote_id__ = nil
|
|
45
44
|
@__droby_marshalled__ = nil
|
|
46
45
|
end
|
|
46
|
+
Roby.class_eval do
|
|
47
|
+
@plan = nil
|
|
48
|
+
@engine = nil
|
|
49
|
+
end
|
|
47
50
|
|
|
48
|
-
if
|
|
49
|
-
|
|
51
|
+
if local
|
|
52
|
+
local.quit
|
|
50
53
|
end
|
|
51
54
|
|
|
52
55
|
timings[:end] = Time.now
|
|
@@ -63,64 +66,81 @@ module Roby
|
|
|
63
66
|
attr_accessor :testcase
|
|
64
67
|
|
|
65
68
|
def enable_communication
|
|
66
|
-
|
|
69
|
+
synchronize do
|
|
67
70
|
local_peer.enable_rx
|
|
68
71
|
# make sure we wake up the communication thread
|
|
69
|
-
|
|
72
|
+
finished_discovery.broadcast
|
|
70
73
|
end
|
|
71
74
|
end
|
|
72
75
|
def disable_communication
|
|
73
76
|
local_peer.disable_rx
|
|
74
77
|
end
|
|
75
78
|
def flush; local_peer.flush end
|
|
76
|
-
def process_events;
|
|
79
|
+
def process_events; engine.process_events end
|
|
77
80
|
def local_peer
|
|
78
|
-
@local_peer ||=
|
|
81
|
+
@local_peer ||= peers.find { true }.last
|
|
79
82
|
end
|
|
80
83
|
def reset_local_peer; @local_peer = nil end
|
|
81
84
|
def send_local_peer(*args); local_peer.send(*args) end
|
|
82
|
-
def wait_one_cycle;
|
|
85
|
+
def wait_one_cycle; engine.wait_one_cycle end
|
|
83
86
|
def console_logger=(value); testcase.console_logger = value end
|
|
84
87
|
def log_level=(value); Roby.logger.level = value end
|
|
85
88
|
def cleanup
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
end
|
|
89
|
+
engine.quit
|
|
90
|
+
engine.join
|
|
91
|
+
end
|
|
92
|
+
def disable_logging
|
|
93
|
+
logger = Roby::Distributed.logger
|
|
94
|
+
@orig_logger_level = logger.level
|
|
95
|
+
logger.level = Logger::UNKNOWN
|
|
96
|
+
end
|
|
97
|
+
def enable_logging
|
|
98
|
+
logger = Roby::Distributed.logger
|
|
99
|
+
logger.level = (@orig_logger_level || Logger::WARN)
|
|
100
|
+
end
|
|
89
101
|
end
|
|
90
102
|
|
|
91
103
|
# Start a central discovery service, a remote connectionspace and a local
|
|
92
104
|
# connection space. It yields the remote connection space *in the forked
|
|
93
105
|
# child* if a block is given.
|
|
94
|
-
def start_peers
|
|
106
|
+
def start_peers
|
|
95
107
|
DRb.stop_service
|
|
96
108
|
remote_process do
|
|
97
109
|
DRb.start_service DISCOVERY_SERVER, Rinda::TupleSpace.new
|
|
98
110
|
end
|
|
99
111
|
|
|
100
|
-
if
|
|
112
|
+
if engine.running?
|
|
101
113
|
begin
|
|
102
|
-
|
|
103
|
-
|
|
114
|
+
engine.quit
|
|
115
|
+
engine.join
|
|
104
116
|
rescue ControlQuitError
|
|
105
117
|
end
|
|
106
118
|
end
|
|
107
119
|
|
|
108
120
|
remote_process do
|
|
109
121
|
central_tuplespace = DRbObject.new_with_uri(DISCOVERY_SERVER)
|
|
122
|
+
|
|
110
123
|
cs = ConnectionSpace.new :ring_discovery => false,
|
|
111
|
-
:discovery_tuplespace => central_tuplespace, :name => "remote"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
:discovery_tuplespace => central_tuplespace, :name => "remote",
|
|
125
|
+
:plan => plan
|
|
126
|
+
|
|
127
|
+
getter = Class.new do
|
|
128
|
+
attr_accessor :cs
|
|
129
|
+
def get; DRbObject.new(cs) end
|
|
130
|
+
end.new
|
|
131
|
+
getter.cs = cs
|
|
132
|
+
|
|
133
|
+
Distributed.state = cs
|
|
134
|
+
|
|
135
|
+
DRb.start_service REMOTE_SERVER, getter
|
|
136
|
+
|
|
115
137
|
cs.extend RemotePeerSupport
|
|
116
138
|
cs.testcase = self
|
|
117
139
|
|
|
118
140
|
def cs.start_control_thread
|
|
119
|
-
|
|
120
|
-
Roby.control.run :detach => true
|
|
141
|
+
engine.run
|
|
121
142
|
end
|
|
122
143
|
|
|
123
|
-
Distributed.state = cs
|
|
124
144
|
yield(cs) if block_given?
|
|
125
145
|
end
|
|
126
146
|
|
|
@@ -130,14 +150,10 @@ module Roby
|
|
|
130
150
|
@local = ConnectionSpace.new :ring_discovery => false,
|
|
131
151
|
:discovery_tuplespace => central_tuplespace, :name => 'local',
|
|
132
152
|
:plan => plan
|
|
153
|
+
Distributed.state = local
|
|
133
154
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if detached_control
|
|
137
|
-
remote.start_control_thread
|
|
138
|
-
Control.event_processing << Distributed.state.method(:start_neighbour_discovery)
|
|
139
|
-
Roby.control.run :detach => true
|
|
140
|
-
end
|
|
155
|
+
remote.start_control_thread
|
|
156
|
+
engine.run
|
|
141
157
|
end
|
|
142
158
|
|
|
143
159
|
def setup_connection
|
|
@@ -153,21 +169,21 @@ module Roby
|
|
|
153
169
|
attr_reader :central_tuplespace, :remote, :remote_peer, :remote_plan, :local
|
|
154
170
|
|
|
155
171
|
# Establishes a peer to peer connection between two ConnectionSpace objects
|
|
156
|
-
def peer2peer(
|
|
172
|
+
def peer2peer(&remote_init)
|
|
157
173
|
timings[:starting_peers] = Time.now
|
|
158
|
-
start_peers(
|
|
174
|
+
start_peers(&remote_init)
|
|
159
175
|
setup_connection
|
|
160
176
|
timings[:started_peers] = Time.now
|
|
161
177
|
end
|
|
162
178
|
|
|
163
179
|
def process_events
|
|
164
|
-
if
|
|
180
|
+
if engine.running?
|
|
165
181
|
remote.wait_one_cycle
|
|
166
|
-
|
|
182
|
+
engine.wait_one_cycle
|
|
167
183
|
elsif remote_peer && !remote_peer.disconnected?
|
|
168
|
-
Roby
|
|
184
|
+
Roby.synchronize do
|
|
169
185
|
remote.process_events
|
|
170
|
-
|
|
186
|
+
engine.process_events
|
|
171
187
|
end
|
|
172
188
|
else
|
|
173
189
|
super
|
|
@@ -181,7 +197,7 @@ module Roby
|
|
|
181
197
|
remote_peer.find_tasks.with_arguments(match).each do |task|
|
|
182
198
|
assert(!found)
|
|
183
199
|
if set_permanent
|
|
184
|
-
plan.
|
|
200
|
+
plan.add_permanent(task)
|
|
185
201
|
end
|
|
186
202
|
|
|
187
203
|
found = if block_given? then yield(task)
|
data/lib/roby/test/testcase.rb
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
require 'roby'
|
|
2
|
-
require 'active_support/core_ext/string/inflections'
|
|
3
|
-
class String # :nodoc: all
|
|
4
|
-
include ActiveSupport::CoreExtensions::String::Inflections
|
|
5
|
-
end
|
|
6
|
-
|
|
7
2
|
require 'test/unit'
|
|
8
3
|
require 'roby/test/common'
|
|
9
4
|
require 'roby/test/tools'
|
|
@@ -14,196 +9,6 @@ module Roby
|
|
|
14
9
|
extend Logger::Hierarchy
|
|
15
10
|
extend Logger::Forward
|
|
16
11
|
|
|
17
|
-
@event_assertions = []
|
|
18
|
-
@waiting_threads = []
|
|
19
|
-
|
|
20
|
-
ASSERT_ANY_EVENTS_TLS = :assert_any_events
|
|
21
|
-
|
|
22
|
-
class << self
|
|
23
|
-
# A [thread, cv, positive, negative] list of event assertions
|
|
24
|
-
attr_reader :event_assertions
|
|
25
|
-
|
|
26
|
-
# Tests for events in +positive+ and +negative+ and returns
|
|
27
|
-
# the set of failing events if the assertion has finished.
|
|
28
|
-
# If the set is empty, it means that the assertion finished
|
|
29
|
-
# successfully
|
|
30
|
-
def assert_any_event_result(positive, negative)
|
|
31
|
-
if positive_ev = positive.find { |ev| ev.happened? }
|
|
32
|
-
return false, "#{positive_ev} happened"
|
|
33
|
-
end
|
|
34
|
-
failure = negative.find_all { |ev| ev.happened? }
|
|
35
|
-
unless failure.empty?
|
|
36
|
-
return true, "#{failure} happened"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
if positive.all? { |ev| ev.unreachable? }
|
|
40
|
-
return true, "all positive events are unreachable"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
nil
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# This method is inserted in the control thread to implement
|
|
47
|
-
# Assertions#assert_events
|
|
48
|
-
def check_event_assertions
|
|
49
|
-
event_assertions.delete_if do |thread, cv, positive, negative|
|
|
50
|
-
error, result = assert_any_event_result(positive, negative)
|
|
51
|
-
if !error.nil?
|
|
52
|
-
thread[ASSERT_ANY_EVENTS_TLS] = [error, result]
|
|
53
|
-
cv.broadcast
|
|
54
|
-
true
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def finalize_event_assertions
|
|
60
|
-
check_event_assertions
|
|
61
|
-
event_assertions.dup.each do |thread, *_|
|
|
62
|
-
thread.raise ControlQuitError
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# A set of threads waiting for something to happen. This is used
|
|
67
|
-
# during #teardown to make sure no threads are block indefinitely
|
|
68
|
-
attr_reader :waiting_threads
|
|
69
|
-
|
|
70
|
-
# This proc is to be called by Control when it quits. It makes sure
|
|
71
|
-
# that threads which are waiting are interrupted
|
|
72
|
-
def interrupt_waiting_threads
|
|
73
|
-
waiting_threads.dup.each do |task|
|
|
74
|
-
task.raise ControlQuitError
|
|
75
|
-
end
|
|
76
|
-
ensure
|
|
77
|
-
waiting_threads.clear
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
end
|
|
81
|
-
Roby::Control.at_cycle_end(&method(:check_event_assertions))
|
|
82
|
-
Roby::Control.finalizers << method(:finalize_event_assertions)
|
|
83
|
-
Roby::Control.finalizers << method(:interrupt_waiting_threads)
|
|
84
|
-
|
|
85
|
-
module Assertions
|
|
86
|
-
# Wait for any event in +positive+ to happen. If +negative+ is
|
|
87
|
-
# non-empty, any event happening in this set will make the
|
|
88
|
-
# assertion fail. If events in +positive+ are task events, the
|
|
89
|
-
# :stop events of the corresponding tasks are added to negative
|
|
90
|
-
# automatically.
|
|
91
|
-
#
|
|
92
|
-
# If a block is given, it is called from within the control thread
|
|
93
|
-
# after the checks are in place
|
|
94
|
-
#
|
|
95
|
-
# So, to check that a task fails, do
|
|
96
|
-
#
|
|
97
|
-
# assert_events(task.event(:fail)) do
|
|
98
|
-
# task.start!
|
|
99
|
-
# end
|
|
100
|
-
#
|
|
101
|
-
def assert_any_event(positive, negative = [], msg = nil, &block)
|
|
102
|
-
control_priority do
|
|
103
|
-
Roby.condition_variable(false) do |cv|
|
|
104
|
-
positive = Array[*positive].to_value_set
|
|
105
|
-
negative = Array[*negative].to_value_set
|
|
106
|
-
|
|
107
|
-
unreachability_reason = ValueSet.new
|
|
108
|
-
Roby::Control.synchronize do
|
|
109
|
-
positive.each do |ev|
|
|
110
|
-
ev.if_unreachable(true) do |reason|
|
|
111
|
-
unreachability_reason << reason if reason
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
error, result = Test.assert_any_event_result(positive, negative)
|
|
116
|
-
if error.nil?
|
|
117
|
-
this_thread = Thread.current
|
|
118
|
-
|
|
119
|
-
Test.event_assertions << [this_thread, cv, positive, negative]
|
|
120
|
-
Roby.once(&block) if block_given?
|
|
121
|
-
begin
|
|
122
|
-
cv.wait(Roby::Control.mutex)
|
|
123
|
-
ensure
|
|
124
|
-
Test.event_assertions.delete_if { |thread, _| thread == this_thread }
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
error, result = this_thread[ASSERT_ANY_EVENTS_TLS]
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
if error
|
|
131
|
-
if !unreachability_reason.empty?
|
|
132
|
-
msg = unreachability_reason.map do |reason|
|
|
133
|
-
if reason.respond_to?(:context)
|
|
134
|
-
context = reason.context.map do |obj|
|
|
135
|
-
if obj.kind_of?(Exception)
|
|
136
|
-
obj.full_message
|
|
137
|
-
else
|
|
138
|
-
obj.to_s
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
reason.to_s + context.join("\n ")
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
msg.join("\n ")
|
|
145
|
-
|
|
146
|
-
flunk("#{msg} all positive events are unreachable for the following reason:\n #{msg}")
|
|
147
|
-
elsif msg
|
|
148
|
-
flunk("#{msg} failed: #{result}")
|
|
149
|
-
else
|
|
150
|
-
flunk(result)
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Starts +task+ and checks it succeeds
|
|
159
|
-
def assert_succeeds(task, *args)
|
|
160
|
-
control_priority do
|
|
161
|
-
if !task.kind_of?(Roby::Task)
|
|
162
|
-
Roby.execute do
|
|
163
|
-
plan.insert(task = planner.send(task, *args))
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
assert_any_event([task.event(:success)], [], nil) do
|
|
168
|
-
plan.permanent(task)
|
|
169
|
-
task.start! if task.pending?
|
|
170
|
-
yield if block_given?
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def control_priority
|
|
176
|
-
old_priority = Thread.current.priority
|
|
177
|
-
Thread.current.priority = Roby.control.thread.priority + 1
|
|
178
|
-
|
|
179
|
-
yield
|
|
180
|
-
ensure
|
|
181
|
-
Thread.current.priority = old_priority
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# This assertion fails if the relative error between +found+ and
|
|
185
|
-
# +expected+is more than +error+
|
|
186
|
-
def assert_relative_error(expected, found, error, msg = "")
|
|
187
|
-
if expected == 0
|
|
188
|
-
assert_in_delta(0, found, error, "comparing #{found} to #{expected} in #{msg}")
|
|
189
|
-
else
|
|
190
|
-
assert_in_delta(0, (found - expected) / expected, error, "comparing #{found} to #{expected} in #{msg}")
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# This assertion fails if +found+ and +expected+ are more than +dl+
|
|
195
|
-
# meters apart in the x, y and z coordinates, or +dt+ radians apart
|
|
196
|
-
# in angles
|
|
197
|
-
def assert_same_position(expected, found, dl = 0.01, dt = 0.01, msg = "")
|
|
198
|
-
assert_relative_error(expected.x, found.x, dl, msg)
|
|
199
|
-
assert_relative_error(expected.y, found.y, dl, msg)
|
|
200
|
-
assert_relative_error(expected.z, found.z, dl, msg)
|
|
201
|
-
assert_relative_error(expected.yaw, found.yaw, dt, msg)
|
|
202
|
-
assert_relative_error(expected.pitch, found.pitch, dt, msg)
|
|
203
|
-
assert_relative_error(expected.roll, found.roll, dt, msg)
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
12
|
# This is the base class for running tests which uses a Roby control
|
|
208
13
|
# loop (i.e. plan execution).
|
|
209
14
|
#
|
|
@@ -289,8 +94,6 @@ module Roby
|
|
|
289
94
|
block.call
|
|
290
95
|
end
|
|
291
96
|
|
|
292
|
-
app.control.delete('executive')
|
|
293
|
-
|
|
294
97
|
yield if block_given?
|
|
295
98
|
end
|
|
296
99
|
|
|
@@ -300,12 +103,10 @@ module Roby
|
|
|
300
103
|
end
|
|
301
104
|
|
|
302
105
|
def setup # :nodoc:
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
106
|
+
@plan = Roby.plan
|
|
107
|
+
@engine = Roby.engine
|
|
108
|
+
@control = Roby.control
|
|
306
109
|
|
|
307
|
-
def teardown # :nodoc:
|
|
308
|
-
Roby::Test.waiting_threads.delete(Thread.current)
|
|
309
110
|
super
|
|
310
111
|
end
|
|
311
112
|
|
|
@@ -405,7 +206,9 @@ module Roby
|
|
|
405
206
|
end
|
|
406
207
|
|
|
407
208
|
def run(result) # :nodoc:
|
|
408
|
-
|
|
209
|
+
if self.class == TestCase
|
|
210
|
+
return
|
|
211
|
+
end
|
|
409
212
|
|
|
410
213
|
self.class.apply_robot_setup do
|
|
411
214
|
yield if block_given?
|
|
@@ -469,7 +272,7 @@ module Roby
|
|
|
469
272
|
# The directory into which the datasets generated by the current
|
|
470
273
|
# testcase are to be saved.
|
|
471
274
|
def dataset_prefix
|
|
472
|
-
"#{Roby.app.robot_name}-#{self.class.name.gsub('TC_', '').underscore}/, '')}"
|
|
275
|
+
"#{Roby.app.robot_name}-#{self.class.name.gsub('TC_', '').underscore}-#{@method_name.gsub(/(?:test|dataset)_/, '')}"
|
|
473
276
|
end
|
|
474
277
|
# Returns the full path of the file name into which the log file +file+
|
|
475
278
|
# should be saved to be referred to as the +dataset_name+ dataset
|
|
@@ -484,6 +287,8 @@ module Roby
|
|
|
484
287
|
flunk("dataset #{dataset_name} has not been generated: #{$!.message}")
|
|
485
288
|
end
|
|
486
289
|
|
|
290
|
+
|
|
291
|
+
|
|
487
292
|
# Saves +file+, which is taken in the log directory, in the
|
|
488
293
|
# test/datasets directory. The data set is saved as
|
|
489
294
|
# 'robot-testname-testmethod-suffix'
|
data/lib/roby/test/tools.rb
CHANGED
|
@@ -21,11 +21,11 @@ module Roby
|
|
|
21
21
|
Roby.condition_variable(true) do |cv, mt|
|
|
22
22
|
first_sample = nil
|
|
23
23
|
mt.synchronize do
|
|
24
|
-
id = Roby
|
|
24
|
+
id = Roby.every(period) do
|
|
25
25
|
result = yield
|
|
26
26
|
if result
|
|
27
27
|
if compute_time
|
|
28
|
-
result << Roby.
|
|
28
|
+
result << Roby.engine.cycle_start
|
|
29
29
|
end
|
|
30
30
|
new_sample = sample_type.new(*result)
|
|
31
31
|
|
|
@@ -43,7 +43,7 @@ module Roby
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
cv.wait(mt)
|
|
46
|
-
Roby
|
|
46
|
+
Roby.engine.remove_periodic_handler(id)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|