roby 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|