atp 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|