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

__capture_log(mock, level) { || ... } click to toggle source
# 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
assert_adds_error(matcher, original_exception: nil, failure_point: PlanObject) { || ... } click to toggle source

@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
assert_adds_framework_error(matcher) { || ... } click to toggle source

@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
assert_child_of(parent, child, relation, *info) click to toggle source

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
assert_droby_compatible(object, local_marshaller: self.droby_local_marshaller, remote_marshaller: self.droby_remote_marshaller, bidirectional: false) click to toggle source

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
assert_event_becomes_unreachable(generator, timeout: 5) { || ... } click to toggle source

@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
assert_event_command_failed(exception = CommandFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) click to toggle source

@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
assert_event_emission(positive = [], negative = [], msg = nil, timeout = 5, enable_scheduler: nil, garbage_collect_pass: true) { || ... } click to toggle source

@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
assert_event_emission_failed(exception = EmissionFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) click to toggle source

@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
assert_event_exception(matcher, original_exception: nil, failure_point: EventGenerator, execution_engine: nil) { || ... } click to toggle source

@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
assert_event_is_unreachable(event, reason: nil) click to toggle source

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
assert_exception_can_be_pretty_printed(e) click to toggle source

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
assert_fatal_exception(matcher, failure_point: Task, original_exception: nil, tasks: [], kill_tasks: tasks, garbage_collect: false) { || ... } click to toggle source

@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
assert_free_event_command_failed(exception = CommandFailed, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) click to toggle source

@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
assert_free_event_emission_failed(exception = EmissionFailed, original_exception: nil, failure_point: EventGenerator, &block) click to toggle source

@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
assert_free_event_exception(matcher, original_exception: nil, failure_point: EventGenerator, execution_engine: nil, &block) click to toggle source

@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
assert_free_event_exception_warning() { || ... } click to toggle source

@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
assert_handled_exception(matcher, failure_point: Task, original_exception: nil, tasks: []) { || ... } click to toggle source

@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
assert_logs_event(event_name, *args) click to toggle source

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
assert_logs_exception_with_backtrace(exception_m, logger, level) click to toggle source

@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
assert_nonfatal_exception(matcher, failure_point: Task, original_exception: nil, tasks: []) { || ... } click to toggle source

@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
assert_notifies_free_event_exception(matcher, failure_point: nil) click to toggle source

@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
assert_relative_error(expected, found, error, msg = "") click to toggle source

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
assert_same_position(expected, found, dl = 0.01, dt = 0.01, msg = "") click to toggle source

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
assert_sets_equal(expected, actual) click to toggle source

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
assert_state_machine_transition(state_machine_task, to_state: Regexp.new, timeout: 5, start: true) { || ... } click to toggle source

@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
assert_task_fails_to_start(task, matcher, failure_point: task.start_event, original_exception: nil, tasks: []) { || ... } click to toggle source

@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
assert_task_quarantined(task, timeout: 5) { || ... } click to toggle source

@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(object, level) click to toggle source

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
create_exception_matcher(localized_error_type, original_exception: nil, failure_point: nil) click to toggle source

@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
droby_local_marshaller() click to toggle source
# File lib/roby/test/assertions.rb, line 163
def droby_local_marshaller
    @droby_local_marshaller ||= DRoby::Marshal.new
end
droby_remote_marshaller() click to toggle source
# File lib/roby/test/assertions.rb, line 167
def droby_remote_marshaller
    @droby_remote_marshaller ||= DRoby::Marshal.new
end
droby_to_remote(object, local_marshaller: self.droby_local_marshaller) click to toggle source
# 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
droby_transfer(object, local_marshaller: self.droby_local_marshaller, remote_marshaller: self.droby_remote_marshaller) click to toggle source
# 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
refute_child_of(parent, child, relation) click to toggle source

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
roby_make_flexmock_exception_matcher(matcher, tasks) click to toggle source

@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
setup() click to toggle source
Calls superclass method
# File lib/roby/test/assertions.rb, line 4
def setup
    @expected_events = Array.new
    super
end
teardown() click to toggle source
Calls superclass method
# 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
validate_state_machine(task_or_action, &block) click to toggle source
# 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