atp 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d20477f1e1e9f17a369fd66bab80a6d281ba14aa
4
- data.tar.gz: a1e3578e7ce467f355d3d977a8892dba404602bb
3
+ metadata.gz: 7f64914b7c8843db8db3ad65544769c34244a2be
4
+ data.tar.gz: 69ad71f98a175f843a851863d00937aa93c6d52a
5
5
  SHA512:
6
- metadata.gz: 24ef6ffa11c6694d9d35c9919c824dab356a60626d44e5ea24fc66eab5838c169407bd0d15d3903830a1ceee49a26f5962eedda59da0cd3e0399367e3ed9f5f2
7
- data.tar.gz: 2eb38eebf9358bb09fd17b1f08e67aecf30a1d21f3831bc06361e0bd81f942aedaa7e9e23a0c1523954ae989bc8d858b0186d3eb0957561b662137fcef6bed7e
6
+ metadata.gz: 22d183c262e97d8218ebd96db88c0c2b5a5b3dc1131240243e56e729ba358b08730fdce8db67b116ecc1a8e21934806cf8bbda95339a5a2934f14fd50e00f00a
7
+ data.tar.gz: 3659a5efe9ee71d5f4cad2df39b5c72e3d13523fff03602087d2dcdb19f8ba74e62c2931619085904cbfdd72ef7c574a627d996c89b8d61e70acbdb818599b92
@@ -1,7 +1,7 @@
1
1
  module ATP
2
2
  MAJOR = 0
3
- MINOR = 3
4
- BUGFIX = 3
3
+ MINOR = 4
4
+ BUGFIX = 0
5
5
  DEV = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
data/lib/atp.rb CHANGED
@@ -27,6 +27,7 @@ module ATP
27
27
  autoload :PostCleaner, 'atp/processors/post_cleaner'
28
28
  autoload :Marshal, 'atp/processors/marshal'
29
29
  autoload :AddIDs, 'atp/processors/add_ids'
30
+ autoload :AddSetResult, 'atp/processors/add_set_result'
30
31
  autoload :FlowID, 'atp/processors/flow_id'
31
32
  end
32
33
 
@@ -10,8 +10,8 @@ module ATP
10
10
  @context = { conditions: [] }
11
11
  end
12
12
 
13
- def flow
14
- n0(:flow)
13
+ def flow(str)
14
+ n(:flow, name(str))
15
15
  end
16
16
 
17
17
  def name(str)
@@ -81,7 +81,7 @@ module ATP
81
81
  children << on_fail(options[:on_fail]) if options[:on_fail]
82
82
  children << on_pass(options[:on_pass]) if options[:on_pass]
83
83
 
84
- children << n(:members, *nodes)
84
+ children += nodes
85
85
  group = n(:group, *children)
86
86
 
87
87
  if options[:conditions]
@@ -29,11 +29,16 @@ module ATP
29
29
 
30
30
  # Adds an empty node of the given type to the children unless another
31
31
  # node of the same type is already present
32
- def ensure_node_present(type)
32
+ def ensure_node_present(type, child_nodes = nil)
33
33
  if children.any? { |n| n.type == type }
34
34
  self
35
35
  else
36
- updated(nil, children + [n0(type)])
36
+ if child_nodes
37
+ node = n(type, *child_nodes)
38
+ else
39
+ node = n0(type)
40
+ end
41
+ updated(nil, children + [node])
37
42
  end
38
43
  end
39
44
 
@@ -58,6 +63,11 @@ module ATP
58
63
  updated(nil, children + nodes)
59
64
  end
60
65
 
66
+ # Remove the given nodes from the children
67
+ def remove(*nodes)
68
+ updated(nil, children - nodes)
69
+ end
70
+
61
71
  # Returns the first child node of the given type that is found
62
72
  def find(type)
63
73
  children.find { |c| c.try(:type) == type }
@@ -7,10 +7,12 @@ module ATP
7
7
  attr_reader :raw
8
8
  attr_accessor :id
9
9
 
10
- def initialize(program, name = nil)
10
+ def initialize(program, name = nil, options = {})
11
+ name, options = nil, name if name.is_a?(Hash)
12
+ extract_meta!(options)
11
13
  @program = program
12
14
  @name = name
13
- @raw = builder.flow
15
+ @raw = builder.flow(name)
14
16
  end
