atp 0.8.0 → 1.0.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 +4 -4
- data/config/commands.rb +5 -7
- data/config/version.rb +2 -2
- data/lib/atp.rb +45 -14
- data/lib/atp/ast/node.rb +18 -9
- data/lib/atp/flow.rb +558 -151
- data/lib/atp/flow_api.rb +26 -0
- data/lib/atp/formatters/basic.rb +3 -1
- data/lib/atp/processor.rb +0 -16
- data/lib/atp/processors/add_ids.rb +1 -0
- data/lib/atp/processors/adjacent_if_combiner.rb +97 -0
- data/lib/atp/processors/append_to.rb +27 -0
- data/lib/atp/processors/apply_post_group_actions.rb +50 -0
- data/lib/atp/processors/condition.rb +38 -37
- data/lib/atp/processors/continue_implementer.rb +35 -0
- data/lib/atp/processors/else_remover.rb +31 -0
- data/lib/atp/processors/empty_branch_remover.rb +17 -0
- data/lib/atp/processors/extract_set_flags.rb +18 -0
- data/lib/atp/processors/flag_optimizer.rb +214 -0
- data/lib/atp/processors/flattener.rb +58 -0
- data/lib/atp/processors/flow_id.rb +10 -4
- data/lib/atp/processors/on_pass_fail_remover.rb +39 -0
- data/lib/atp/processors/one_flag_per_test.rb +79 -0
- data/lib/atp/processors/pre_cleaner.rb +13 -8
- data/lib/atp/processors/redundant_condition_remover.rb +28 -0
- data/lib/atp/processors/relationship.rb +91 -53
- data/lib/atp/runner.rb +41 -31
- data/lib/atp/validator.rb +19 -0
- data/lib/atp/validators/duplicate_ids.rb +2 -2
- data/lib/atp/validators/jobs.rb +12 -10
- data/lib/atp/validators/missing_ids.rb +14 -8
- metadata +15 -5
- data/lib/atp/ast/builder.rb +0 -397
- data/lib/atp/ast/factories.rb +0 -17
- data/lib/atp/processors/post_cleaner.rb +0 -43
@@ -0,0 +1,28 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Removes any conditions nodes that are nested within other condition
|
4
|
+
# nodes that specify the same condition
|
5
|
+
class RedundantConditionRemover < Processor
|
6
|
+
def run(node)
|
7
|
+
@conditions = []
|
8
|
+
process(node)
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_condition_node(node)
|
12
|
+
sig = [node.type, node.to_a[0]]
|
13
|
+
if @conditions.include?(sig)
|
14
|
+
flag, *nodes = *node
|
15
|
+
node.updated(:inline, process_all(nodes))
|
16
|
+
else
|
17
|
+
@conditions << sig
|
18
|
+
node = node.updated(nil, process_all(node.children))
|
19
|
+
@conditions.pop
|
20
|
+
node
|
21
|
+
end
|
22
|
+
end
|
23
|
+
ATP::Flow::CONDITION_NODE_TYPES.each do |type|
|
24
|
+
alias_method "on_#{type}", :on_condition_node unless method_defined?("on_#{type}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -11,49 +11,52 @@ module ATP
|
|
11
11
|
class ExtractTestResults < Processor
|
12
12
|
attr_reader :results
|
13
13
|
|
14
|
-
def
|
15
|
-
ids,
|
14
|
+
def on_if_failed(node)
|
15
|
+
ids, *children = *node
|
16
16
|
unless ids.is_a?(Array)
|
17
17
|
ids = [ids]
|
18
18
|
end
|
19
19
|
ids.each do |id|
|
20
20
|
results[id] ||= {}
|
21
|
-
|
22
|
-
results[id][:passed] = true
|
23
|
-
else
|
24
|
-
results[id][:failed] = true
|
25
|
-
end
|
21
|
+
results[id][:failed] = true
|
26
22
|
end
|
27
23
|
process_all(children)
|
28
24
|
end
|
25
|
+
alias_method :on_if_any_failed, :on_if_failed
|
26
|
+
alias_method :on_if_all_failed, :on_if_failed
|
29
27
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
28
|
+
def on_if_passed(node)
|
29
|
+
ids, *children = *node
|
30
|
+
unless ids.is_a?(Array)
|
31
|
+
ids = [ids]
|
32
|
+
end
|
33
|
+
ids.each do |id|
|
34
|
+
results[id] ||= {}
|
35
|
+
results[id][:passed] = true
|
36
|
+
end
|
37
|
+
process_all(children)
|
38
|
+
end
|
39
|
+
alias_method :on_if_any_passed, :on_if_passed
|
40
|
+
alias_method :on_if_all_passed, :on_if_passed
|
41
|
+
|
42
|
+
def on_if_ran(node)
|
43
|
+
id, *children = *node
|
33
44
|
results[id] ||= {}
|
34
|
-
results[id][:
|
45
|
+
results[id][:ran] = true
|
35
46
|
process_all(children)
|
36
47
|
end
|
48
|
+
alias_method :on_unless_ran, :on_if_ran
|
37
49
|
|
38
50
|
def results
|
39
51
|
@results ||= {}.with_indifferent_access
|
40
52
|
end
|
41
53
|
end
|
42
54
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
else
|
49
|
-
@first_call_done = true
|
50
|
-
t = ExtractTestResults.new
|
51
|
-
t.process(node)
|
52
|
-
@test_results = t.results || {}
|
53
|
-
result = super
|
54
|
-
@first_call_done = false
|
55
|
-
end
|
56
|
-
result
|
55
|
+
def run(node)
|
56
|
+
t = ExtractTestResults.new
|
57
|
+
t.process(node)
|
58
|
+
@test_results = t.results || {}
|
59
|
+
process(node)
|
57
60
|
end
|
58
61
|
|
59
62
|
def add_pass_flag(id, node)
|
@@ -61,7 +64,7 @@ module ATP
|
|
61
64
|
node = node.ensure_node_present(:on_fail)
|
62
65
|
node.updated(nil, node.children.map do |n|
|
63
66
|
if n.type == :on_pass
|
64
|
-
n = n.add
|
67
|
+
n = n.add node.updated(:set_flag, ["#{id}_PASSED", :auto_generated])
|
65
68
|
elsif n.type == :on_fail
|
66
69
|
n.ensure_node_present(:continue)
|
67
70
|
else
|
@@ -74,7 +77,7 @@ module ATP
|
|
74
77
|
node = node.ensure_node_present(:on_fail)
|
75
78
|
node.updated(nil, node.children.map do |n|
|
76
79
|
if n.type == :on_fail
|
77
|
-
n = n.add
|
80
|
+
n = n.add node.updated(:set_flag, ["#{id}_FAILED", :auto_generated])
|
78
81
|
n.ensure_node_present(:continue)
|
79
82
|
else
|
80
83
|
n
|
@@ -82,16 +85,27 @@ module ATP
|
|
82
85
|
end)
|
83
86
|
end
|
84
87
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
def add_ran_flags(id, node)
|
89
|
+
set_flag = node.updated(:set_flag, ["#{id}_RAN", :auto_generated])
|
90
|
+
# For a group, set a flag immediately upon entry to the group to signal that
|
91
|
+
# it ran to later tests
|
92
|
+
if node.type == :group
|
93
|
+
name, id, *nodes = *node
|
94
|
+
if id.type == :id
|
95
|
+
nodes.unshift(set_flag)
|
96
|
+
nodes.unshift(id)
|
91
97
|
else
|
92
|
-
|
98
|
+
nodes.unshift(id)
|
99
|
+
nodes.unshift(set_flag)
|
93
100
|
end
|
94
|
-
|
101
|
+
node.updated(nil, [name] + nodes)
|
102
|
+
# For a test, set a flag immediately after the referenced test has executed
|
103
|
+
# but don't change its pass/fail handling
|
104
|
+
elsif node.type == :test
|
105
|
+
node.updated(:inline, [node, set_flag])
|
106
|
+
else
|
107
|
+
fail "Don't know how to add ran flag to #{node.type}"
|
108
|
+
end
|
95
109
|
end
|
96
110
|
|
97
111
|
# Set flags depending on the result on tests which have dependents later
|
@@ -102,7 +116,7 @@ module ATP
|
|
102
116
|
if test_results[nid]
|
103
117
|
node = add_pass_flag(nid, node) if test_results[nid][:passed]
|
104
118
|
node = add_fail_flag(nid, node) if test_results[nid][:failed]
|
105
|
-
node =
|
119
|
+
node = add_ran_flags(nid, node) if test_results[nid][:ran]
|
106
120
|
end
|
107
121
|
if node.type == :group
|
108
122
|
node.updated(nil, process_all(node))
|
@@ -112,26 +126,50 @@ module ATP
|
|
112
126
|
end
|
113
127
|
alias_method :on_group, :on_test
|
114
128
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
129
|
+
def on_if_failed(node)
|
130
|
+
id, *children = *node
|
131
|
+
node.updated(:if_flag, [id_to_flag(id, 'FAILED')] + process_all(children))
|
132
|
+
end
|
133
|
+
alias_method :on_if_any_failed, :on_if_failed
|
134
|
+
|
135
|
+
def on_if_all_failed(node)
|
136
|
+
ids, *children = *node
|
137
|
+
ids.reverse_each.with_index do |id, i|
|
138
|
+
if i == 0
|
139
|
+
node = node.updated(:if_flag, [id_to_flag(id, 'FAILED')] + process_all(children))
|
140
|
+
else
|
141
|
+
node = node.updated(:if_flag, [id_to_flag(id, 'FAILED'), node])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
node
|
145
|
+
end
|
146
|
+
|
147
|
+
def on_if_passed(node)
|
148
|
+
id, *children = *node
|
149
|
+
node.updated(:if_flag, [id_to_flag(id, 'PASSED')] + process_all(children))
|
150
|
+
end
|
151
|
+
alias_method :on_if_any_passed, :on_if_passed
|
152
|
+
|
153
|
+
def on_if_all_passed(node)
|
154
|
+
ids, *children = *node
|
155
|
+
ids.reverse_each.with_index do |id, i|
|
156
|
+
if i == 0
|
157
|
+
node = node.updated(:if_flag, [id_to_flag(id, 'PASSED')] + process_all(children))
|
158
|
+
else
|
159
|
+
node = node.updated(:if_flag, [id_to_flag(id, 'PASSED'), node])
|
160
|
+
end
|
125
161
|
end
|
162
|
+
node
|
163
|
+
end
|
164
|
+
|
165
|
+
def on_if_ran(node)
|
166
|
+
id, *children = *node
|
167
|
+
node.updated(:if_flag, [id_to_flag(id, 'RAN')] + process_all(children))
|
126
168
|
end
|
127
169
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
children = node.children.dup
|
132
|
-
id = children.shift
|
133
|
-
state = children.shift
|
134
|
-
n(:run_flag, [id_to_flag(id, 'RAN'), state] + children)
|
170
|
+
def on_unless_ran(node)
|
171
|
+
id, *children = *node
|
172
|
+
node.updated(:unless_flag, [id_to_flag(id, 'RAN')] + process_all(children))
|
135
173
|
end
|
136
174
|
|
137
175
|
# Returns the ID of the give test node (if any), caller is responsible
|
data/lib/atp/runner.rb
CHANGED
@@ -6,8 +6,8 @@ module ATP
|
|
6
6
|
class Runner < Processor
|
7
7
|
def run(node, options = {})
|
8
8
|
options = {
|
9
|
-
|
10
|
-
|
9
|
+
evaluate_enables: true,
|
10
|
+
evaluate_flags: true,
|
11
11
|
evaluate_set_result: true
|
12
12
|
}.merge(options)
|
13
13
|
@options = options
|
@@ -31,11 +31,12 @@ module ATP
|
|
31
31
|
container << node
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
if @options[:
|
36
|
-
flag,
|
34
|
+
def on_if_flag(node)
|
35
|
+
if @options[:evaluate_flags]
|
36
|
+
flag, *nodes = *node
|
37
37
|
flag = [flag].flatten
|
38
|
-
|
38
|
+
enabled = node.type == :if_flag
|
39
|
+
active = flag.any? { |f| set_flags.include?(f) }
|
39
40
|
if (enabled && active) || (!enabled && !active)
|
40
41
|
process_all(nodes)
|
41
42
|
end
|
@@ -43,15 +44,17 @@ module ATP
|
|
43
44
|
c = open_container do
|
44
45
|
process_all(node.children)
|
45
46
|
end
|
46
|
-
container << node.updated(nil, node.children.take(
|
47
|
+
container << node.updated(nil, node.children.take(1) + c)
|
47
48
|
end
|
48
49
|
end
|
50
|
+
alias_method :on_unless_flag, :on_if_flag
|
49
51
|
|
50
|
-
def
|
51
|
-
if @options[:
|
52
|
-
flag,
|
52
|
+
def on_if_enabled(node)
|
53
|
+
if @options[:evaluate_enables]
|
54
|
+
flag, *nodes = *node
|
53
55
|
flag = [flag].flatten
|
54
|
-
|
56
|
+
enabled = node.type == :if_enabled
|
57
|
+
active = flag.any? { |f| set_enables.include?(f) }
|
55
58
|
if (enabled && active) || (!enabled && !active)
|
56
59
|
process_all(nodes)
|
57
60
|
end
|
@@ -59,16 +62,21 @@ module ATP
|
|
59
62
|
c = open_container do
|
60
63
|
process_all(node.children)
|
61
64
|
end
|
62
|
-
container << node.updated(nil, node.children.take(
|
65
|
+
container << node.updated(nil, node.children.take(1) + c)
|
63
66
|
end
|
64
67
|
end
|
68
|
+
alias_method :on_unless_enabled, :on_if_enabled
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
def on_if_failed(node)
|
71
|
+
id, *nodes = *node
|
72
|
+
if failed_test_ids.include?(id)
|
73
|
+
process_all(nodes)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_if_passed(node)
|
78
|
+
id, *nodes = *node
|
79
|
+
unless failed_test_ids.include?(id)
|
72
80
|
process_all(nodes)
|
73
81
|
end
|
74
82
|
end
|
@@ -77,7 +85,7 @@ module ATP
|
|
77
85
|
if id = node.find(:id)
|
78
86
|
id = id.to_a[0]
|
79
87
|
if failed_test_ids.include?(id)
|
80
|
-
node = node.add(
|
88
|
+
node = node.add(node.updated(:failed, []))
|
81
89
|
failed = true
|
82
90
|
if n_on_fail = node.find(:on_fail)
|
83
91
|
node = node.remove(n_on_fail)
|
@@ -155,16 +163,16 @@ module ATP
|
|
155
163
|
end
|
156
164
|
end
|
157
165
|
|
158
|
-
def
|
159
|
-
|
166
|
+
def on_set_flag(node)
|
167
|
+
set_flags << node.to_a[0]
|
160
168
|
end
|
161
169
|
|
162
|
-
def
|
163
|
-
|
170
|
+
def on_enable(node)
|
171
|
+
set_enables << node.value unless set_enables.include?(node.value)
|
164
172
|
end
|
165
173
|
|
166
|
-
def
|
167
|
-
|
174
|
+
def on_disable(node)
|
175
|
+
set_enables.delete(node.value)
|
168
176
|
end
|
169
177
|
|
170
178
|
def on_log(node)
|
@@ -172,9 +180,10 @@ module ATP
|
|
172
180
|
end
|
173
181
|
alias_method :on_render, :on_log
|
174
182
|
|
175
|
-
def
|
176
|
-
jobs,
|
183
|
+
def on_if_job(node)
|
184
|
+
jobs, *nodes = *node
|
177
185
|
jobs = clean_job(jobs)
|
186
|
+
state = node.type == :if_job
|
178
187
|
unless job
|
179
188
|
fail 'Flow contains JOB-based conditions and no current JOB has been given!'
|
180
189
|
end
|
@@ -184,6 +193,7 @@ module ATP
|
|
184
193
|
process_all(node) unless jobs.include?(job)
|
185
194
|
end
|
186
195
|
end
|
196
|
+
alias_method :on_unless_job, :on_if_job
|
187
197
|
|
188
198
|
def clean_job(job)
|
189
199
|
[job].flatten.map { |j| j.to_s.upcase }
|
@@ -197,13 +207,13 @@ module ATP
|
|
197
207
|
@failed_test_ids ||= [@options[:failed_test_id] || @options[:failed_test_ids]].flatten.compact
|
198
208
|
end
|
199
209
|
|
200
|
-
def
|
201
|
-
@
|
210
|
+
def set_flags
|
211
|
+
@set_flags ||= []
|
202
212
|
end
|
203
213
|
|
204
214
|
# Returns an array of enabled flow flags
|
205
|
-
def
|
206
|
-
@
|
215
|
+
def set_enables
|
216
|
+
@set_enables ||= [@options[:enable] || @options[:enables]].flatten.compact
|
207
217
|
end
|
208
218
|
|
209
219
|
def completed?
|
data/lib/atp/validator.rb
CHANGED
@@ -3,6 +3,14 @@ module ATP
|
|
3
3
|
class Validator < Processor
|
4
4
|
attr_reader :flow
|
5
5
|
|
6
|
+
def self.testing=(value)
|
7
|
+
@testing = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.testing
|
11
|
+
@testing
|
12
|
+
end
|
13
|
+
|
6
14
|
def initialize(flow)
|
7
15
|
@flow = flow
|
8
16
|
end
|
@@ -30,5 +38,16 @@ module ATP
|
|
30
38
|
|
31
39
|
def setup
|
32
40
|
end
|
41
|
+
|
42
|
+
def error(message)
|
43
|
+
# This is a hack to make the specs pass, for some reason RSpec
|
44
|
+
# seems to be swallowing the Origen log output after the first
|
45
|
+
# test that generates an error
|
46
|
+
if Validator.testing
|
47
|
+
puts message
|
48
|
+
else
|
49
|
+
Origen.log.error(message)
|
50
|
+
end
|
51
|
+
end
|
33
52
|
end
|
34
53
|
end
|
@@ -4,9 +4,9 @@ module ATP
|
|
4
4
|
def on_completion
|
5
5
|
if @duplicate_ids
|
6
6
|
@duplicate_ids.each do |id, nodes|
|
7
|
-
|
7
|
+
error "Test ID #{id} is defined more than once in flow #{flow.name}:"
|
8
8
|
nodes.each do |node|
|
9
|
-
|
9
|
+
error " #{node.source}"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
true
|
data/lib/atp/validators/jobs.rb
CHANGED
@@ -9,23 +9,23 @@ module ATP
|
|
9
9
|
def on_completion
|
10
10
|
failed = false
|
11
11
|
unless @conflicting.empty?
|
12
|
-
|
13
|
-
|
12
|
+
error 'if_job and unless_job conditions cannot both be applied to the same tests'
|
13
|
+
error "The following conflicts were found in flow #{flow.name}:"
|
14
14
|
@conflicting.each do |a, b|
|
15
15
|
a_condition = a.to_a[1] ? 'if_job: ' : 'unless_job:'
|
16
16
|
b_condition = b.to_a[1] ? 'if_job: ' : 'unless_job:'
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
error " #{a_condition} #{a.source}"
|
18
|
+
error " #{b_condition} #{b.source}"
|
19
|
+
error ''
|
20
20
|
end
|
21
21
|
failed = true
|
22
22
|
end
|
23
23
|
|
24
24
|
unless @negative.empty?
|
25
|
-
|
26
|
-
|
25
|
+
error 'Job names should not be negated, use unless_job if you want to specify !JOB'
|
26
|
+
error "The following negative job names were found in flow #{flow.name}:"
|
27
27
|
@negative.each do |node|
|
28
|
-
|
28
|
+
error " #{node.to_a[0]} #{node.source}"
|
29
29
|
end
|
30
30
|
failed = true
|
31
31
|
end
|
@@ -33,9 +33,10 @@ module ATP
|
|
33
33
|
failed
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
jobs,
|
36
|
+
def on_if_job(node)
|
37
|
+
jobs, *nodes = *node
|
38
38
|
jobs = [jobs].flatten
|
39
|
+
state = node.type == :if_job
|
39
40
|
if jobs.any? { |j| j.to_s =~ /^(!|~)/ }
|
40
41
|
@negative << node
|
41
42
|
end
|
@@ -48,6 +49,7 @@ module ATP
|
|
48
49
|
@stack.pop
|
49
50
|
end
|
50
51
|
end
|
52
|
+
alias_method :on_unless_job, :on_if_job
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|