atp 1.0.0 → 1.1.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/version.rb +1 -1
- data/lib/atp.rb +1 -0
- data/lib/atp/ast/node.rb +7 -0
- data/lib/atp/flow.rb +72 -21
- data/lib/atp/flow_api.rb +31 -1
- data/lib/atp/processors/adjacent_if_combiner.rb +2 -1
- data/lib/atp/processors/flag_optimizer.rb +17 -5
- data/lib/atp/processors/relationship.rb +14 -7
- data/lib/atp/validators/flags.rb +59 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a0d850eca7f69b2f9c49af6e1192fc97d248cb8
|
4
|
+
data.tar.gz: fcf7c3fa24bcca9d19eb3d590d68f6acef66ac83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b2cf5e3e8b7252884cdb9f45ef8cd57374b1eda91e1559f19f5303c10ccfb6c16b35fdf38a2fd5d7ca58a124034b6551964e59937227398ec67710125c9ab8d
|
7
|
+
data.tar.gz: 88d0018049a88372325e2acbbec0fd729f872c70500ae15208001321da2504404814d5401886e8752d5ed8f3dc2cb50d6fb97bf63293697b9df986325cf3241f
|
data/config/version.rb
CHANGED
data/lib/atp.rb
CHANGED
@@ -79,6 +79,7 @@ module ATP
|
|
79
79
|
autoload :MissingIDs, 'atp/validators/missing_ids'
|
80
80
|
autoload :Condition, 'atp/validators/condition'
|
81
81
|
autoload :Jobs, 'atp/validators/jobs'
|
82
|
+
autoload :Flags, 'atp/validators/flags'
|
82
83
|
end
|
83
84
|
|
84
85
|
# Formatters are run on the processed AST to display the flow or to render
|
data/lib/atp/ast/node.rb
CHANGED
@@ -86,6 +86,13 @@ module ATP
|
|
86
86
|
def set_flags
|
87
87
|
Processors::ExtractSetFlags.new.run(self)
|
88
88
|
end
|
89
|
+
|
90
|
+
# Returns true if the node contains any nodes of the given type(s) or if any
|
91
|
+
# of its children do.
|
92
|
+
# To consider only direct children of this node use: node.find_all(*types).empty?
|
93
|
+
def contains?(*types)
|
94
|
+
!Extractor.new.process(self, types).empty?
|
95
|
+
end
|
89
96
|
end
|
90
97
|
end
|
91
98
|
end
|
data/lib/atp/flow.rb
CHANGED
@@ -98,17 +98,21 @@ module ATP
|
|
98
98
|
# used to build and represent the given test flow
|
99
99
|
def ast(options = {})
|
100
100
|
options = {
|
101
|
-
apply_relationships:
|
101
|
+
apply_relationships: true,
|
102
102
|
# Supply a unique ID to append to all IDs
|
103
|
-
unique_id:
|
103
|
+
unique_id: nil,
|
104
104
|
# Set to :smt, or :igxl
|
105
|
-
optimization:
|
105
|
+
optimization: :runner,
|
106
|
+
# When true, will remove set_result nodes in an on_fail branch which contains a continue
|
107
|
+
implement_continue: true,
|
108
|
+
# When false, this will not optimize the use of a flag by nesting a dependent test within
|
109
|
+
# the parent test's on_fail branch if the on_fail contains a continue
|
110
|
+
optimize_flags_when_continue: true,
|
106
111
|
# These options are not intended for application use, but provide the ability to
|
107
112
|
# turn off certain processors during test cases
|
108
|
-
add_ids:
|
109
|
-
optimize_flags:
|
110
|
-
one_flag_per_test:
|
111
|
-
implement_continue: true
|
113
|
+
add_ids: true,
|
114
|
+
optimize_flags: true,
|
115
|
+
one_flag_per_test: true
|
112
116
|
}.merge(options)
|
113
117
|
###############################################################################
|
114
118
|
## Common pre-processing and validation
|
@@ -117,6 +121,7 @@ module ATP
|
|
117
121
|
Validators::DuplicateIDs.new(self).run(ast)
|
118
122
|
Validators::MissingIDs.new(self).run(ast)
|
119
123
|
Validators::Jobs.new(self).run(ast)
|
124
|
+
Validators::Flags.new(self).run(ast)
|
120
125
|
# Ensure everything has an ID, this helps later if condition nodes need to be generated
|
121
126
|
ast = Processors::AddIDs.new.run(ast) if options[:add_ids]
|
122
127
|
ast = Processors::FlowID.new.run(ast, options[:unique_id]) if options[:unique_id]
|
@@ -132,7 +137,9 @@ module ATP
|
|
132
137
|
unless options[:optimization] == :runner
|
133
138
|
ast = Processors::ContinueImplementer.new.run(ast) if options[:implement_continue]
|
134
139
|
end
|
135
|
-
|
140
|
+
if options[:optimize_flags]
|
141
|
+
ast = Processors::FlagOptimizer.new.run(ast, optimize_when_continue: options[:optimize_flags_when_continue])
|
142
|
+
end
|
136
143
|
ast = Processors::AdjacentIfCombiner.new.run(ast)
|
137
144
|
|
138
145
|
###############################################################################
|
@@ -187,6 +194,17 @@ module ATP
|
|
187
194
|
@pipeline[0] = add_volatile_flags(@pipeline[0], flags)
|
188
195
|
end
|
189
196
|
|
197
|
+
# Record a description for a bin number
|
198
|
+
def describe_bin(number, description, options = {})
|
199
|
+
@pipeline[0] = add_bin_description(@pipeline[0], number, description, type: :hard)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Record a description for a softbin number
|
203
|
+
def describe_soft_bin(number, description, options = {})
|
204
|
+
@pipeline[0] = add_bin_description(@pipeline[0], number, description, type: :soft)
|
205
|
+
end
|
206
|
+
alias_method :describe_softbin, :describe_soft_bin
|
207
|
+
|
190
208
|
# Group all tests generated within the given block
|
191
209
|
#
|
192
210
|
# @example
|
@@ -240,6 +258,10 @@ module ATP
|
|
240
258
|
options[:on_fail] ||= {}
|
241
259
|
options[:on_fail][:continue] = true
|
242
260
|
end
|
261
|
+
if options.key?(:delayed)
|
262
|
+
options[:on_fail] ||= {}
|
263
|
+
options[:on_fail][:delayed] = options.delete(:delayed)
|
264
|
+
end
|
243
265
|
if f = options.delete(:flag_pass)
|
244
266
|
options[:on_pass] ||= {}
|
245
267
|
options[:on_pass][:set_flag] = f
|
@@ -276,11 +298,22 @@ module ATP
|
|
276
298
|
end
|
277
299
|
end
|
278
300
|
|
279
|
-
|
280
|
-
|
281
|
-
lims
|
282
|
-
|
283
|
-
|
301
|
+
lims = options[:limit] || options[:limits]
|
302
|
+
if lims || options[:lo] || options[:low] || options[:hi] || options[:high]
|
303
|
+
if lims == :none || lims == 'none'
|
304
|
+
children << n0(:nolimits)
|
305
|
+
else
|
306
|
+
lims = Array(lims) unless lims.is_a?(Array)
|
307
|
+
if lo = options[:lo] || options[:low]
|
308
|
+
lims << { value: lo, rule: :gte }
|
309
|
+
end
|
310
|
+
if hi = options[:hi] || options[:high]
|
311
|
+
lims << { value: hi, rule: :lte }
|
312
|
+
end
|
313
|
+
lims.each do |l|
|
314
|
+
if l.is_a?(Hash)
|
315
|
+
children << n(:limit, [l[:value], l[:rule], l[:unit] || l[:units], l[:selector]])
|
316
|
+
end
|
284
317
|
end
|
285
318
|
end
|
286
319
|
end
|
@@ -450,6 +483,10 @@ module ATP
|
|
450
483
|
"<ATP::Flow:#{object_id} #{name}>"
|
451
484
|
end
|
452
485
|
|
486
|
+
def ids(options = {})
|
487
|
+
ATP::AST::Extractor.new.process(raw, [:id]).map { |node| node.to_a[0] }
|
488
|
+
end
|
489
|
+
|
453
490
|
private
|
454
491
|
|
455
492
|
def flow_control_method(name, flag, options = {}, &block)
|
@@ -617,6 +654,7 @@ module ATP
|
|
617
654
|
children << set_flag_node(options[:set_run_flag] || options[:set_flag])
|
618
655
|
end
|
619
656
|
children << n0(:continue) if options[:continue]
|
657
|
+
children << n1(:delayed, !!options[:delayed]) if options.key?(:delayed)
|
620
658
|
children << n1(:render, options[:render]) if options[:render]
|
621
659
|
n(:on_fail, children)
|
622
660
|
end
|
@@ -663,14 +701,6 @@ module ATP
|
|
663
701
|
end
|
664
702
|
end
|
665
703
|
|
666
|
-
def limit(value, rule, units = nil)
|
667
|
-
if units
|
668
|
-
n(:limit, [value, rule, units])
|
669
|
-
else
|
670
|
-
n2(:limit, value, rule)
|
671
|
-
end
|
672
|
-
end
|
673
|
-
|
674
704
|
def pin(name)
|
675
705
|
n1(:pin, name)
|
676
706
|
end
|
@@ -717,6 +747,27 @@ module ATP
|
|
717
747
|
node.updated(nil, [name, v] + nodes)
|
718
748
|
end
|
719
749
|
|
750
|
+
# Ensures the flow ast has a bin descriptions node, then adds the
|
751
|
+
# given description to it
|
752
|
+
def add_bin_description(node, number, description, options)
|
753
|
+
@existing_bin_descriptions ||= { soft: {}, hard: {} }
|
754
|
+
return node if @existing_bin_descriptions[options[:type]][number]
|
755
|
+
@existing_bin_descriptions[options[:type]][number] = true
|
756
|
+
name, *nodes = *node
|
757
|
+
if nodes[0] && nodes[0].type == :volatile
|
758
|
+
v = nodes.shift
|
759
|
+
else
|
760
|
+
v = nil
|
761
|
+
end
|
762
|
+
if nodes[0] && nodes[0].type == :bin_descriptions
|
763
|
+
d = nodes.shift
|
764
|
+
else
|
765
|
+
d = n0(:bin_descriptions)
|
766
|
+
end
|
767
|
+
d = d.updated(nil, d.children + [n2(options[:type], number, description)])
|
768
|
+
node.updated(nil, [name, v, d].compact + nodes)
|
769
|
+
end
|
770
|
+
|
720
771
|
def n(type, children, options = {})
|
721
772
|
options[:file] ||= options.delete(:source_file) || source_file
|
722
773
|
options[:line_number] ||= options.delete(:source_line_number) || source_line_number
|
data/lib/atp/flow_api.rb
CHANGED
@@ -9,7 +9,7 @@ module ATP
|
|
9
9
|
end
|
10
10
|
|
11
11
|
([:test, :bin, :pass, :continue, :cz, :log, :sub_test, :volatile, :set_flag, :enable, :disable, :render,
|
12
|
-
:context_changed
|
12
|
+
:context_changed?, :ids, :describe_bin, :describe_softbin, :describe_soft_bin] +
|
13
13
|
ATP::Flow::CONDITION_KEYS.keys).each do |method|
|
14
14
|
define_method method do |*args, &block|
|
15
15
|
options = args.pop if args.last.is_a?(Hash)
|
@@ -22,5 +22,35 @@ module ATP
|
|
22
22
|
end
|
23
23
|
|
24
24
|
alias_method :logprint, :log
|
25
|
+
|
26
|
+
def lo_limit(value, options)
|
27
|
+
{
|
28
|
+
value: value,
|
29
|
+
rule: options[:rule] || :gte,
|
30
|
+
units: options[:units],
|
31
|
+
selector: options[:selector] || options[:test_mode]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def hi_limit(value, options)
|
36
|
+
{
|
37
|
+
value: value,
|
38
|
+
rule: options[:rule] || :lte,
|
39
|
+
units: options[:units],
|
40
|
+
selector: options[:selector] || options[:test_mode]
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def limit(value, options)
|
45
|
+
unless options[:rule]
|
46
|
+
fail 'You must supply option :rule (e.g. rule: :gt) when calling the limit helper'
|
47
|
+
end
|
48
|
+
{
|
49
|
+
value: value,
|
50
|
+
rule: options[:rule] || :lt,
|
51
|
+
units: options[:units],
|
52
|
+
selector: options[:selector] || options[:test_mode]
|
53
|
+
}
|
54
|
+
end
|
25
55
|
end
|
26
56
|
end
|
@@ -90,7 +90,8 @@ module ATP
|
|
90
90
|
def safe_to_combine?(node1, node2)
|
91
91
|
# Nodes won't be collapsed if node1 touches the shared run flag, i.e. if there is any chance
|
92
92
|
# that by the time it would naturally execute node2, the flag could have been changed by node1
|
93
|
-
!volatile?(node1.to_a[0])
|
93
|
+
(!volatile?(node1.to_a[0]) || (volatile?(node1.to_a[0]) && !node1.contains?(:test))) &&
|
94
|
+
!SetRunFlagFinder.new.contains?(node1, node1.to_a[0])
|
94
95
|
end
|
95
96
|
end
|
96
97
|
end
|
@@ -25,7 +25,7 @@ module ATP
|
|
25
25
|
# s(:name, "test2")))))
|
26
26
|
#
|
27
27
|
class FlagOptimizer < Processor
|
28
|
-
attr_reader :run_flag_table
|
28
|
+
attr_reader :run_flag_table, :optimize_when_continue
|
29
29
|
|
30
30
|
class ExtractRunFlagTable < Processor
|
31
31
|
# Hash table of run_flag name with number of times used
|
@@ -53,7 +53,11 @@ module ATP
|
|
53
53
|
alias_method :on_unless_flag, :on_if_flag
|
54
54
|
end
|
55
55
|
|
56
|
-
def run(node)
|
56
|
+
def run(node, options = {})
|
57
|
+
options = {
|
58
|
+
optimize_when_continue: true
|
59
|
+
}.merge(options)
|
60
|
+
@optimize_when_continue = options[:optimize_when_continue]
|
57
61
|
# Pre-process the AST for # of occurrences of each run-flag used
|
58
62
|
t = ExtractRunFlagTable.new
|
59
63
|
t.process(node)
|
@@ -70,11 +74,16 @@ module ATP
|
|
70
74
|
alias_method :on_group, :on_named_collection
|
71
75
|
alias_method :on_unless_flag, :on_named_collection
|
72
76
|
|
77
|
+
def on_unnamed_collection(node)
|
78
|
+
node.updated(nil, optimize(process_all(node.children)))
|
79
|
+
end
|
80
|
+
alias_method :on_else, :on_unnamed_collection
|
81
|
+
|
73
82
|
def on_if_flag(node)
|
74
83
|
name, *nodes = *node
|
75
84
|
# Remove this node and return its children if required
|
76
85
|
if if_run_flag_to_remove.last == node.to_a[0]
|
77
|
-
node.updated(:inline, node.to_a[1..-1])
|
86
|
+
node.updated(:inline, optimize(process_all(node.to_a[1..-1])))
|
78
87
|
else
|
79
88
|
node.updated(nil, [name] + optimize(process_all(nodes)))
|
80
89
|
end
|
@@ -124,7 +133,10 @@ module ATP
|
|
124
133
|
end
|
125
134
|
|
126
135
|
def can_be_combined?(node1, node2)
|
127
|
-
if node1.type == :test && (node2.type == :if_flag || node2.type == :unless_flag)
|
136
|
+
if node1.type == :test && (node2.type == :if_flag || node2.type == :unless_flag) &&
|
137
|
+
# Don't optimize tests which are marked as continue if told not to
|
138
|
+
!(node1.find(:on_fail) && node1.find(:on_fail).find(:continue) && !optimize_when_continue)
|
139
|
+
|
128
140
|
if node1.find_all(:on_fail, :on_pass).any? do |node|
|
129
141
|
if n = node.find(:set_flag)
|
130
142
|
# Inline instead of setting a flag if...
|
@@ -141,7 +153,7 @@ module ATP
|
|
141
153
|
end
|
142
154
|
|
143
155
|
def combine(node1, node2)
|
144
|
-
nodes_to_inline_on_pass_or_fail << node2
|
156
|
+
nodes_to_inline_on_pass_or_fail << node2 # .updated(nil, process_all(node2.children))
|
145
157
|
node1 = node1.updated(nil, process_all(node1.children))
|
146
158
|
nodes_to_inline_on_pass_or_fail.pop
|
147
159
|
node1
|
@@ -66,7 +66,12 @@ module ATP
|
|
66
66
|
if n.type == :on_pass
|
67
67
|
n = n.add node.updated(:set_flag, ["#{id}_PASSED", :auto_generated])
|
68
68
|
elsif n.type == :on_fail
|
69
|
-
n.
|
69
|
+
delayed = n.find(:delayed)
|
70
|
+
if delayed && delayed.to_a[0]
|
71
|
+
n
|
72
|
+
else
|
73
|
+
n.ensure_node_present(:continue)
|
74
|
+
end
|
70
75
|
else
|
71
76
|
n
|
72
77
|
end
|
@@ -78,7 +83,12 @@ module ATP
|
|
78
83
|
node.updated(nil, node.children.map do |n|
|
79
84
|
if n.type == :on_fail
|
80
85
|
n = n.add node.updated(:set_flag, ["#{id}_FAILED", :auto_generated])
|
81
|
-
n.
|
86
|
+
delayed = n.find(:delayed)
|
87
|
+
if delayed && delayed.to_a[0]
|
88
|
+
n
|
89
|
+
else
|
90
|
+
n.ensure_node_present(:continue)
|
91
|
+
end
|
82
92
|
else
|
83
93
|
n
|
84
94
|
end
|
@@ -111,6 +121,7 @@ module ATP
|
|
111
121
|
# Set flags depending on the result on tests which have dependents later
|
112
122
|
# in the flow
|
113
123
|
def on_test(node)
|
124
|
+
node = node.updated(nil, process_all(node.children))
|
114
125
|
nid = id(node)
|
115
126
|
# If this test has a dependent
|
116
127
|
if test_results[nid]
|
@@ -118,11 +129,7 @@ module ATP
|
|
118
129
|
node = add_fail_flag(nid, node) if test_results[nid][:failed]
|
119
130
|
node = add_ran_flags(nid, node) if test_results[nid][:ran]
|
120
131
|
end
|
121
|
-
|
122
|
-
node.updated(nil, process_all(node))
|
123
|
-
else
|
124
|
-
node
|
125
|
-
end
|
132
|
+
node
|
126
133
|
end
|
127
134
|
alias_method :on_group, :on_test
|
128
135
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ATP
|
2
|
+
module Validators
|
3
|
+
class Flags < Validator
|
4
|
+
def setup
|
5
|
+
@open_if_nodes = []
|
6
|
+
@open_unless_nodes = []
|
7
|
+
@conflicting = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_completion
|
11
|
+
failed = false
|
12
|
+
unless @conflicting.empty?
|
13
|
+
error 'if_flag and unless_flag conditions cannot be nested and refer to the same flag unless it is declared as volatile'
|
14
|
+
error "The following conflicts were found in flow #{flow.name}:"
|
15
|
+
@conflicting.each do |a, b|
|
16
|
+
a_condition = a.to_a[1] ? 'if_job: ' : 'unless_job:'
|
17
|
+
b_condition = b.to_a[1] ? 'if_job: ' : 'unless_job:'
|
18
|
+
error " #{a.type}(#{a.to_a[0]}) #{a.source}"
|
19
|
+
error " #{b.type}(#{b.to_a[0]}) #{b.source}"
|
20
|
+
error ''
|
21
|
+
end
|
22
|
+
failed = true
|
23
|
+
end
|
24
|
+
failed
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_flow(node)
|
28
|
+
extract_volatiles(node)
|
29
|
+
process_all(node.children)
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_if_flag(node)
|
33
|
+
if volatile?(node.to_a[0])
|
34
|
+
process_all(node.children)
|
35
|
+
else
|
36
|
+
if n = @open_unless_nodes.find { |n| n.to_a[0] == node.to_a[0] }
|
37
|
+
@conflicting << [n, node]
|
38
|
+
end
|
39
|
+
@open_if_nodes << node
|
40
|
+
process_all(node.children)
|
41
|
+
@open_if_nodes.pop
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_unless_flag(node)
|
46
|
+
if volatile?(node.to_a[0])
|
47
|
+
process_all(node.children)
|
48
|
+
else
|
49
|
+
if n = @open_if_nodes.find { |n| n.to_a[0] == node.to_a[0] }
|
50
|
+
@conflicting << [n, node]
|
51
|
+
end
|
52
|
+
@open_unless_nodes << node
|
53
|
+
process_all(node.children)
|
54
|
+
@open_unless_nodes.pop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
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: 1.
|
4
|
+
version: 1.1.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:
|
11
|
+
date: 2018-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/atp/validator.rb
|
98
98
|
- lib/atp/validators/condition.rb
|
99
99
|
- lib/atp/validators/duplicate_ids.rb
|
100
|
+
- lib/atp/validators/flags.rb
|
100
101
|
- lib/atp/validators/jobs.rb
|
101
102
|
- lib/atp/validators/missing_ids.rb
|
102
103
|
- lib/tasks/atp.rake
|
@@ -125,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
126
|
version: 1.8.11
|
126
127
|
requirements: []
|
127
128
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
129
|
+
rubygems_version: 2.6.8
|
129
130
|
signing_key:
|
130
131
|
specification_version: 4
|
131
132
|
summary: An abstract test program model for Origen
|