15
17
 
16
18
  # @api private
@@ -49,6 +51,7 @@ module ATP
49
51
  def group(name, options = {})
50
52
  open_groups.push([])
51
53
  yield
54
+ extract_meta!(options)
52
55
  append builder.group(name, open_groups.pop, options)
53
56
  end
54
57
 
@@ -268,9 +271,9 @@ module ATP
268
271
  end
269
272
 
270
273
  def extract_meta!(options)
271
- builder.source_file = options.delete(:source_file) if options[:source_file]
272
- builder.source_line_number = options.delete(:source_line_number) if options[:source_line_number]
273
- builder.description = options.delete(:description) if options[:description]
274
+ builder.source_file = options.delete(:source_file)
275
+ builder.source_line_number = options.delete(:source_line_number)
276
+ builder.description = options.delete(:description)
274
277
  end
275
278
 
276
279
  # For testing
@@ -21,8 +21,13 @@ module ATP
21
21
  else
22
22
  str += 'PASS'.ljust(9)
23
23
  end
24
- str += "#{node.find(:name).value}".ljust(55)
25
- str += "#{node.find(:object).value}".ljust(55)
24
+ if n = node.find(:name)
25
+ name = n.value
26
+ else
27
+ name = node.find(:object).value['Test']
28
+ end
29
+ str += "#{name}".ljust(55)
30
+ str += "#{node.find(:object).value['Test']}".ljust(55)
26
31
  str += "#{node.find(:id).value}"
27
32
  puts str
28
33
  end
@@ -4,20 +4,41 @@ module ATP
4
4
  class AddIDs < Processor
5
5
  def run(node)
6
6
  @i = 0
7
+ @existing_ids = []
8
+ @add_ids = false
9
+ # First collect all existing IDs, this is required to make sure
10
+ # that a generated ID does not clash with an existing one
11
+ process(node)
12
+ # Now run again to fill in the blanks
13
+ @add_ids = true
7
14
  process(node)
8
15
  end
9
16
 
10
17
  def on_test(node)
11
- @i += 1
12
- node = node.ensure_node_present(:id)
13
- node.updated(nil, process_all(node))
18
+ if @add_ids
19
+ node = node.ensure_node_present(:id)
20
+ node.updated(nil, process_all(node))
21
+ else
22
+ if id = node.find(:id)
23
+ @existing_ids << id.value
24
+ end
25
+ process_all(node)
26
+ end
14
27
  end
15
28
 
16
29
  def on_id(node)
17
- unless node.value
18
- node.updated(nil, ["t#{@i}"])
30
+ if @add_ids
31
+ unless node.value
32
+ node.updated(nil, [next_id])
33
+ end
19
34
  end
20
35
  end
36
+
37
+ def next_id
38
+ @i += 1
39
+ @i += 1 while @existing_ids.include?("t#{@i}")
40
+ "t#{@i}"
41
+ end
21
42
  end
22
43
  end
23
44
  end
@@ -0,0 +1,22 @@
1
+ module ATP
2
+ module Processors
3
+ # Makes sure every test node has an on_fail/set_result node,
4
+ class AddSetResult < Processor
5
+ def run(node)
6
+ process(node)
7
+ end
8
+
9
+ def on_test(node)
10
+ node = node.ensure_node_present(:on_fail)
11
+ node.updated(nil, process_all(node))
12
+ end
13
+
14
+ def on_on_fail(node)
15
+ unless node.find(:continue)
16
+ node = node.ensure_node_present(:set_result, 'fail')
17
+ end
18
+ node.updated(nil, process_all(node))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -7,14 +7,16 @@ module ATP
7
7
  # For example this AST:
8
8
  #
9
9
  # (flow
10
- # (group "g1"
10
+ # (group
11
+ # (name "g1")
11
12
  # (test
12
13
  # (name "test1"))
13
14
  # (flow-flag "bitmap" true
14
15
  # (test
15
16
  # (name "test2"))))
16
17
  # (flow-flag "bitmap" true
17
- # (group "g1"
18
+ # (group
19
+ # (name "g1")
18
20
  # (flow-flag "x" true
19
21
  # (test
20
22
  # (name "test3")))
@@ -26,7 +28,8 @@ module ATP
26
28
  # Will be optimized to this:
27
29
  #
28
30
  # (flow
