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