module Roby::Test::Assertions
Constants
- FlexmockExceptionMatcher
@api private
Helper matcher used to provide a better error message in the various exception assertions
- FlexmockExceptionTasks
@api private
Helper matcher used to provide a better error message in the various exception assertions
Public Instance Methods
# File lib/roby/test/assertions.rb, line 57 def __capture_log(mock, level) Roby.disable_colors if mock.respond_to?(:logger) object_logger = mock.logger else object_logger = mock end capture = Array.new original_level = object_logger.level level_value = Logger.const_get(level.upcase) if original_level > level_value object_logger.level = level_value end mock.should_receive(level). and_return do |msg| if msg.respond_to?(:to_str) capture << msg else mock.invoke_original(level) do capture << msg.call break end end end yield capture ensure Roby.enable_colors_if_available object_logger.level = original_level end
@deprecated use expect_execution { … }.to { have_error_matching … } instead
# File lib/roby/test/assertions.rb, line 395 def assert_adds_error(matcher, original_exception: nil, failure_point: PlanObject) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield }.to { have_error_matching matcher } end
@deprecated use expect_execution { … }.to { have_framework_error_matching … } instead
# File lib/roby/test/assertions.rb, line 404 def assert_adds_framework_error(matcher) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_framework_error_matching ... } instead" expect_execution { yield }.to { have_framework_error_matching matcher } end
Asserts that two tasks are in a parent-child relationship in a specific relation
@param [Roby::Task] parent the parent task @param [Roby::Task] child the child task @param [Relations::Models::Graph] relation the relation @param [#===] info optional object used to match the edge
information. Leave empty if it should not be matched. Note that giving 'nil' will match against nil
# File lib/roby/test/assertions.rb, line 122 def assert_child_of(parent, child, relation, *info) assert_same parent.relation_graphs, child.relation_graphs, "#{parent} and #{child} cannot be related as they are not acting on the same relation graphs" graph = parent.relation_graph_for(relation) assert graph.has_vertex?(parent), "#{parent} and #{child} canot be related in #{relation} as the former is not in the graph" assert graph.has_vertex?(child), "#{parent} and #{child} canot be related in #{relation} as the latter is not in the graph" assert parent.child_object?(child, relation), "#{child} is not a child of #{parent} in #{relation}" if !info.empty? assert_equal info.first, parent[child, relation], "info differs" end end
Asserts that an object can marshalled an unmarshalled by the DRoby
protocol
It does not verify that the resulting objects are equal as they usually are not
@param [Object] object the object to test against @param [DRoby::Marshal] local_marshaller the local marshaller,
which will be used to marshal 'object'
@param [DRoby::Marshal] remote_marshaller the remote marshaller,
which will be used to unmarshal the marshalled version of 'object'
@return [Object] the 'remote' object created from the unmarshalled
droby representation
# File lib/roby/test/assertions.rb, line 203 def assert_droby_compatible(object, local_marshaller: self.droby_local_marshaller, remote_marshaller: self.droby_remote_marshaller, bidirectional: false) remote_object = droby_transfer(object, local_marshaller: local_marshaller, remote_marshaller: remote_marshaller) if bidirectional local_object = droby_transfer(remote_object, local_marshaller: remote_marshaller, remote_marshaller: local_marshaller) return remote_object, local_object else return remote_object end end
@deprecated use expect_execution { … }.to { become_unreachable generator }
# File lib/roby/test/assertions.rb, line 276 def assert_event_becomes_unreachable(generator, timeout: 5, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { become_unreachable generator } instead" expect_execution { yield }.timeout(timeout). to { become_unreachable generator } end
@deprecated use expect_execution { … }.to { have_error_matching CommandFailed.match
… }
# File lib/roby/test/assertions.rb, line 307 def assert_event_command_failed(exception = CommandFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching CommandFailed.match... } instead" assert_event_exception( exception, original_exception: original_exception, failure_point: failure_point, execution_engine: execution_engine, &block) end
@deprecated use expect_execution { … }.to { emit event } instead
# File lib/roby/test/assertions.rb, line 255 def assert_event_emission(positive = [], negative = [], msg = nil, timeout = 5, enable_scheduler: nil, garbage_collect_pass: true) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { emit event } instead" expect_execution do yield if block_given? end.timeout(timeout). scheduler(enable_scheduler). garbage_collect(garbage_collect_pass). to do not_emit *Array(negative) emit *Array(positive) end end
@deprecated use expect_execution { … }.to { have_error_matching EmissionFailed.match
.… }
# File lib/roby/test/assertions.rb, line 289 def assert_event_emission_failed(exception = EmissionFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching EmissionFailed.match... } instead" assert_event_exception( exception, original_exception: original_exception, failure_point: failure_point, execution_engine: execution_engine, &block) end
@deprecated use expect_execution { … }.to { have_error_matching … }
# File lib/roby/test/assertions.rb, line 325 def assert_event_exception(matcher, original_exception: nil, failure_point: EventGenerator, execution_engine: nil) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield if block_given? }.to { have_error_matching matcher } end
Verifies that a given event is unreachable, optionally checking its unreachability reason
@return the unreachability reason
# File lib/roby/test/assertions.rb, line 105 def assert_event_is_unreachable(event, reason: nil) assert event.unreachable?, "#{event} was expected to be unreachable but is not" if reason assert(reason === event.unreachability_reason, "the unreachability of #{event} was expected to match #{reason} but it is #{event.unreachability_reason}") end event.unreachability_reason end
Checks that an exception's pretty_print method passes without exceptions
# File lib/roby/test/assertions.rb, line 28 def assert_exception_can_be_pretty_printed(e) PP.pp(e, "") # verify that the exception can be pretty-printed, all Roby exceptions should end
@deprecated use expect_execution { … }.to { have_error_matching … }
# File lib/roby/test/assertions.rb, line 344 def assert_fatal_exception(matcher, failure_point: Task, original_exception: nil, tasks: [], kill_tasks: tasks, garbage_collect: false) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield if block_given? }.garbage_collect(garbage_collect).to { have_error_matching matcher }.exception end
@deprecated use expect_execution { … }.to { have_error_matching CommandFailed.match
… }
# File lib/roby/test/assertions.rb, line 298 def assert_free_event_command_failed(exception = CommandFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching CommandFailed.match... } instead" assert_event_exception( exception, original_exception: original_exception, failure_point: failure_point, execution_engine: execution_engine, &block) end
@deprecated use expect_execution { … }.to { have_error_matching … }
# File lib/roby/test/assertions.rb, line 283 def assert_free_event_emission_failed(exception = EmissionFailed, original_exception: nil, failure_point: EventGenerator, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" assert_event_emission_failed(exception, original_exception: original_exception, failure_point: failure_point, &block) end
@deprecated use expect_execution { … }.to { have_error_matching … }
# File lib/roby/test/assertions.rb, line 316 def assert_free_event_exception(matcher, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" assert_event_exception( matcher, original_exception: original_exception, failure_point: failure_point, execution_engine: execution_engine, &block) end
@deprecated
# File lib/roby/test/assertions.rb, line 377 def assert_free_event_exception_warning Roby.warn_deprecated "#{__method__} is deprecated, and has no replacements. It is not needed when using the expect_execution harness" messages = capture_log(execution_engine, :warn) do yield end assert_equal ["1 free event exceptions"], messages end
@deprecated use expect_execution { … }.to { have_handled_error_matching … }
# File lib/roby/test/assertions.rb, line 353 def assert_handled_exception(matcher, failure_point: Task, original_exception: nil, tasks: []) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_handled_error_matching ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield if block_given? }.to { have_handled_error_matching matcher } end
Expects the event logger to receive the given message
The assertion is validated on teardown
# File lib/roby/test/assertions.rb, line 218 def assert_logs_event(event_name, *args) @expected_events << [event_name, args] end
@deprecated
# File lib/roby/test/assertions.rb, line 371 def assert_logs_exception_with_backtrace(exception_m, logger, level) flexmock(Roby).should_receive(:log_exception_with_backtrace).once. with(exception_m, logger, level) end
@deprecated use expect_execution { … }.to { have_error_matching … }
# File lib/roby/test/assertions.rb, line 362 def assert_nonfatal_exception(matcher, failure_point: Task, original_exception: nil, tasks: []) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { have_error_matching ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield }.to { have_error_matching matcher } end
@deprecated
# File lib/roby/test/assertions.rb, line 386 def assert_notifies_free_event_exception(matcher, failure_point: nil) Roby.warn_deprecated "#{__method__} is deprecated, and has no replacements. It is not needed when using the expect_execution harness" flexmock(execution_engine).should_receive(:notify_exception). with(ExecutionEngine::EXCEPTION_FREE_EVENT, *roby_make_flexmock_exception_matcher(matcher, [failure_point])). once end
This assertion fails if the relative error between found
and +expected+is more than error
# File lib/roby/test/assertions.rb, line 143 def assert_relative_error(expected, found, error, msg = "") if expected == 0 assert_in_delta(0, found, error, "comparing #{found} to #{expected} in #{msg}") else assert_in_delta(0, (found - expected) / expected, error, "comparing #{found} to #{expected} in #{msg}") end end
This assertion fails if found
and expected
are more than dl
meters apart in the x, y and z coordinates, or dt
radians apart in angles
# File lib/roby/test/assertions.rb, line 154 def assert_same_position(expected, found, dl = 0.01, dt = 0.01, msg = "") assert_relative_error(expected.x, found.x, dl, msg) assert_relative_error(expected.y, found.y, dl, msg) assert_relative_error(expected.z, found.z, dl, msg) assert_relative_error(expected.yaw, found.yaw, dt, msg) assert_relative_error(expected.pitch, found.pitch, dt, msg) assert_relative_error(expected.roll, found.roll, dt, msg) end
Better equality test for sets
It displays the difference between the two sets
# File lib/roby/test/assertions.rb, line 35 def assert_sets_equal(expected, actual) if !(diff = (expected - actual)).empty? flunk("expects two sets to be equal, but #{expected} is missing #{diff.size} expected elements:\n #{diff.to_a.map(&:to_s).join(", ")}") elsif !(diff = (actual - expected)).empty? flunk("expects two sets to be equal, but #{actual} has #{diff.size} more elements than expected:\n #{diff.to_a.map(&:to_s).join(", ")}") end end
@deprecated use {#validate_state_machine} instead
# File lib/roby/test/assertions.rb, line 457 def assert_state_machine_transition(state_machine_task, to_state: Regexp.new, timeout: 5, start: true) Roby.warn_deprecated "#{__method__} is deprecated, use #validate_state_machine instead" state_machines = state_machine_task.each_coordination_object. find_all { |obj| obj.kind_of?(Coordination::ActionStateMachine) } if state_machines.empty? raise ArgumentError, "#{state_machine_task} has no state machines" end if to_state.respond_to?(:to_str) && !to_state.end_with?('_state') to_state = "#{to_state}_state" end done = false state_machines.each do |m| m.on_transition do |_, new_state| if to_state === new_state.name done = true end end end yield if block_given? process_events_until(timeout: timeout, garbage_collect_pass: false) do done end roby_run_planner(state_machine_task) if start assert_event_emission state_machine_task.current_task_child.start_event end state_machine_task.current_task_child end
@deprecated use expect_execution { … }.to { fail_to_start … }
# File lib/roby/test/assertions.rb, line 334 def assert_task_fails_to_start(task, matcher, failure_point: task.start_event, original_exception: nil, tasks: []) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { fail_to_start ... } instead" matcher = create_exception_matcher( matcher, original_exception: original_exception, failure_point: failure_point) expect_execution { yield if block_given? }.to { fail_to_start task } task.failure_reason end
@deprecated use expect_execution { … }.to { quarantine task }
# File lib/roby/test/assertions.rb, line 269 def assert_task_quarantined(task, timeout: 5) Roby.warn_deprecated "#{__method__} is deprecated, use #expect_execution { ... }.to { quarantine task } instead" expect_execution { yield }.timeout(timeout). to { quarantine task } end
Capture log output from one logger and returns it
Note that it currently does not “de-shares” loggers
@param [Logger,#logger] a logger object, or an object that holds
one
@param [Symbol] level the name of the logging method (e.g. :warn) @return [Array<String>]
# File lib/roby/test/assertions.rb, line 51 def capture_log(object, level) FlexMock.use(object) do |mock| __capture_log(mock, level, &proc) end end
@api private
Helper method that creates a matching object for localized errors
@param [LocalizedError] localized_error_type the error model to
match
@param [Exception,nil] original_exception an original exception
to match, for exceptions that transform exceptions into other (e.g. CodeError)
@param [Task,EventGenerator] failure_point the exceptions' failure
point
@return [#===] an object that can match an execution exception
# File lib/roby/test/assertions.rb, line 236 def create_exception_matcher(localized_error_type, original_exception: nil, failure_point: nil) matcher = localized_error_type.match if original_exception matcher.with_original_exception(original_exception) end if matcher.respond_to?(:with_ruby_exception) && matcher.ruby_exception_class == Exception if original_exception matcher.with_ruby_exception(original_exception) else matcher.without_ruby_exception end end if failure_point matcher.with_origin(failure_point) end matcher end
# File lib/roby/test/assertions.rb, line 163 def droby_local_marshaller @droby_local_marshaller ||= DRoby::Marshal.new end
# File lib/roby/test/assertions.rb, line 167 def droby_remote_marshaller @droby_remote_marshaller ||= DRoby::Marshal.new end
# File lib/roby/test/assertions.rb, line 171 def droby_to_remote(object, local_marshaller: self.droby_local_marshaller) droby = local_marshaller.dump(object) dumped = begin Marshal.dump(droby) rescue Exception => e require 'roby/droby/logfile/writer' obj, exception = Roby::DRoby::Logfile::Writer.find_invalid_marshalling_object(droby) raise e, "#{obj} cannot be marshalled: #{exception.message}", exception.backtrace end Marshal.load(dumped) end
# File lib/roby/test/assertions.rb, line 183 def droby_transfer(object, local_marshaller: self.droby_local_marshaller, remote_marshaller: self.droby_remote_marshaller) loaded = droby_to_remote(object, local_marshaller: local_marshaller) remote_marshaller.local_object(loaded) end
Asserts that two tasks are not a parent-child relationship in a specific relation
# File lib/roby/test/assertions.rb, line 135 def refute_child_of(parent, child, relation) assert_same parent.relation_graphs, child.relation_graphs, "#{parent} and #{child} cannot be related as they are not acting on the same relation graphs" graph = parent.relation_graph_for(relation) refute(graph.has_vertex?(parent) && graph.has_vertex?(child) && parent.child_object?(child, relation)) end
@api private
Helper method that creates exception matchers that provide better error messages, for the benefit of the exception assertions
# File lib/roby/test/assertions.rb, line 449 def roby_make_flexmock_exception_matcher(matcher, tasks) return FlexmockExceptionMatcher.new(matcher.to_execution_exception_matcher), FlexmockExceptionTasks.new(tasks.to_set) end
# File lib/roby/test/assertions.rb, line 4 def setup @expected_events = Array.new super end
# File lib/roby/test/assertions.rb, line 9 def teardown @expected_events.each do |m, args| if !plan.event_logger.has_received_event?(m, *args) flunk("expected to receive a log event #{m}(#{args.map(&:to_s).join(", ")}) but did not. Received:\n " + plan.event_logger.received_events. find_all { |m, _, args| m.to_s !~ /timegroup/ }. map { |m, time, args| "#{m}(#{args.map(&:to_s).join(", ")})" }. join("\n ")) end end super end
# File lib/roby/test/assertions.rb, line 22 def validate_state_machine(task_or_action, &block) ValidateStateMachine.new(self, task_or_action).evaluate(&block) end