29
- # (group "g1"
31
+ # (group
32
+ # (name "g1")
30
33
  # (test
31
34
  # (name "test1"))
32
35
  # (flow-flag "bitmap" true
@@ -66,7 +69,7 @@ module ATP
66
69
  name = children.shift
67
70
  state = children.shift
68
71
  remove_condition << node
69
- children = optimize_siblings(n(:temp, children))
72
+ children = extract_common_embedded_conditions(n(:temp, children))
70
73
  remove_condition.pop
71
74
  if condition_to_be_removed?(node)
72
75
  process_all(children)
@@ -79,11 +82,11 @@ module ATP
79
82
  alias_method :on_test_executed, :on_boolean_condition
80
83
  alias_method :on_job, :on_boolean_condition
81
84
 
82
- def on_condition(node)
85
+ def on_group(node)
83
86
  children = node.children.dup
84
87
  name = children.shift
85
88
  remove_condition << node
86
- children = optimize_siblings(n(:temp, children))
89
+ children = extract_common_embedded_conditions(n(:temp, children))
87
90
  remove_condition.pop
88
91
  if condition_to_be_removed?(node)
89
92
  process_all(children)
@@ -91,7 +94,6 @@ module ATP
91
94
  node.updated(nil, [name] + process_all(children))
92
95
  end
93
96
  end
94
- alias_method :on_group, :on_condition
95
97
 
96
98
  # Returns true if the given node contains the given condition within
97
99
  # its immediate children
@@ -122,58 +124,9 @@ module ATP
122
124
  end
123
125
 
124
126
  def on_flow(node)
125
- # The extract_common_embedded_conditions method can probably do the whole job,
126
- # but it might get a little complicated with regards to optimizing adjacent groups,
127
- # so have left the original logic to have the first crack and deal with the groups
128
- # for now.
129
- nodes = optimize_siblings(node)
127
+ name, *nodes = *node
130
128
  nodes = extract_common_embedded_conditions(nodes)
131
- node.updated(nil, nodes)
132
- end
133
-
134
- def on_members(node)
135
- node.updated(nil, extract_common_embedded_conditions(optimize_siblings(node)))
136
- end
137
-
138
- def optimize_siblings(top_node)
139
- children = []
140
- unprocessed_children = []
141
- current = nil
142
- last = top_node.children.size - 1
143
- top_node.to_a.each_with_index do |node, i|
144
- # If a condition has been identified in a previous node
145
- if current
146
- process_nodes = false
147
- # If this node has the current condition, then buffer it for later processing
148
- # and continue to the next node
149
- if has_condition?(current, node)
150
- unprocessed_children << node
151
- node = nil
152
- else
153
- process_nodes = true
154
- end
155
- if process_nodes || i == last
156
- remove_condition << current
157
- current_children = current.children + [process_all(unprocessed_children)].flatten
158
- unprocessed_children = []
159
- remove_condition.pop
160
- children << process(current.updated(nil, current_children))
161
- if node && (!condition?(node) || i == last)
162
- current = nil
163
- children << process(node)
164
- else
165
- current = node
166
- end
167
- end
168
- else
169
- if condition?(node) && i != last
170
- current = node
171
- else
172
- children << process(node)
173
- end
174
- end
175
- end
176
- children.flatten
129
+ node.updated(nil, [name] + nodes)
177
130
  end
178
131
 
179
132
  def extract_common_embedded_conditions(nodes)
@@ -23,18 +23,17 @@ module ATP
23
23
  alias_method :on_test_executed, :on_boolean_condition
24
24
  alias_method :on_job, :on_boolean_condition
25
25
 
26
- def on_condition(node)
26
+ def on_group(node)
27
+ sig = node.children.select { |n| [:id, :name, :on_fail, :on_pass].include?(n.try(:type)) }
27
28
  children = node.children.dup
28
- name = children.shift
29
- conditions << node.updated(nil, [name])
30
- process_all(children)
29
+ conditions << node.updated(nil, sig)
30
+ process_all(children - sig)
31
31
  conditions.pop
32
32
  end
33
33
 
34
34
  def on_test(node)
35
35
  results << [conditions.uniq, node]
36
36
  end
37
- alias_method :on_group, :on_test
38
37
  alias_method :on_log, :on_test
39
38
  alias_method :on_enable_flow_flag, :on_test
40
39
  alias_method :on_disable_flow_flag, :on_test
