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
data/lib/atp/flow_api.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module ATP
|
2
|
+
module FlowAPI
|
3
|
+
def atp=(atp)
|
4
|
+
@atp = atp
|
5
|
+
end
|
6
|
+
|
7
|
+
def atp
|
8
|
+
@atp
|
9
|
+
end
|
10
|
+
|
11
|
+
([:test, :bin, :pass, :continue, :cz, :log, :sub_test, :volatile, :set_flag, :enable, :disable, :render,
|
12
|
+
:context_changed?] +
|
13
|
+
ATP::Flow::CONDITION_KEYS.keys).each do |method|
|
14
|
+
define_method method do |*args, &block|
|
15
|
+
options = args.pop if args.last.is_a?(Hash)
|
16
|
+
options ||= {}
|
17
|
+
add_meta!(options) if respond_to?(:add_meta!, true)
|
18
|
+
add_description!(options) if respond_to?(:add_description!, true)
|
19
|
+
args << options
|
20
|
+
atp.send(method, *args, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :logprint, :log
|
25
|
+
end
|
26
|
+
end
|
data/lib/atp/formatters/basic.rb
CHANGED
@@ -13,7 +13,9 @@ module ATP
|
|
13
13
|
if node.find(:name)
|
14
14
|
@output += node.find(:name).value
|
15
15
|
else
|
16
|
-
|
16
|
+
obj = node.find(:object).value
|
17
|
+
obj = obj['Test'] unless obj.is_a?(String)
|
18
|
+
@output += obj
|
17
19
|
end
|
18
20
|
@output += ' F' if node.find(:failed)
|
19
21
|
@output += "\n"
|
data/lib/atp/processor.rb
CHANGED
@@ -44,22 +44,6 @@ module ATP
|
|
44
44
|
node.updated(nil, process_all(node.children))
|
45
45
|
end
|
46
46
|
|
47
|
-
def n(type, children)
|
48
|
-
ATP::AST::Node.new(type, children)
|
49
|
-
end
|
50
|
-
|
51
|
-
def n0(type)
|
52
|
-
n(type, [])
|
53
|
-
end
|
54
|
-
|
55
|
-
def n1(type, arg)
|
56
|
-
n(type, [arg])
|
57
|
-
end
|
58
|
-
|
59
|
-
def n2(type, arg1, arg2)
|
60
|
-
n(type, [arg1, arg2])
|
61
|
-
end
|
62
|
-
|
63
47
|
def extract_volatiles(flow)
|
64
48
|
@volatiles = {}
|
65
49
|
if v = flow.find(:volatile)
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# This combines adjacent if flag nodes where the flag is in the opposite state
|
4
|
+
#
|
5
|
+
# s(:flow,
|
6
|
+
# s(:name, "prb1"),
|
7
|
+
# s(:if_flag, "SOME_FLAG",
|
8
|
+
# s(:test,
|
9
|
+
# s(:name, "test1"))),
|
10
|
+
# s(:unless_flag, "SOME_FLAG",
|
11
|
+
# s(:test,
|
12
|
+
# s(:name, "test2"))))
|
13
|
+
#
|
14
|
+
# s(:flow,
|
15
|
+
# s(:name, "prb1"),
|
16
|
+
# s(:if_flag, "SOME_FLAG",
|
17
|
+
# s(:test,
|
18
|
+
# s(:name, "test1"))),
|
19
|
+
# s(:else,
|
20
|
+
# s(:test,
|
21
|
+
# s(:name, "test2"))))
|
22
|
+
#
|
23
|
+
# See here for an example of the kind of flow level effect it has:
|
24
|
+
# https://github.com/Origen-SDK/origen_testers/issues/43
|
25
|
+
class AdjacentIfCombiner < ATP::Processor
|
26
|
+
class SetRunFlagFinder < ATP::Processor
|
27
|
+
def contains?(node, flag_name)
|
28
|
+
@result = false
|
29
|
+
@flag_name = flag_name
|
30
|
+
process_all(node)
|
31
|
+
@result
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_set_flag(node)
|
35
|
+
if node.to_a[0] == @flag_name
|
36
|
+
@result = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
alias_method :on_enable, :on_set_flag
|
40
|
+
alias_method :on_disable, :on_set_flag
|
41
|
+
end
|
42
|
+
|
43
|
+
def on_flow(node)
|
44
|
+
extract_volatiles(node)
|
45
|
+
name, *nodes = *node
|
46
|
+
node.updated(nil, [name] + optimize(process_all(nodes)))
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_group(node)
|
50
|
+
name, *nodes = *node
|
51
|
+
node.updated(nil, [name] + optimize(process_all(nodes)))
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_unnamed_collection(node)
|
55
|
+
node.updated(nil, optimize(process_all(node.children)))
|
56
|
+
end
|
57
|
+
alias_method :on_on_fail, :on_unnamed_collection
|
58
|
+
alias_method :on_on_pass, :on_unnamed_collection
|
59
|
+
|
60
|
+
def optimize(nodes)
|
61
|
+
results = []
|
62
|
+
node1 = nil
|
63
|
+
nodes.each do |node2|
|
64
|
+
if node1
|
65
|
+
if opposite_flag_states?(node1, node2) && safe_to_combine?(node1, node2)
|
66
|
+
results << combine(node1, node2)
|
67
|
+
node1 = nil
|
68
|
+
else
|
69
|
+
results << node1
|
70
|
+
node1 = node2
|
71
|
+
end
|
72
|
+
else
|
73
|
+
node1 = node2
|
74
|
+
end
|
75
|
+
end
|
76
|
+
results << node1 if node1
|
77
|
+
results
|
78
|
+
end
|
79
|
+
|
80
|
+
def combine(node1, node2)
|
81
|
+
node1.updated(nil, process_all(node1.children) + [node2.updated(:else, process_all(node2.to_a[1..-1]))])
|
82
|
+
end
|
83
|
+
|
84
|
+
def opposite_flag_states?(node1, node2)
|
85
|
+
((node1.type == :if_flag && node2.type == :unless_flag) || (node1.type == :unless_flag && node2.type == :if_flag) ||
|
86
|
+
(node1.type == :if_enabled && node2.type == :unless_enabled) || (node1.type == :unless_enabled && node2.type == :if_enabled)) &&
|
87
|
+
node1.to_a[0] == node2.to_a[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
def safe_to_combine?(node1, node2)
|
91
|
+
# Nodes won't be collapsed if node1 touches the shared run flag, i.e. if there is any chance
|
92
|
+
# that by the time it would naturally execute node2, the flag could have been changed by node1
|
93
|
+
!volatile?(node1.to_a[0]) && !SetRunFlagFinder.new.contains?(node1, node1.to_a[0])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Appends the given node to the node with the given ID, if it exists
|
4
|
+
# somewhere within the given parent node
|
5
|
+
class AppendTo < Processor
|
6
|
+
def run(parent, node, id, options = {})
|
7
|
+
@to_be_appended = node
|
8
|
+
@id_of_to_be_appended_to = id
|
9
|
+
@found = false
|
10
|
+
process(parent)
|
11
|
+
end
|
12
|
+
|
13
|
+
def succeeded?
|
14
|
+
@found
|
15
|
+
end
|
16
|
+
|
17
|
+
def handler_missing(node)
|
18
|
+
if node.id == @id_of_to_be_appended_to
|
19
|
+
@found = true
|
20
|
+
node.updated(nil, node.children + [@to_be_appended])
|
21
|
+
else
|
22
|
+
node.updated(nil, process_all(node.children))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# This removes on_pass/fail operations from groups and applies them to all
|
4
|
+
# contained tests
|
5
|
+
class ApplyPostGroupActions < Processor
|
6
|
+
def run(node)
|
7
|
+
@on_pass = []
|
8
|
+
@on_fail = []
|
9
|
+
process(node)
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_group(node)
|
13
|
+
on_pass = node.find(:on_pass)
|
14
|
+
on_fail = node.find(:on_fail)
|
15
|
+
@on_pass << on_pass
|
16
|
+
@on_fail << on_fail
|
17
|
+
node = node.remove(on_pass) if on_pass
|
18
|
+
node = node.remove(on_fail) if on_fail
|
19
|
+
node = node.updated(nil, process_all(node.children))
|
20
|
+
@on_fail.pop
|
21
|
+
@on_pass.pop
|
22
|
+
node
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_test(node)
|
26
|
+
node = node.ensure_node_present(:on_pass) if @on_pass.any? { |n| n }
|
27
|
+
node = node.ensure_node_present(:on_fail) if @on_fail.any? { |n| n }
|
28
|
+
node.updated(nil, process_all(node.children))
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_on_pass(node)
|
32
|
+
@on_pass.each do |on_pass|
|
33
|
+
if on_pass
|
34
|
+
node = node.updated(nil, node.children + process_all(on_pass.children))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
node
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_on_fail(node)
|
41
|
+
@on_fail.each do |on_fail|
|
42
|
+
if on_fail
|
43
|
+
node = node.updated(nil, node.children + process_all(on_fail.children))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
node
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -48,45 +48,44 @@ module ATP
|
|
48
48
|
node.updated(nil, optimize(process_all(node.children)))
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
if conditions_to_remove.any? { |c| node.type == c.type && c.to_a == [
|
51
|
+
def on_group(node)
|
52
|
+
name, *nodes = *node
|
53
|
+
if conditions_to_remove.any? { |c| node.type == c.type && c.to_a == [name] }
|
54
|
+
conditions_to_remove << node.updated(nil, [name])
|
55
|
+
result = node.updated(:inline, optimize(process_all(nodes)))
|
56
|
+
conditions_to_remove.pop
|
57
|
+
else
|
58
|
+
conditions_to_remove << node.updated(nil, [name])
|
59
|
+
result = node.updated(nil, [name] + optimize(process_all(nodes)))
|
60
|
+
conditions_to_remove.pop
|
61
|
+
end
|
62
|
+
result
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_condition_node(node)
|
66
|
+
flag, *nodes = *node
|
67
|
+
if conditions_to_remove.any? { |c| node.type == c.type && c.to_a == [flag] }
|
54
68
|
if volatile?(flag)
|
55
|
-
result =
|
69
|
+
result = node.updated(:inline, optimize(process_all(nodes)))
|
56
70
|
else
|
57
71
|
# This ensures any duplicate conditions matching the current one get removed
|
58
|
-
conditions_to_remove << node.updated(nil, [flag
|
59
|
-
result =
|
72
|
+
conditions_to_remove << node.updated(nil, [flag])
|
73
|
+
result = node.updated(:inline, optimize(process_all(nodes)))
|
60
74
|
conditions_to_remove.pop
|
61
75
|
end
|
62
76
|
else
|
63
77
|
if volatile?(flag)
|
64
|
-
result = node.updated(nil, [flag
|
78
|
+
result = node.updated(nil, [flag] + optimize(process_all(nodes)))
|
65
79
|
else
|
66
|
-
conditions_to_remove << node.updated(nil, [flag
|
67
|
-
result = node.updated(nil, [flag
|
80
|
+
conditions_to_remove << node.updated(nil, [flag])
|
81
|
+
result = node.updated(nil, [flag] + optimize(process_all(nodes)))
|
68
82
|
conditions_to_remove.pop
|
69
83
|
end
|
70
84
|
end
|
71
85
|
result
|
72
86
|
end
|
73
|
-
|
74
|
-
|
75
|
-
alias_method :on_run_flag, :on_flow_flag
|
76
|
-
alias_method :on_test_executed, :on_flow_flag
|
77
|
-
|
78
|
-
def on_group(node)
|
79
|
-
name, *nodes = *node
|
80
|
-
if conditions_to_remove.any? { |c| node.type == c.type && c.to_a == [name] }
|
81
|
-
conditions_to_remove << node.updated(nil, [name])
|
82
|
-
result = n(:inline, optimize(process_all(nodes)))
|
83
|
-
conditions_to_remove.pop
|
84
|
-
else
|
85
|
-
conditions_to_remove << node.updated(nil, [name])
|
86
|
-
result = node.updated(nil, [name] + optimize(process_all(nodes)))
|
87
|
-
conditions_to_remove.pop
|
88
|
-
end
|
89
|
-
result
|
87
|
+
ATP::Flow::CONDITION_NODE_TYPES.each do |type|
|
88
|
+
alias_method "on_#{type}", :on_condition_node unless method_defined?("on_#{type}")
|
90
89
|
end
|
91
90
|
|
92
91
|
def optimize(nodes)
|
@@ -117,8 +116,8 @@ module ATP
|
|
117
116
|
end
|
118
117
|
|
119
118
|
def condition_node?(node)
|
120
|
-
|
121
|
-
|
119
|
+
# [:flow_flag, :run_flag, :test_result, :group, :job, :test_executed].include?(node.type)
|
120
|
+
node.respond_to?(:type) && ATP::Flow::CONDITION_KEYS[node.type]
|
122
121
|
end
|
123
122
|
|
124
123
|
def combine(node1, node2)
|
@@ -143,16 +142,14 @@ module ATP
|
|
143
142
|
|
144
143
|
def conditions(node)
|
145
144
|
result = []
|
146
|
-
if [:flow_flag, :run_flag].include?(node.type)
|
147
|
-
|
145
|
+
# if [:flow_flag, :run_flag].include?(node.type)
|
146
|
+
if [:if_enabled, :unless_enabled, :if_flag, :unless_flag].include?(node.type)
|
147
|
+
flag, *children = *node
|
148
148
|
unless volatile?(flag)
|
149
|
-
result << node.updated(nil, [flag
|
149
|
+
result << node.updated(nil, [flag])
|
150
150
|
end
|
151
|
-
result += conditions(children.first) if children.first
|
152
|
-
elsif [:test_result, :job, :test_executed].include?(node.type)
|
153
|
-
flag, state, *children = *node
|
154
|
-
result << node.updated(nil, [flag, state])
|
155
|
-
result += conditions(children.first) if children.first
|
151
|
+
result += conditions(children.first) if children.first && children.size == 1
|
152
|
+
# elsif [:test_result, :job, :test_executed].include?(node.type)
|
156
153
|
elsif node.type == :group
|
157
154
|
name, *children = *node
|
158
155
|
# Sometimes a group can have an ID
|
@@ -161,7 +158,11 @@ module ATP
|
|
161
158
|
else
|
162
159
|
result << node.updated(nil, [name])
|
163
160
|
end
|
164
|
-
result += conditions(children.first) if children.first
|
161
|
+
result += conditions(children.first) if children.first && children.size == 1
|
162
|
+
elsif ATP::Flow::CONDITION_NODE_TYPES.include?(node.type)
|
163
|
+
flag, *children = *node
|
164
|
+
result << node.updated(nil, [flag])
|
165
|
+
result += conditions(children.first) if children.first && children.size == 1
|
165
166
|
end
|
166
167
|
result
|
167
168
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Implements continue on a fail branch for V93K by removing any bin nodes that are
|
4
|
+
# siblings of continue nodes. The continue nodes are also removed in the process since
|
5
|
+
# they have now served their function.
|
6
|
+
class ContinueImplementer < ATP::Processor
|
7
|
+
# Delete any on-fail child if it's 'empty'
|
8
|
+
def on_on_fail(node)
|
9
|
+
if cont = node.find(:continue) || @continue
|
10
|
+
node = node.updated(nil, node.children - [cont] - node.find_all(:set_result))
|
11
|
+
end
|
12
|
+
node.updated(nil, process_all(node.children))
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_group(node)
|
16
|
+
f = node.find(:on_fail)
|
17
|
+
if f && f.find(:continue)
|
18
|
+
with_continue do
|
19
|
+
node = node.updated(nil, process_all(node.children))
|
20
|
+
end
|
21
|
+
node
|
22
|
+
else
|
23
|
+
node.updated(nil, process_all(node.children))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_continue
|
28
|
+
orig = @continue
|
29
|
+
@continue = true
|
30
|
+
yield
|
31
|
+
@continue = orig
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Removes embedded else nodes and converts them to the equivalent inverse condition
|
4
|
+
# node at the same level as the parent node
|
5
|
+
class ElseRemover < Processor
|
6
|
+
def run(node)
|
7
|
+
process(node)
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_condition_node(node)
|
11
|
+
if e = node.find(:else)
|
12
|
+
n1 = node.remove(e)
|
13
|
+
if node.type.to_s =~ /if_/
|
14
|
+
type = node.type.to_s.sub('if_', 'unless_').to_sym
|
15
|
+
elsif node.type.to_s =~ /unless_/
|
16
|
+
type = node.type.to_s.sub('unless_', 'if_').to_sym
|
17
|
+
else
|
18
|
+
fail "Don't know how to inverse: #{node.type}"
|
19
|
+
end
|
20
|
+
n2 = e.updated(type, [n1.to_a[0]] + e.children)
|
21
|
+
node.updated(:inline, [n1, n2])
|
22
|
+
else
|
23
|
+
node.updated(nil, process_all(node.children))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
ATP::Flow::CONDITION_NODE_TYPES.each do |type|
|
27
|
+
alias_method "on_#{type}", :on_condition_node unless method_defined?("on_#{type}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Removes any empty on_pass and on_fail branches
|
4
|
+
class EmptyBranchRemover < Processor
|
5
|
+
# Delete any on-fail child if it's 'empty'
|
6
|
+
def on_test(node)
|
7
|
+
if on_pass = node.find(:on_pass)
|
8
|
+
node = node.remove(on_pass) if on_pass.children.empty?
|
9
|
+
end
|
10
|
+
if on_fail = node.find(:on_fail)
|
11
|
+
node = node.remove(on_fail) if on_fail.children.empty?
|
12
|
+
end
|
13
|
+
node = node.updated(nil, process_all(node.children))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|