atp 0.7.0 → 0.8.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 +0 -1
- data/lib/atp/ast/builder.rb +99 -0
- data/lib/atp/flow.rb +32 -10
- data/lib/atp/processor.rb +43 -0
- data/lib/atp/processors/condition.rb +95 -98
- metadata +2 -3
- data/lib/atp/processors/condition_extractor.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f75bbab3b302da47d1dee34b1d3ee5ff9e19fbf8
|
4
|
+
data.tar.gz: bdd796b0790974ab59638e3eb1c3a6d0978838e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c75c86487c1fa3db9cd8ec84b754850b4cb308c6cd5bd6c2fbc96342bf300d433154e66787b66bd896b484677f6c367102b641f9bdd5166f2b8be1a62a054767
|
7
|
+
data.tar.gz: eb3547a04a6b3ceea52ac58c831d5d320a1c818ffd161195207f858b0b30b592853ab94edeae371684221def67a0ee7075ee8c8ca7bb6e6af7890469b58e59b5
|
data/config/version.rb
CHANGED
data/lib/atp.rb
CHANGED
@@ -21,7 +21,6 @@ module ATP
|
|
21
21
|
# and to implement the flow control API
|
22
22
|
module Processors
|
23
23
|
autoload :Condition, 'atp/processors/condition'
|
24
|
-
autoload :ConditionExtractor, 'atp/processors/condition_extractor'
|
25
24
|
autoload :Relationship, 'atp/processors/relationship'
|
26
25
|
autoload :PreCleaner, 'atp/processors/pre_cleaner'
|
27
26
|
autoload :PostCleaner, 'atp/processors/post_cleaner'
|
data/lib/atp/ast/builder.rb
CHANGED
@@ -14,6 +14,24 @@ module ATP
|
|
14
14
|
n(:flow, name(str))
|
15
15
|
end
|
16
16
|
|
17
|
+
# Ensures the given flow ast has a volatile node, then adds the
|
18
|
+
# given flags to it
|
19
|
+
def add_volatile_flags(flow, flags)
|
20
|
+
name, *nodes = *flow
|
21
|
+
if nodes[0] && nodes[0].type == :volatile
|
22
|
+
v = nodes.shift
|
23
|
+
else
|
24
|
+
v = n0(:volatile)
|
25
|
+
end
|
26
|
+
existing = v.children.map { |f| f.type == :flag ? f.value : nil }.compact
|
27
|
+
new = []
|
28
|
+
flags.each do |flag|
|
29
|
+
new << n(:flag, flag) unless existing.include?(flag)
|
30
|
+
end
|
31
|
+
v = v.updated(nil, v.children + new)
|
32
|
+
flow.updated(nil, [name, v] + nodes)
|
33
|
+
end
|
34
|
+
|
17
35
|
def name(str)
|
18
36
|
n(:name, str.to_s)
|
19
37
|
end
|
@@ -220,6 +238,55 @@ module ATP
|
|
220
238
|
|
221
239
|
children << id(options[:id].to_s.downcase.to_sym) if options[:id]
|
222
240
|
|
241
|
+
if levels = options[:level] || options[:levels]
|
242
|
+
levels = [levels] unless levels.is_a?(Array)
|
243
|
+
levels.each do |l|
|
244
|
+
children << level(l[:name], l[:value], l[:unit] || l[:units])
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
if lims = options[:limit] || options[:limits]
|
249
|
+
lims = [lims] unless lims.is_a?(Array)
|
250
|
+
lims.each do |l|
|
251
|
+
children << limit(l[:value], l[:rule], l[:unit] || l[:units])
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
if pins = options[:pin] || options[:pins]
|
256
|
+
pins = [pins] unless pins.is_a?(Array)
|
257
|
+
pins.each do |p|
|
258
|
+
if p.is_a?(Hash)
|
259
|
+
children << pin(p[:name])
|
260
|
+
else
|
261
|
+
children << pin(p)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
if pats = options[:pattern] || options[:patterns]
|
267
|
+
pats = [pats] unless pats.is_a?(Array)
|
268
|
+
pats.each do |p|
|
269
|
+
if p.is_a?(Hash)
|
270
|
+
children << pattern(p[:name], p[:path])
|
271
|
+
else
|
272
|
+
children << pattern(p)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
if options[:meta]
|
278
|
+
attrs = []
|
279
|
+
options[:meta].each { |k, v| attrs << attribute(k, v) }
|
280
|
+
children << n(:meta, *attrs)
|
281
|
+
end
|
282
|
+
|
283
|
+
if subs = options[:sub_test] || options[:sub_tests]
|
284
|
+
subs = [subs] unless subs.is_a?(Array)
|
285
|
+
subs.each do |s|
|
286
|
+
children << s.updated(:sub_test, nil)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
223
290
|
children << on_fail(options[:on_fail]) if options[:on_fail]
|
224
291
|
children << on_pass(options[:on_pass]) if options[:on_pass]
|
225
292
|
|
@@ -232,6 +299,38 @@ module ATP
|
|
232
299
|
end
|
233
300
|
end
|
234
301
|
|
302
|
+
def pattern(name, path = nil)
|
303
|
+
if path
|
304
|
+
n(:pattern, name, path)
|
305
|
+
else
|
306
|
+
n(:pattern, name)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def attribute(name, value)
|
311
|
+
n(:attribute, name, value)
|
312
|
+
end
|
313
|
+
|
314
|
+
def level(name, value, units = nil)
|
315
|
+
if units
|
316
|
+
n(:level, name, value, units)
|
317
|
+
else
|
318
|
+
n(:level, name, value)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def limit(value, rule, units = nil)
|
323
|
+
if units
|
324
|
+
n(:limit, value, rule, units)
|
325
|
+
else
|
326
|
+
n(:limit, value, rule)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def pin(name)
|
331
|
+
n(:pin, name)
|
332
|
+
end
|
333
|
+
|
235
334
|
def on_fail(options = {})
|
236
335
|
children = []
|
237
336
|
if options[:bin] || options[:softbin]
|
data/lib/atp/flow.rb
CHANGED
@@ -41,6 +41,14 @@ module ATP
|
|
41
41
|
ast
|
42
42
|
end
|
43
43
|
|
44
|
+
# Indicate the that given flags should be considered volatile (can change at any time), which will
|
45
|
+
# prevent them from been touched by the optimization algorithms
|
46
|
+
def volatile(*flags)
|
47
|
+
options = flags.pop if flags.last.is_a?(Hash)
|
48
|
+
flags = flags.flatten
|
49
|
+
@raw = builder.add_volatile_flags(@raw, flags)
|
50
|
+
end
|
51
|
+
|
44
52
|
# Group all tests generated within the given block
|
45
53
|
#
|
46
54
|
# @example
|
@@ -104,6 +112,16 @@ module ATP
|
|
104
112
|
t
|
105
113
|
end
|
106
114
|
|
115
|
+
# Equivalent to calling test, but returns a sub_test node instead of adding it to the flow.
|
116
|
+
# It will also ignore any condition nodes that would normally wrap the equivalent flow.test call.
|
117
|
+
#
|
118
|
+
# This is a helper to create sub_tests for inclusion in a top-level test node.
|
119
|
+
def sub_test(instance, options = {})
|
120
|
+
options[:return] = true
|
121
|
+
options[:ignore_all_conditions] = true
|
122
|
+
test(instance, options)
|
123
|
+
end
|
124
|
+
|
107
125
|
def bin(number, options = {})
|
108
126
|
extract_meta!(options)
|
109
127
|
t = apply_open_conditions(options) do |options|
|
@@ -268,19 +286,23 @@ module ATP
|
|
268
286
|
end
|
269
287
|
|
270
288
|
def apply_open_conditions(options)
|
271
|
-
if options[:
|
272
|
-
options
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
289
|
+
if options[:ignore_all_conditions]
|
290
|
+
yield(options)
|
291
|
+
else
|
292
|
+
if options[:context] == :current
|
293
|
+
options[:conditions] = builder.context[:conditions]
|
294
|
+
end
|
295
|
+
builder.new_context
|
296
|
+
t = yield(options)
|
297
|
+
unless options[:context] == :current
|
298
|
+
unless options[:dont_apply_conditions]
|
299
|
+
open_conditions.each do |conditions|
|
300
|
+
t = builder.apply_conditions(t, conditions)
|
301
|
+
end
|
280
302
|
end
|
281
303
|
end
|
304
|
+
t
|
282
305
|
end
|
283
|
-
t
|
284
306
|
end
|
285
307
|
|
286
308
|
def extract_meta!(options)
|
data/lib/atp/processor.rb
CHANGED
@@ -23,6 +23,23 @@ module ATP
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
# Some of our processors remove a wrapping node from the AST, returning
|
27
|
+
# a node of type :inline containing the children which should be inlined.
|
28
|
+
# Here we override the default version of this method to deal with handlers
|
29
|
+
# that return an inline node in place of a regular node.
|
30
|
+
def process_all(nodes)
|
31
|
+
results = []
|
32
|
+
nodes.to_a.each do |node|
|
33
|
+
n = process(node)
|
34
|
+
if n.respond_to?(:type) && n.type == :inline
|
35
|
+
results += n.children
|
36
|
+
else
|
37
|
+
results << n
|
38
|
+
end
|
39
|
+
end
|
40
|
+
results
|
41
|
+
end
|
42
|
+
|
26
43
|
def handler_missing(node)
|
27
44
|
node.updated(nil, process_all(node.children))
|
28
45
|
end
|
@@ -42,5 +59,31 @@ module ATP
|
|
42
59
|
def n2(type, arg1, arg2)
|
43
60
|
n(type, [arg1, arg2])
|
44
61
|
end
|
62
|
+
|
63
|
+
def extract_volatiles(flow)
|
64
|
+
@volatiles = {}
|
65
|
+
if v = flow.find(:volatile)
|
66
|
+
@volatiles[:flags] = Array(v.find_all(:flag)).map(&:value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def volatile_flags
|
71
|
+
unless @volatiles
|
72
|
+
fail 'You must first call extract_volatiles(node) from your on_flow hander method'
|
73
|
+
end
|
74
|
+
@volatiles[:flags] || []
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns true if the given flag name has been marked as volatile
|
78
|
+
def volatile?(flag)
|
79
|
+
result = volatile_flags.any? { |f| clean_flag(f) == clean_flag(flag) }
|
80
|
+
result
|
81
|
+
end
|
82
|
+
|
83
|
+
def clean_flag(flag)
|
84
|
+
flag = flag.dup.to_s
|
85
|
+
flag[0] = '' if flag[0] == '$'
|
86
|
+
flag.downcase
|
87
|
+
end
|
45
88
|
end
|
46
89
|
end
|
@@ -43,134 +43,131 @@ module ATP
|
|
43
43
|
# (name "test4")))))))
|
44
44
|
#
|
45
45
|
class Condition < Processor
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# Bit of a hack - To get all of the nested conditions optimized away it is necessary
|
50
|
-
# to execute this recursively a few times. This guard ensures that the recursion is
|
51
|
-
# only performed on the top-level and not on every process operation.
|
52
|
-
if @top_level_called
|
53
|
-
super
|
54
|
-
else
|
55
|
-
@top_level_called = true
|
56
|
-
ast1 = nil
|
57
|
-
ast2 = node
|
58
|
-
while ast1 != ast2
|
59
|
-
ast1 = super(ast2)
|
60
|
-
ast2 = super(ast1)
|
61
|
-
end
|
62
|
-
@top_level_called = false
|
63
|
-
ast1
|
64
|
-
end
|
46
|
+
def on_flow(node)
|
47
|
+
extract_volatiles(node)
|
48
|
+
node.updated(nil, optimize(process_all(node.children)))
|
65
49
|
end
|
66
50
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
51
|
+
def on_flow_flag(node)
|
52
|
+
flag, state, *nodes = *node
|
53
|
+
if conditions_to_remove.any? { |c| node.type == c.type && c.to_a == [flag, state] }
|
54
|
+
if volatile?(flag)
|
55
|
+
result = n(:inline, optimize(process_all(nodes)))
|
56
|
+
else
|
57
|
+
# This ensures any duplicate conditions matching the current one get removed
|
58
|
+
conditions_to_remove << node.updated(nil, [flag, state])
|
59
|
+
result = n(:inline, optimize(process_all(nodes)))
|
60
|
+
conditions_to_remove.pop
|
61
|
+
end
|
76
62
|
else
|
77
|
-
|
63
|
+
if volatile?(flag)
|
64
|
+
result = node.updated(nil, [flag, state] + optimize(process_all(nodes)))
|
65
|
+
else
|
66
|
+
conditions_to_remove << node.updated(nil, [flag, state])
|
67
|
+
result = node.updated(nil, [flag, state] + optimize(process_all(nodes)))
|
68
|
+
conditions_to_remove.pop
|
69
|
+
end
|
78
70
|
end
|
71
|
+
result
|
79
72
|
end
|
80
|
-
alias_method :
|
81
|
-
alias_method :
|
82
|
-
alias_method :
|
83
|
-
alias_method :
|
73
|
+
alias_method :on_test_result, :on_flow_flag
|
74
|
+
alias_method :on_job, :on_flow_flag
|
75
|
+
alias_method :on_run_flag, :on_flow_flag
|
76
|
+
alias_method :on_test_executed, :on_flow_flag
|
84
77
|
|
85
78
|
def on_group(node)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
if condition_to_be_removed?(node)
|
92
|
-
process_all(children)
|
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
|
93
84
|
else
|
94
|
-
node.updated(nil, [name]
|
85
|
+
conditions_to_remove << node.updated(nil, [name])
|
86
|
+
result = node.updated(nil, [name] + optimize(process_all(nodes)))
|
87
|
+
conditions_to_remove.pop
|
95
88
|
end
|
89
|
+
result
|
96
90
|
end
|
97
91
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
if
|
103
|
-
|
92
|
+
def optimize(nodes)
|
93
|
+
results = []
|
94
|
+
node1 = nil
|
95
|
+
nodes.each do |node2|
|
96
|
+
if node1
|
97
|
+
if can_be_combined?(node1, node2)
|
98
|
+
node1 = process(combine(node1, node2))
|
99
|
+
else
|
100
|
+
results << node1
|
101
|
+
node1 = node2
|
102
|
+
end
|
103
|
+
else
|
104
|
+
node1 = node2
|
104
105
|
end
|
105
106
|
end
|
107
|
+
results << node1 if node1
|
108
|
+
results
|
106
109
|
end
|
107
110
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
if node1.type == node2.type
|
114
|
-
if node1.type == :group
|
115
|
-
node1.to_a.take(1) == node2.to_a.take(1)
|
116
|
-
else
|
117
|
-
node1.to_a.take(2) == node2.to_a.take(2)
|
118
|
-
end
|
111
|
+
def can_be_combined?(node1, node2)
|
112
|
+
if condition_node?(node1) && condition_node?(node2)
|
113
|
+
!(conditions(node1) & conditions(node2)).empty?
|
114
|
+
else
|
115
|
+
false
|
119
116
|
end
|
120
117
|
end
|
121
118
|
|
122
|
-
def
|
123
|
-
node.
|
119
|
+
def condition_node?(node)
|
120
|
+
node.respond_to?(:type) &&
|
121
|
+
[:flow_flag, :run_flag, :test_result, :group, :job, :test_executed].include?(node.type)
|
124
122
|
end
|
125
123
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
124
|
+
def combine(node1, node2)
|
125
|
+
common = conditions(node1) & conditions(node2)
|
126
|
+
common.each { |condition| conditions_to_remove << condition }
|
127
|
+
node1 = process(node1)
|
128
|
+
node1 = [node1] unless node1.is_a?(Array)
|
129
|
+
node2 = process(node2)
|
130
|
+
node2 = [node2] unless node2.is_a?(Array)
|
131
|
+
common.size.times { conditions_to_remove.pop }
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
test_a = nil
|
137
|
-
ConditionExtractor.new.run(nodes).each do |cond_b, test_b|
|
138
|
-
if cond_a
|
139
|
-
common = cond_a & cond_b
|
140
|
-
if common.empty?
|
141
|
-
result << combine(cond_a, extract_common_embedded_conditions(test_a))
|
142
|
-
cond_a = cond_b
|
143
|
-
test_a = test_b
|
144
|
-
else
|
145
|
-
a = combine(cond_a - common, test_a)
|
146
|
-
b = combine(cond_b - common, test_b)
|
147
|
-
cond_a = common
|
148
|
-
test_a = [a, b].flatten
|
149
|
-
end
|
133
|
+
node = nil
|
134
|
+
common.reverse_each do |condition|
|
135
|
+
if node
|
136
|
+
node = condition.updated(nil, condition.children + [node])
|
150
137
|
else
|
151
|
-
|
152
|
-
test_a = test_b
|
138
|
+
node = condition.updated(nil, condition.children + node1 + node2)
|
153
139
|
end
|
154
140
|
end
|
155
|
-
|
156
|
-
nodes
|
157
|
-
else
|
158
|
-
result << combine(cond_a, extract_common_embedded_conditions(test_a))
|
159
|
-
result.flatten
|
160
|
-
end
|
141
|
+
node
|
161
142
|
end
|
162
143
|
|
163
|
-
def
|
164
|
-
|
165
|
-
|
166
|
-
|
144
|
+
def conditions(node)
|
145
|
+
result = []
|
146
|
+
if [:flow_flag, :run_flag].include?(node.type)
|
147
|
+
flag, state, *children = *node
|
148
|
+
unless volatile?(flag)
|
149
|
+
result << node.updated(nil, [flag, state])
|
167
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
|
156
|
+
elsif node.type == :group
|
157
|
+
name, *children = *node
|
158
|
+
# Sometimes a group can have an ID
|
159
|
+
if children.first.try(:type) == :id
|
160
|
+
result << node.updated(nil, [name, children.shift])
|
161
|
+
else
|
162
|
+
result << node.updated(nil, [name])
|
163
|
+
end
|
164
|
+
result += conditions(children.first) if children.first
|
168
165
|
end
|
169
|
-
|
166
|
+
result
|
170
167
|
end
|
171
168
|
|
172
|
-
def
|
173
|
-
@
|
169
|
+
def conditions_to_remove
|
170
|
+
@conditions_to_remove ||= []
|
174
171
|
end
|
175
172
|
end
|
176
173
|
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: 0.
|
4
|
+
version: 0.8.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: 2017-
|
11
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -77,7 +77,6 @@ files:
|
|
77
77
|
- lib/atp/processors/add_ids.rb
|
78
78
|
- lib/atp/processors/add_set_result.rb
|
79
79
|
- lib/atp/processors/condition.rb
|
80
|
-
- lib/atp/processors/condition_extractor.rb
|
81
80
|
- lib/atp/processors/flow_id.rb
|
82
81
|
- lib/atp/processors/marshal.rb
|
83
82
|
- lib/atp/processors/post_cleaner.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module ATP
|
2
|
-
module Processors
|
3
|
-
class ConditionExtractor < Processor
|
4
|
-
attr_reader :results, :conditions
|
5
|
-
|
6
|
-
def run(nodes)
|
7
|
-
@results = []
|
8
|
-
@conditions = []
|
9
|
-
process_all(nodes)
|
10
|
-
@results
|
11
|
-
end
|
12
|
-
|
13
|
-
def on_boolean_condition(node)
|
14
|
-
children = node.children.dup
|
15
|
-
name = children.shift
|
16
|
-
state = children.shift
|
17
|
-
conditions << node.updated(nil, [name, state])
|
18
|
-
process_all(children)
|
19
|
-
conditions.pop
|
20
|
-
end
|
21
|
-
alias_method :on_flow_flag, :on_boolean_condition
|
22
|
-
alias_method :on_test_result, :on_boolean_condition
|
23
|
-
alias_method :on_test_executed, :on_boolean_condition
|
24
|
-
alias_method :on_job, :on_boolean_condition
|
25
|
-
alias_method :on_run_flag, :on_boolean_condition
|
26
|
-
|
27
|
-
def on_group(node)
|
28
|
-
sig = node.children.select { |n| [:id, :name, :on_fail, :on_pass].include?(n.try(:type)) }
|
29
|
-
children = node.children.dup
|
30
|
-
conditions << node.updated(nil, sig)
|
31
|
-
process_all(children - sig)
|
32
|
-
conditions.pop
|
33
|
-
end
|
34
|
-
|
35
|
-
def on_test(node)
|
36
|
-
results << [conditions.uniq, node]
|
37
|
-
end
|
38
|
-
alias_method :on_log, :on_test
|
39
|
-
alias_method :on_enable_flow_flag, :on_test
|
40
|
-
alias_method :on_disable_flow_flag, :on_test
|
41
|
-
alias_method :on_cz, :on_test
|
42
|
-
alias_method :on_set_result, :on_test
|
43
|
-
alias_method :on_render, :on_test
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|