@@ -3,10 +3,12 @@ module ATP
3
3
  # Makes the AST safe for Marshaling
4
4
  class Marshal < Processor
5
5
  def on_object(node)
6
- if node.value.is_a?(String)
7
- node
6
+ if node.value.is_a?(String) || node.value.is_a?(Hash)
7
+ node.updated(nil, [{ 'Test' => node.value }])
8
+ elsif node.value.respond_to?(:to_meta)
9
+ node.updated(nil, [node.value.to_meta])
8
10
  else
9
- node.updated(nil, [node.value.name])
11
+ node.updated(nil, [{ 'Test' => node.value.name }])
10
12
  end
11
13
  end
12
14
  end
@@ -10,8 +10,8 @@ module ATP
10
10
  p
11
11
  end
12
12
 
13
- def flow(name)
14
- flows[name] ||= Flow.new(self, name)
13
+ def flow(name, options = {})
14
+ flows[name] ||= Flow.new(self, name, options)
15
15
  end
16
16
 
17
17
  def flows
@@ -5,32 +5,70 @@ module ATP
5
5
  # be hit when the flow is executed under the given conditions.
6
6
  class Runner < Processor
7
7
  def run(node, options = {})
8
+ options = {
9
+ evaluate_flow_flags: true,
10
+ evaluate_run_flags: true,
11
+ evaluate_set_result: true
12
+ }.merge(options)
8
13
  @options = options
9
14
  @completed = false
10
15
  @groups = []
11
- process(Processors::AddIDs.new.run(node))
16
+ @groups_on_fail = []
17
+ @groups_on_pass = []
18
+ node = Processors::AddIDs.new.run(node)
19
+ node = Processors::AddSetResult.new.run(node)
20
+ process(node)
12
21
  end
13
22
 
14
23
  def on_flow(node)
15
- @flow = []
16
- process_all(node.children)
17
- node.updated(nil, @flow)
24
+ c = open_container do
25
+ process_all(node.children)
26
+ end
27
+ node.updated(nil, c)
28
+ end
29
+
30
+ def on_name(node)
31
+ container << node
18
32
  end
19
33
 
20
34
  def on_flow_flag(node)
21
- flag, enabled, *nodes = *node
22
- flag = [flag].flatten
23
- active = flag.any? { |f| flow_flags.include?(f) }
24
- if (enabled && active) || (!enabled && !active)
25
- process_all(nodes)
35
+ if @options[:evaluate_flow_flags]
36
+ flag, enabled, *nodes = *node
37
+ flag = [flag].flatten
38
+ active = flag.any? { |f| flow_flags.include?(f) }
39
+ if (enabled && active) || (!enabled && !active)
40
+ process_all(nodes)
41
+ end
42
+ else
43
+ c = open_container do
44
+ process_all(node.children)
45
+ end
46
+ container << node.updated(nil, node.children.take(2) + c)
26
47
  end
27
48
  end
28
49
 
29
50
  def on_run_flag(node)
30
- flag, enabled, *nodes = *node
31
- flag = [flag].flatten
32
- active = flag.any? { |f| run_flags.include?(f) }
33
- if (enabled && active) || (!enabled && !active)
51
+ if @options[:evaluate_run_flags]
52
+ flag, enabled, *nodes = *node
53
+ flag = [flag].flatten
54
+ active = flag.any? { |f| run_flags.include?(f) }
55
+ if (enabled && active) || (!enabled && !active)
56
+ process_all(nodes)
57
+ end
58
+ else
59
+ c = open_container do
60
+ process_all(node.children)
61
+ end
62
+ container << node.updated(nil, node.children.take(2) + c)
63
+ end
64
+ end
65
+
66
+ # Not sure why this method is here, all test_result nodes should have been
67
+ # converted to run_flag nodes by now
68
+ def on_test_result(node)
69
+ id, passed, *nodes = *node
70
+ if (passed && !failed_test_ids.include?(id)) ||
71
+ (!passed && failed_test_ids.include?(id))
34
72
  process_all(nodes)
35
73
  end
36
74
  end
@@ -43,7 +81,19 @@ module ATP
43
81
  failed = true
44
82
  end
45
83
  end
