Class: Rtml::ReverseEngineering::Simulator

Inherits:
Object
  • Object
show all
Includes:
VariableLookup, Rtml::Rules::DomValidation
Defined in:
lib/rtml/reverse_engineering/simulator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tml = nil) ⇒ Simulator

Returns a new instance of Simulator.



6
7
8
# File 'lib/rtml/reverse_engineering/simulator.rb', line 6

def initialize(tml = nil)
  self.tml = tml if tml
end

Instance Attribute Details

#tmlObject

Returns the value of attribute tml.



4
5
6
# File 'lib/rtml/reverse_engineering/simulator.rb', line 4

def tml
  @tml
end

Instance Method Details

#analyze(*path) ⇒ Object

Analyzes the specified path (which can be one or more symbols and/or strings) and verifies that screens with the specified IDs are followed, in the specified order. If any screen is encountered which is NOT in the list, no error is raised as long as the next screen in the list is visited at some point. Returns one of the following values:

:completion - each screen was visited in the specified order.
:assertion  - a TML assertion error was raised in the form of the "assert" screen being visited.
:no_route   - The TML pathway did not result in the specified screens being visited in the expected order.
:dead_end   - The TML pathway ended abruptly, and did not visit all of the specified screens before doing so.
:circular   - The TML pathway was a circular route which never touched one or more nodes.
:error      - Processing ended abruptly, for an unknown reason.
a String    - The TML pathway encountered a link to an external document, and not an anchor. The String returned
              is the reference to the external document.

This method also builds the #route up, so that you can analyze the order in which screens were visited.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rtml/reverse_engineering/simulator.rb', line 48

def analyze(*path)
  raise Rtml::Errors::ScreenNotFound, "No screens found to visit in RTML document!" unless first_screen
  options = path.extract_options!
  path.flatten!
  raise ArgumentError, "Expected at least one screen ID as an argument" unless path.length > 0
  @ignore_pathlist = path.empty? || options.delete(:ignore_pathlist)
  @interaction = options.delete(:interaction) || options.delete(:interactions) || :all
  @recursion_limit = options.delete(:recursion_limit) || options.delete(:max_depth) || 150

  r = catch(:completion) do
    current = path.shift || first_screen['id']
    #route << current
    @pathlist = path
    catch(:abort) do
      trace(find_screen(current))
      :error
    end
  end
  r
end

#find_screen(id) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/rtml/reverse_engineering/simulator.rb', line 81

def find_screen(id)
  rt = screens.select { |scr| scr['id'] == id.to_s }
  raise Rtml::Errors::ScreenNotFound, "Could not find screen with ID '#{id}'" if rt.empty?
  scr = rt.shift
  raise Rtml::Errors::ScreenNotFound, "Multiple ambiguous screens found with ID '#{id}'" unless rt.empty?
  scr
end

#routeObject



14
15
16
# File 'lib/rtml/reverse_engineering/simulator.rb', line 14

def route
  @stack.last ? @stack.last[4] : []
end

#set(values) ⇒ Object



10
11
12
# File 'lib/rtml/reverse_engineering/simulator.rb', line 10

def set(values)
  variables.merge!(values.with_indifferent_access)
end

#visit(screen_name = nil) ⇒ Object

Visits the specified screen. Evaluates variable assignments and follows TML logical flow, but does not interact with hotkeys, hyperlinks, etc.

Timeouts are not evaluated because they usually indicate that some interaction is required by the user.

The return value is the last screen to be visited with the above exceptions. Circular paths return the last screen in the path before it would loop over; external references return the URL of the reference.



25
26
27
28
29
30
# File 'lib/rtml/reverse_engineering/simulator.rb', line 25

def visit(screen_name = nil)
  raise Rtml::Errors::ScreenNotFound, "No screens found to visit in RTML document!" unless first_screen
  screen_name = first_screen['id'] if screen_name.blank?
  response = analyze screen_name, :ignore_pathlist => true, :interaction => :none
  response.kind_of?(Symbol) ? route.last || response : response
end