Class: Roby::Queries::ExecutionExceptionMatcher

Inherits:
Object
  • Object
show all
Includes:
DRoby::V5::Queries::ExecutionExceptionMatcherDumper
Defined in:
lib/roby/queries/execution_exception_matcher.rb,
lib/roby/droby/enable.rb

Overview

Object that allows to specify generalized matches on a Roby::ExecutionException object

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DRoby::V5::Queries::ExecutionExceptionMatcherDumper

#droby_dump

Constructor Details

#initializeExecutionExceptionMatcher

Returns a new instance of ExecutionExceptionMatcher.



15
16
17
18
19
20
# File 'lib/roby/queries/execution_exception_matcher.rb', line 15

def initialize
    @exception_matcher = LocalizedErrorMatcher.new
    @involved_tasks_matchers = []
    @expected_edges = nil
    @handled = nil
end

Instance Attribute Details

#exception_matcherLocalizedErrorMatcher (readonly)

An object that will be used to match the actual (Ruby) exception



10
11
12
# File 'lib/roby/queries/execution_exception_matcher.rb', line 10

def exception_matcher
  @exception_matcher
end

#involved_tasks_matchersArray<#===,TaskMatcher> (readonly)

An object that will be used to match the exception origin

Returns:



13
14
15
# File 'lib/roby/queries/execution_exception_matcher.rb', line 13

def involved_tasks_matchers
  @involved_tasks_matchers
end

Instance Method Details

#===(exception) ⇒ Boolean

Returns true if the given execution exception object matches self, false otherwise.

Returns:

  • (Boolean)

    true if the given execution exception object matches self, false otherwise



139
140
141
142
143
144
145
146
147
# File 'lib/roby/queries/execution_exception_matcher.rb', line 139

def ===(exception) # rubocop:disable Metrics/PerceivedComplexity
    return false unless exception.respond_to?(:to_execution_exception)

    exception = exception.to_execution_exception
    exception_matcher === exception.exception &&
        involved_tasks_matchers.all? { |m| exception.trace.any? { |t| m === t } } &&
        (!@expected_edges || (@expected_edges == exception.trace.each_edge.to_set)) &&
        (@handled.nil? || !(@handled ^ exception.handled?))
end

#describe_failed_match(exception) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/roby/queries/execution_exception_matcher.rb', line 149

def describe_failed_match(exception)
    unless exception_matcher === exception.exception
        return exception_matcher.describe_failed_match(exception.exception)
    end

    missing_involved_task = involved_tasks_matchers.find do |m|
        exception.trace.none? { |t| m === t }
    end

    if missing_involved_task
        return "#{missing_involved_task} cannot be found in "\
               "the exception trace\n"\
               "  #{exception.trace.map(&:to_s).join("\n  ")}"
    end

    nil
end

#fatalObject



50
51
52
53
# File 'lib/roby/queries/execution_exception_matcher.rb', line 50

def fatal
    exception_matcher.fatal
    self
end

#handled(flag = true) ⇒ Object



22
23
24
25
# File 'lib/roby/queries/execution_exception_matcher.rb', line 22

def handled(flag = true)
    @handled = flag
    self
end

#involving(_task_matcher) ⇒ Object

Matched exceptions must have a task in their trace that matches the given task matcher

Parameters:



94
95
96
97
# File 'lib/roby/queries/execution_exception_matcher.rb', line 94

def involving(_task_matcher)
    involved_tasks_matchers << origin_matcher
    self
end

#matches_task?(task) ⇒ Boolean

Returns:

  • (Boolean)


167
168
169
170
# File 'lib/roby/queries/execution_exception_matcher.rb', line 167

def matches_task?(task)
    involved_tasks_matchers.all? { |m| m === task } &&
        exception_matcher.matches_task?(task)
end

#not_handledObject



27
28
29
# File 'lib/roby/queries/execution_exception_matcher.rb', line 27

def not_handled
    handled(false)
end

#pretty_print(pp) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/roby/queries/execution_exception_matcher.rb', line 103

def pretty_print(pp)
    pp.text "ExecutionException("
    exception_matcher.pretty_print(pp)
    pp.text ")"
    unless involved_tasks_matchers.empty?
        pp.text ".involving("
        pp.nest(2) do
            involved_tasks_matchers.each do |m|
                pp.breakable
                m.pretty_print(pp)
            end
        end
        pp.text ")"
    end
    if @expected_edges
        pp.text ".with_trace("
        pp.nest(2) do
            @expected_edges.each do |a, b, _|
                pp.breakable
                pp.text "#{a} => #{b}"
            end
        end
        pp.text ")"
    end
    unless @handled.nil?
        if @handled
            pp.text ".handled"
        else
            pp.text ".not_handled"
        end
    end
    nil
end

#to_execution_exception_matcherObject



172
173
174
# File 'lib/roby/queries/execution_exception_matcher.rb', line 172

def to_execution_exception_matcher
    self
end

#to_sObject



99
100
101
# File 'lib/roby/queries/execution_exception_matcher.rb', line 99

def to_s
    PP.pp(self, "".dup)
end

#with_empty_traceObject



55
56
57
58
# File 'lib/roby/queries/execution_exception_matcher.rb', line 55

def with_empty_trace
    @expected_edges = Set.new
    self
end

#with_exception(exception_matcher) ⇒ Object

Sets the exception matcher object



32
33
34
35
# File 'lib/roby/queries/execution_exception_matcher.rb', line 32

def with_exception(exception_matcher)
    @exception_matcher = exception_matcher
    self
end

#with_model(exception_model) ⇒ Object

Specifies which subclass of LocalizedError this matcher should look for

Returns:

  • self



38
39
40
41
# File 'lib/roby/queries/execution_exception_matcher.rb', line 38

def with_model(exception_model)
    exception_matcher.with_model(exception_model)
    self
end

#with_origin(plan_object_matcher) ⇒ Object

Specifies a match on the error origin

The resulting match is extended, i.e. a task matcher will match the origin’s task event if the origin itself is an event.

Returns:

  • self



44
45
46
47
# File 'lib/roby/queries/execution_exception_matcher.rb', line 44

def with_origin(plan_object_matcher)
    exception_matcher.with_origin(plan_object_matcher)
    self
end

#with_trace(*edges) ⇒ Object #with_trace(edges) ⇒ Object

Match the exception trace

The trace is a representation of the exception’s propagation during Roby’s exception propagation phase. This verifies that the graph contains the edges specified by its argument

Overloads:

  • #with_trace(*edges) ⇒ Object

    Parameters:

    • edges (Array<Task>)

      specify the edges of the propagation graph two-by-two, source then sink

      @example match a graph with (source0, sink0), (source0, sink1) edges

      with_trace(source0, sink0, source0, sink1)
      
  • #with_trace(edges) ⇒ Object

    Parameters:

    • edges (Hash)

      specify edges as a mapping. Edges that share the same source must be specified as source=>[sink0, sink1]

      @example match a graph with (source0, sink0), (source0, sink1) edges

      with_trace(source0 => [sink0, sink1])
      


80
81
82
83
84
85
86
87
88
# File 'lib/roby/queries/execution_exception_matcher.rb', line 80

def with_trace(*edges)
    if edges.first.kind_of?(Hash)
        edges = edges.first.to_a.flat_map do |source, targets|
            Array(targets).flat_map { |t| [source, t] }
        end
    end
    @expected_edges = edges.each_slice(2).map { |a, b| [a, b, nil] }.to_set
    self
end