46
- @flow << node unless completed?
84
+ # If there is a group on_fail, then remove any test specific one as that
85
+ # will be overridden
86
+ if @groups_on_fail.last
87
+ if n_on_fail = node.find(:on_fail)
88
+ node = node.remove(n_on_fail)
89
+ end
90
+ end
91
+ if @groups_on_pass.last
92
+ if n_on_pass = node.find(:on_pass)
93
+ node = node.remove(n_on_pass)
94
+ end
95
+ end
96
+ container << node unless completed?
47
97
  if failed
48
98
  # Give indication to the parent group that at least one test within it failed
49
99
  if @groups.last
@@ -51,9 +101,11 @@ module ATP
51
101
  @groups << false
52
102
  end
53
103
  if n = node.find(:on_fail)
54
- @continue = !!n.find(:continue)
104
+ # If it has been set by a parent group, don't clear it
105
+ orig = @continue
106
+ @continue ||= !!n.find(:continue)
55
107
  process_all(n)
56
- @continue = false
108
+ @continue = orig
57
109
  end
58
110
  else
59
111
  if n = node.find(:on_pass)
@@ -63,37 +115,41 @@ module ATP
63
115
  end
64
116
 
65
117
  def on_group(node)
66
- @groups << true # This will be set to false by any tests that fail within the group
67
- process_all(node.find(:members))
68
- if !@groups.pop # If failed
69
- if n = node.find(:on_fail)
70
- @continue = !!n.find(:continue)
71
- process_all(n)
72
- @continue = false
118
+ on_fail = node.find(:on_fail)
119
+ on_pass = node.find(:on_pass)
120
+ c = open_container do
121
+ @groups << true # This will be set to false by any tests that fail within the group
122
+ @groups_on_fail << on_fail
123
+ @groups_on_pass << on_pass
124
+ if on_fail
125
+ orig = @continue
126
+ @continue = !!on_fail.find(:continue)
127
+ process_all(node.children - [on_fail, on_pass])
128
+ @continue = orig
129
+ else
130
+ process_all(node.children - [on_fail, on_pass])
73
131
  end
74
- else
75
- if n = node.find(:on_pass)
76
- process_all(n)
132
+ if !@groups.pop # If failed
133
+ if on_fail
134
+ @continue = !!on_fail.find(:continue)
135
+ process_all(on_fail)
136
+ @continue = false
137
+ end
138
+ else
139
+ if on_pass
140
+ process_all(on_pass)
141
+ end
77
142
  end
143
+ @groups_on_fail.pop
144
+ @groups_on_pass.pop
78
145
  end
79
- end
80
-
81
- def on_members(node)
82
- # Do nothing, will be processed directly by the on_group handler
83
- end
84
-
85
- def on_test_result(node)
86
- id, passed, *nodes = *node
87
- if (passed && !failed_test_ids.include?(id)) ||
88
- (!passed && failed_test_ids.include?(id))
89
- process_all(nodes)
90
- end
146
+ container << node.updated(nil, c + [on_fail, on_pass])
91
147
  end
92
148
 
93
149
  def on_set_result(node)
94
150
  unless @continue
95
- @flow << node unless completed?
96
- @completed = true
151
+ container << node unless completed?
152
+ @completed = true if @options[:evaluate_set_result]
97
153
  end
98
154
  end
99
155
 
@@ -110,7 +166,7 @@ module ATP
110
166
  end
111
167
 
112
168
  def on_log(node)
113
- @flow << node unless completed?
169
+ container << node unless completed?
114
170
  end
115
171
  alias_method :on_render, :on_log
116
172
 
@@ -151,5 +207,16 @@ module ATP
151
207
  def completed?
152
208
  @completed
153
209
  end
210
+
211
+ def open_container(c = [])
212
+ @containers ||= []
213
+ @containers << c
214
+ yield
215
+ @containers.pop
216
+ end
217
+
218
+ def container
219
+ @containers.last
220
+ end
154
221
  end
155
222
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-11 00:00:00.000000000 Z
11
+ date: 2016-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -75,6 +75,7 @@ files:
75
75
  - lib/atp/parser.rb
76
76
  - lib/atp/processor.rb
77
77
  - lib/atp/processors/add_ids.rb
78
+ - lib/atp/processors/add_set_result.rb
78
79
  - lib/atp/processors/condition.rb
79
80
  - lib/atp/processors/condition_extractor.rb
80
81
  - lib/atp/processors/flow_id.rb