Module: DeepCover::Node::Mixin::FlowAccounting

Defined in:
lib/deep_cover/node/mixin/flow_accounting.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



6
7
8
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 6

def self.included(base)
  base.has_child_handler('%{name}_flow_entry_count')
end

Instance Method Details

#child_flow_entry_count(child, _name = nil) ⇒ Object

Returns the number of time the control flow entered this child_node. This is the responsability of the Node, not of the child. Must be refined if the parent node may have an impact on control flow (raising, branching, …)



56
57
58
59
60
61
62
63
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 56

def child_flow_entry_count(child, _name = nil)
  prev = child.previous_sibling
  if prev
    prev.flow_completion_count
  else
    flow_entry_count
  end
end

#countsObject

Returns the counts in a hash



66
67
68
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 66

def counts
  {flow_entry: flow_entry_count, flow_completion: flow_completion_count, execution: execution_count}
end

#executable?Boolean

Returns true iff it is executable. Keywords like ‘end` are not executable, but literals like `42` are executable.

Returns:

  • (Boolean)


34
35
36
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 34

def executable?
  true
end

#execution_countObject

Returns number of times the node itself was “executed”. Definition of executed depends on the node. For now at least, don’t return ‘nil`, instead return `false` in `executable?`



40
41
42
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 40

def execution_count
  flow_entry_count
end

#flow_completion_countObject

Returns the number of times the control flow succesfully left the node. This is the responsability of the child Node, never of the parent. Must be refined if the child node may have an impact on control flow (raising, branching, …)



47
48
49
50
51
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 47

def flow_completion_count
  last = children_nodes_in_flow_order.last
  return last.flow_completion_count if last
  flow_entry_count
end

#flow_entry_countObject

Returns the control flow entered the node. The control flow can then either complete normally or be interrupted

Implementation: This is always the responsibility of the parent; Nodes should not override.



21
22
23
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 21

def flow_entry_count
  parent.child_flow_entry_count(self)
end

#flow_interrupt_countObject

Returns the number of times it changed the usual control flow (e.g. raised, returned, …) Implementation: This is always deduced; Nodes should not override.



27
28
29
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 27

def flow_interrupt_count
  flow_entry_count - flow_completion_count
end

#was_executed?Boolean

Returns true iff it is executable and if was successfully executed

Returns:

  • (Boolean)


11
12
13
14
15
# File 'lib/deep_cover/node/mixin/flow_accounting.rb', line 11

def was_executed?
  # There is a rare case of non executable nodes that have important data in flow_entry_count / flow_completion_count,
  # like `if cond; end`, so make sure it's actually executable first...
  executable? && execution_count > 0
end