atp 0.2.1 → 0.3.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 +2 -2
- data/lib/atp.rb +3 -3
- data/lib/atp/ast/builder.rb +20 -24
- data/lib/atp/ast/node.rb +3 -12
- data/lib/atp/flow.rb +101 -5
- data/lib/atp/formatters/basic.rb +1 -1
- data/lib/atp/formatters/datalog.rb +45 -5
- data/lib/atp/processors/add_ids.rb +23 -0
- data/lib/atp/processors/condition.rb +2 -2
- data/lib/atp/processors/condition_extractor.rb +1 -1
- data/lib/atp/processors/marshal.rb +14 -0
- data/lib/atp/program.rb +16 -0
- data/lib/atp/runner.rb +106 -4
- data/lib/atp/validator.rb +11 -1
- data/lib/atp/validators/jobs.rb +53 -0
- metadata +5 -5
- data/lib/atp/and.rb +0 -11
- data/lib/atp/not.rb +0 -13
- data/lib/atp/or.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cdbd30f66efb6b3795073de37ccdf0623377b7b
|
4
|
+
data.tar.gz: 4b3deec7a4e80eaa56dfd1b14934790a044ab611
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5309d2a1ddef3772ae949e47d3ce750a3eee0236498741cc0d752e3a7973fca9a016186ff17c02d54095055af51676b03eb2af8d6a23ebf695d7273096b5a406
|
7
|
+
data.tar.gz: b391e87fa09e223a717b6f11842ca2af604b33849ade223a657f8acaa5202dc90153070a89c4117b6a99fdb8e36bfa2dbef633b22957032c274aba6332eeffae
|
data/config/version.rb
CHANGED
data/lib/atp.rb
CHANGED
@@ -9,9 +9,6 @@ module ATP
|
|
9
9
|
autoload :Runner, 'atp/runner'
|
10
10
|
autoload :Formatter, 'atp/formatter'
|
11
11
|
autoload :Parser, 'atp/parser'
|
12
|
-
autoload :AND, 'atp/and'
|
13
|
-
autoload :OR, 'atp/or'
|
14
|
-
autoload :NOT, 'atp/not'
|
15
12
|
|
16
13
|
module AST
|
17
14
|
autoload :Node, 'atp/ast/node'
|
@@ -28,6 +25,8 @@ module ATP
|
|
28
25
|
autoload :Relationship, 'atp/processors/relationship'
|
29
26
|
autoload :PreCleaner, 'atp/processors/pre_cleaner'
|
30
27
|
autoload :PostCleaner, 'atp/processors/post_cleaner'
|
28
|
+
autoload :Marshal, 'atp/processors/marshal'
|
29
|
+
autoload :AddIDs, 'atp/processors/add_ids'
|
31
30
|
end
|
32
31
|
|
33
32
|
# Summarizers extract summary data from the given AST
|
@@ -40,6 +39,7 @@ module ATP
|
|
40
39
|
autoload :DuplicateIDs, 'atp/validators/duplicate_ids'
|
41
40
|
autoload :MissingIDs, 'atp/validators/missing_ids'
|
42
41
|
autoload :Condition, 'atp/validators/condition'
|
42
|
+
autoload :Jobs, 'atp/validators/jobs'
|
43
43
|
end
|
44
44
|
|
45
45
|
# Formatters are run on the processed AST to display the flow or to render
|
data/lib/atp/ast/builder.rb
CHANGED
@@ -47,6 +47,10 @@ module ATP
|
|
47
47
|
n(:test_executed, id, executed, node)
|
48
48
|
end
|
49
49
|
|
50
|
+
def job(id, enabled, node)
|
51
|
+
n(:job, id, enabled, node)
|
52
|
+
end
|
53
|
+
|
50
54
|
def enable_flow_flag(var, options = {})
|
51
55
|
test = n(:enable_flow_flag, var)
|
52
56
|
if options[:conditions]
|
@@ -93,7 +97,7 @@ module ATP
|
|
93
97
|
end
|
94
98
|
|
95
99
|
def new_context
|
96
|
-
@context = { conditions:
|
100
|
+
@context = { conditions: [] }
|
97
101
|
yield if block_given?
|
98
102
|
@context
|
99
103
|
end
|
@@ -115,8 +119,20 @@ module ATP
|
|
115
119
|
|
116
120
|
def apply_conditions(node, conditions)
|
117
121
|
conditions.each do |key, value|
|
122
|
+
# Sometimes conditions can be an array (in the case of the current context
|
123
|
+
# being re-used), so rectify that now
|
124
|
+
if key.is_a?(Hash)
|
125
|
+
fail 'Something has gone wrong applying the test conditions' if key.size > 1
|
126
|
+
key, value = key.first[0], key.first[1]
|
127
|
+
end
|
118
128
|
key = key.to_s.downcase.to_sym
|
119
|
-
|
129
|
+
# Represent all condition values as lower cased strings internally
|
130
|
+
if value.is_a?(Array)
|
131
|
+
value = value.map { |v| v.to_s.downcase }
|
132
|
+
else
|
133
|
+
value = value.to_s.downcase
|
134
|
+
end
|
135
|
+
context[:conditions] << { key => value }
|
120
136
|
case key
|
121
137
|
when :if_enabled, :enabled, :enable_flag, :enable, :if_enable
|
122
138
|
node = flow_flag(value, true, node)
|
@@ -149,17 +165,9 @@ module ATP
|
|
149
165
|
when :unless_ran, :unless_executed
|
150
166
|
node = test_executed(value, false, node)
|
151
167
|
when :job, :jobs, :if_job, :if_jobs
|
152
|
-
|
153
|
-
unless value.is_a?(OR)
|
154
|
-
value = ATP.or(value)
|
155
|
-
end
|
156
|
-
node = n(:job, apply_boolean(value), node)
|
168
|
+
node = job(value, true, node)
|
157
169
|
when :unless_job, :unless_jobs
|
158
|
-
|
159
|
-
unless value.is_a?(OR)
|
160
|
-
value = ATP.or(value)
|
161
|
-
end
|
162
|
-
node = n(:job, apply_boolean(ATP.not(value)), node)
|
170
|
+
node = job(value, false, node)
|
163
171
|
else
|
164
172
|
fail "Unknown test condition attribute - #{key} (#{value})"
|
165
173
|
end
|
@@ -167,18 +175,6 @@ module ATP
|
|
167
175
|
node
|
168
176
|
end
|
169
177
|
|
170
|
-
def apply_boolean(value)
|
171
|
-
if value.is_a?(OR)
|
172
|
-
n(:or, *value.map { |v| apply_boolean(v) })
|
173
|
-
elsif value.is_a?(AND)
|
174
|
-
n(:and, *value.map { |v| apply_boolean(v) })
|
175
|
-
elsif value.is_a?(NOT)
|
176
|
-
n(:not, apply_boolean(value.value))
|
177
|
-
else
|
178
|
-
value
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
178
|
def test(object, options = {})
|
183
179
|
children = [n(:object, object)]
|
184
180
|
|
data/lib/atp/ast/node.rb
CHANGED
@@ -4,7 +4,7 @@ module ATP
|
|
4
4
|
class Node < ::AST::Node
|
5
5
|
include Factories
|
6
6
|
|
7
|
-
attr_reader :file, :line_number
|
7
|
+
attr_reader :file, :line_number, :description
|
8
8
|
|
9
9
|
def initialize(type, children = [], properties = {})
|
10
10
|
# Always use strings instead of symbols in the AST, makes serializing
|
@@ -60,21 +60,12 @@ module ATP
|
|
60
60
|
|
61
61
|
# Returns the first child node of the given type that is found
|
62
62
|
def find(type)
|
63
|
-
|
64
|
-
nodes.first
|
63
|
+
children.find { |c| c.try(:type) == type }
|
65
64
|
end
|
66
65
|
|
67
66
|
# Returns an array containing all child nodes of the given type(s)
|
68
67
|
def find_all(*types)
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
def to_h
|
73
|
-
h = {}
|
74
|
-
children.each do |node|
|
75
|
-
h[node.type] = node.children.map { |n| n.is_a?(AST::Node) ? n.to_h : n }
|
76
|
-
end
|
77
|
-
h
|
68
|
+
children.select { |c| types.include?(c.try(:type)) }
|
78
69
|
end
|
79
70
|
end
|
80
71
|
end
|
data/lib/atp/flow.rb
CHANGED
@@ -9,10 +9,19 @@ module ATP
|
|
9
9
|
def initialize(program, name = nil)
|
10
10
|
@program = program
|
11
11
|
@name = name
|
12
|
-
@builder = AST::Builder.new
|
13
12
|
@raw = builder.flow
|
14
13
|
end
|
15
14
|
|
15
|
+
# @api private
|
16
|
+
def marshal_dump
|
17
|
+
[@name, @program, Processors::Marshal.new.process(@raw)]
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def marshal_load(array)
|
22
|
+
@name, @program, @raw = array
|
23
|
+
end
|
24
|
+
|
16
25
|
# Returns a processed/optimized AST, this is the one that should be
|
17
26
|
# used to build and represent the given test flow
|
18
27
|
def ast
|
@@ -22,6 +31,8 @@ module ATP
|
|
22
31
|
ast = Processors::Condition.new.process(ast)
|
23
32
|
ast = Processors::Relationship.new.process(ast)
|
24
33
|
ast = Processors::PostCleaner.new.process(ast)
|
34
|
+
Validators::Jobs.new(self).process(ast)
|
35
|
+
ast
|
25
36
|
end
|
26
37
|
|
27
38
|
# Group all tests generated within the given block
|
@@ -139,8 +150,97 @@ module ATP
|
|
139
150
|
nil
|
140
151
|
end
|
141
152
|
|
153
|
+
# Returns true if the test context generated from the supplied options + existing condition
|
154
|
+
# wrappers, is different from that which was applied to the previous test.
|
155
|
+
def context_changed?(options)
|
156
|
+
a = context[:conditions]
|
157
|
+
b = build_context(options)[:conditions]
|
158
|
+
!conditions_equal?(a, b)
|
159
|
+
end
|
160
|
+
|
161
|
+
def context
|
162
|
+
builder.context
|
163
|
+
end
|
164
|
+
|
142
165
|
private
|
143
166
|
|
167
|
+
def conditions_equal?(a, b)
|
168
|
+
if a.size == b.size
|
169
|
+
a = clean_condition(a)
|
170
|
+
b = clean_condition(b)
|
171
|
+
if a.keys.sort == b.keys.sort
|
172
|
+
a.all? do |key, value|
|
173
|
+
value.flatten.uniq.sort == b[key].flatten.uniq.sort
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def clean_condition(h)
|
180
|
+
c = {}
|
181
|
+
h.each do |hash|
|
182
|
+
key, value = hash.first[0], hash.first[1]
|
183
|
+
key = clean_key(key)
|
184
|
+
value = clean_value(value)
|
185
|
+
c[key] ||= []
|
186
|
+
c[key] << value unless c[key].include?(value)
|
187
|
+
end
|
188
|
+
c
|
189
|
+
end
|
190
|
+
|
191
|
+
def clean_value(value)
|
192
|
+
if value.is_a?(Array)
|
193
|
+
value.map { |v| v.to_s.downcase }.sort
|
194
|
+
else
|
195
|
+
value.to_s.downcase
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def clean_key(key)
|
200
|
+
case key.to_sym
|
201
|
+
when :if_enabled, :enabled, :enable_flag, :enable, :if_enable
|
202
|
+
:if_enable
|
203
|
+
when :unless_enabled, :not_enabled, :disabled, :disable, :unless_enable
|
204
|
+
:unless_enable
|
205
|
+
when :if_failed, :unless_passed, :failed
|
206
|
+
:if_failed
|
207
|
+
when :if_passed, :unless_failed, :passed
|
208
|
+
:if_passed
|
209
|
+
when :if_any_failed, :unless_all_passed
|
210
|
+
:if_any_failed
|
211
|
+
when :if_all_failed, :unless_any_passed
|
212
|
+
:if_all_failed
|
213
|
+
when :if_any_passed, :unless_all_failed
|
214
|
+
:if_any_passed
|
215
|
+
when :if_all_passed, :unless_any_failed
|
216
|
+
:if_all_passed
|
217
|
+
when :if_ran, :if_executed
|
218
|
+
:if_ran
|
219
|
+
when :unless_ran, :unless_executed
|
220
|
+
:unless_ran
|
221
|
+
when :job, :jobs, :if_job, :if_jobs
|
222
|
+
:if_job
|
223
|
+
when :unless_job, :unless_jobs
|
224
|
+
:unless_job
|
225
|
+
else
|
226
|
+
fail "Unknown test condition attribute - #{key}"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def build_context(options)
|
231
|
+
c = open_conditions.dup
|
232
|
+
if options[:conditions]
|
233
|
+
options[:conditions].each do |key, value|
|
234
|
+
c << { key => value }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
{ conditions: c }
|
238
|
+
end
|
239
|
+
|
240
|
+
def builder
|
241
|
+
@builder ||= AST::Builder.new
|
242
|
+
end
|
243
|
+
|
144
244
|
def apply_open_conditions(options)
|
145
245
|
if options[:context] == :current
|
146
246
|
options[:conditions] = builder.context[:conditions]
|
@@ -180,9 +280,5 @@ module ATP
|
|
180
280
|
open_groups.last << node
|
181
281
|
end
|
182
282
|
end
|
183
|
-
|
184
|
-
def builder
|
185
|
-
@builder
|
186
|
-
end
|
187
283
|
end
|
188
284
|
end
|
data/lib/atp/formatters/basic.rb
CHANGED
@@ -1,20 +1,60 @@
|
|
1
|
+
require 'colored'
|
1
2
|
module ATP
|
2
3
|
module Formatters
|
3
4
|
# Outputs the given AST to something resembling an ATE datalog,
|
4
5
|
# this can optionally be rendered to a file or the console (the default).
|
5
6
|
class Datalog < Formatter
|
6
7
|
def on_flow(node)
|
7
|
-
|
8
|
+
str = 'Number'.ljust(15)
|
9
|
+
str += 'Result'.ljust(9)
|
10
|
+
str += 'Name'.ljust(55)
|
11
|
+
str += 'Test'.ljust(55)
|
12
|
+
str += 'ID'
|
13
|
+
puts str
|
8
14
|
process_all(node.children)
|
9
15
|
end
|
10
16
|
|
11
17
|
def on_test(node)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
str = "#{node.find(:number).try(:value)}".ljust(15)
|
19
|
+
if node.find(:failed)
|
20
|
+
str += 'FAIL'.ljust(9).red
|
21
|
+
else
|
22
|
+
str += 'PASS'.ljust(9)
|
23
|
+
end
|
24
|
+
str += "#{node.find(:name).value}".ljust(55)
|
25
|
+
str += "#{node.find(:object).value}".ljust(55)
|
26
|
+
str += "#{node.find(:id).value}"
|
16
27
|
puts str
|
17
28
|
end
|
29
|
+
|
30
|
+
def on_render(node)
|
31
|
+
puts '************ Directly rendered flow snippet ************'
|
32
|
+
puts node.value
|
33
|
+
puts '********************************************************'
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_log(node)
|
37
|
+
puts "// #{node.value}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_set_result(node)
|
41
|
+
bin = node.find(:bin).try(:value)
|
42
|
+
sbin = node.find(:softbin).try(:value)
|
43
|
+
desc = node.find(:description).try(:value)
|
44
|
+
|
45
|
+
if node.to_a[0] == 'pass'
|
46
|
+
str = " PASS #{bin} #{sbin}"
|
47
|
+
color = :green
|
48
|
+
else
|
49
|
+
str = " FAIL #{bin} #{sbin}"
|
50
|
+
color = :red
|
51
|
+
end
|
52
|
+
str += " (#{desc})" if desc
|
53
|
+
|
54
|
+
puts '---------------------------------------------------------------------------------------------------------------------------------------------------------'
|
55
|
+
puts str.send(color)
|
56
|
+
puts '---------------------------------------------------------------------------------------------------------------------------------------------------------'
|
57
|
+
end
|
18
58
|
end
|
19
59
|
end
|
20
60
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Assigns an ID to all test nodes that don't have one
|
4
|
+
class AddIDs < Processor
|
5
|
+
def run(node)
|
6
|
+
@i = 0
|
7
|
+
process(node)
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_test(node)
|
11
|
+
@i += 1
|
12
|
+
node = node.ensure_node_present(:id)
|
13
|
+
node.updated(nil, process_all(node))
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_id(node)
|
17
|
+
unless node.value
|
18
|
+
node.updated(nil, ["t#{@i}"])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -77,6 +77,7 @@ module ATP
|
|
77
77
|
alias_method :on_flow_flag, :on_boolean_condition
|
78
78
|
alias_method :on_test_result, :on_boolean_condition
|
79
79
|
alias_method :on_test_executed, :on_boolean_condition
|
80
|
+
alias_method :on_job, :on_boolean_condition
|
80
81
|
|
81
82
|
def on_condition(node)
|
82
83
|
children = node.children.dup
|
@@ -91,7 +92,6 @@ module ATP
|
|
91
92
|
end
|
92
93
|
end
|
93
94
|
alias_method :on_group, :on_condition
|
94
|
-
alias_method :on_job, :on_condition
|
95
95
|
|
96
96
|
# Returns true if the given node contains the given condition within
|
97
97
|
# its immediate children
|
@@ -109,7 +109,7 @@ module ATP
|
|
109
109
|
|
110
110
|
def equal_conditions?(node1, node2)
|
111
111
|
if node1.type == node2.type
|
112
|
-
if node1.type == :group
|
112
|
+
if node1.type == :group
|
113
113
|
node1.to_a.take(1) == node2.to_a.take(1)
|
114
114
|
else
|
115
115
|
node1.to_a.take(2) == node2.to_a.take(2)
|
@@ -21,6 +21,7 @@ module ATP
|
|
21
21
|
alias_method :on_flow_flag, :on_boolean_condition
|
22
22
|
alias_method :on_test_result, :on_boolean_condition
|
23
23
|
alias_method :on_test_executed, :on_boolean_condition
|
24
|
+
alias_method :on_job, :on_boolean_condition
|
24
25
|
|
25
26
|
def on_condition(node)
|
26
27
|
children = node.children.dup
|
@@ -29,7 +30,6 @@ module ATP
|
|
29
30
|
process_all(children)
|
30
31
|
conditions.pop
|
31
32
|
end
|
32
|
-
alias_method :on_job, :on_condition
|
33
33
|
|
34
34
|
def on_test(node)
|
35
35
|
results << [conditions.uniq, node]
|
data/lib/atp/program.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
module ATP
|
2
2
|
# Program is the top-level container for a collection of test flows
|
3
3
|
class Program
|
4
|
+
# Load a program from a previously saved file
|
5
|
+
def self.load(file)
|
6
|
+
p = nil
|
7
|
+
File.open(file) do |f|
|
8
|
+
p = Marshal.load(f)
|
9
|
+
end
|
10
|
+
p
|
11
|
+
end
|
12
|
+
|
4
13
|
def flow(name)
|
5
14
|
flows[name] ||= Flow.new(self, name)
|
6
15
|
end
|
@@ -9,6 +18,13 @@ module ATP
|
|
9
18
|
@flows ||= {}
|
10
19
|
end
|
11
20
|
|
21
|
+
# Save the program to a file
|
22
|
+
def save(file)
|
23
|
+
File.open(file, 'w') do |f|
|
24
|
+
Marshal.dump(self, f)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
12
28
|
def respond_to?(*args)
|
13
29
|
flows.key?(args.first) || super
|
14
30
|
end
|
data/lib/atp/runner.rb
CHANGED
@@ -6,7 +6,9 @@ module ATP
|
|
6
6
|
class Runner < Processor
|
7
7
|
def run(node, options = {})
|
8
8
|
@options = options
|
9
|
-
|
9
|
+
@completed = false
|
10
|
+
@groups = []
|
11
|
+
process(Processors::AddIDs.new.run(node))
|
10
12
|
end
|
11
13
|
|
12
14
|
def on_flow(node)
|
@@ -17,8 +19,18 @@ module ATP
|
|
17
19
|
|
18
20
|
def on_flow_flag(node)
|
19
21
|
flag, enabled, *nodes = *node
|
20
|
-
|
21
|
-
|
22
|
+
flag = [flag].flatten
|
23
|
+
active = flag.any? { |f| flow_flags.include?(f) }
|
24
|
+
if (enabled && active) || (!enabled && !active)
|
25
|
+
process_all(nodes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_run_flag(node)
|
30
|
+
flag, enabled, *nodes = *node
|
31
|
+
flag = [flag].flatten
|
32
|
+
active = flag.any? { |f| run_flags.include?(f) }
|
33
|
+
if (enabled && active) || (!enabled && !active)
|
22
34
|
process_all(nodes)
|
23
35
|
end
|
24
36
|
end
|
@@ -28,9 +40,46 @@ module ATP
|
|
28
40
|
id = id.to_a[0]
|
29
41
|
if failed_test_ids.include?(id)
|
30
42
|
node = node.add(n0(:failed))
|
43
|
+
failed = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
@flow << node unless completed?
|
47
|
+
if failed
|
48
|
+
# Give indication to the parent group that at least one test within it failed
|
49
|
+
if @groups.last
|
50
|
+
@groups.pop
|
51
|
+
@groups << false
|
52
|
+
end
|
53
|
+
if n = node.find(:on_fail)
|
54
|
+
@continue = !!n.find(:continue)
|
55
|
+
process_all(n)
|
56
|
+
@continue = false
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if n = node.find(:on_pass)
|
60
|
+
process_all(n)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_group(node)
|
66
|
+
@groups << true # This will be set to false by any tests that fail within the group
|
67
|
+
process_all(node.find(:members))
|
68
|
+
if !@groups.pop # If failed
|
69
|
+
if n = node.find(:on_fail)
|
70
|
+
@continue = !!n.find(:continue)
|
71
|
+
process_all(n)
|
72
|
+
@continue = false
|
73
|
+
end
|
74
|
+
else
|
75
|
+
if n = node.find(:on_pass)
|
76
|
+
process_all(n)
|
31
77
|
end
|
32
78
|
end
|
33
|
-
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_members(node)
|
82
|
+
# Do nothing, will be processed directly by the on_group handler
|
34
83
|
end
|
35
84
|
|
36
85
|
def on_test_result(node)
|
@@ -41,13 +90,66 @@ module ATP
|
|
41
90
|
end
|
42
91
|
end
|
43
92
|
|
93
|
+
def on_set_result(node)
|
94
|
+
unless @continue
|
95
|
+
@flow << node unless completed?
|
96
|
+
@completed = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_set_run_flag(node)
|
101
|
+
run_flags << node.to_a[0]
|
102
|
+
end
|
103
|
+
|
104
|
+
def on_enable_flow_flag(node)
|
105
|
+
flow_flags << node.value unless flow_flags.include?(node.value)
|
106
|
+
end
|
107
|
+
|
108
|
+
def on_disable_flow_flag(node)
|
109
|
+
flow_flags.delete(node.value)
|
110
|
+
end
|
111
|
+
|
112
|
+
def on_log(node)
|
113
|
+
@flow << node unless completed?
|
114
|
+
end
|
115
|
+
alias_method :on_render, :on_log
|
116
|
+
|
117
|
+
def on_job(node)
|
118
|
+
jobs, state, *nodes = *node
|
119
|
+
jobs = clean_job(jobs)
|
120
|
+
unless job
|
121
|
+
fail 'Flow contains JOB-based conditions and no current JOB has been given!'
|
122
|
+
end
|
123
|
+
if state
|
124
|
+
process_all(node) if jobs.include?(job)
|
125
|
+
else
|
126
|
+
process_all(node) unless jobs.include?(job)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def clean_job(job)
|
131
|
+
[job].flatten.map { |j| j.to_s.upcase }
|
132
|
+
end
|
133
|
+
|
134
|
+
def job
|
135
|
+
@options[:job].to_s.upcase if @options[:job]
|
136
|
+
end
|
137
|
+
|
44
138
|
def failed_test_ids
|
45
139
|
@failed_test_ids ||= [@options[:failed_test_id] || @options[:failed_test_ids]].flatten.compact
|
46
140
|
end
|
47
141
|
|
142
|
+
def run_flags
|
143
|
+
@run_flags ||= []
|
144
|
+
end
|
145
|
+
|
48
146
|
# Returns an array of enabled flow flags
|
49
147
|
def flow_flags
|
50
148
|
@flow_flags ||= [@options[:flow_flag] || @options[:flow_flags]].flatten.compact
|
51
149
|
end
|
150
|
+
|
151
|
+
def completed?
|
152
|
+
@completed
|
153
|
+
end
|
52
154
|
end
|
53
155
|
end
|
data/lib/atp/validator.rb
CHANGED
@@ -14,10 +14,20 @@ module ATP
|
|
14
14
|
@top_level_called = true
|
15
15
|
setup
|
16
16
|
super(node)
|
17
|
-
|
17
|
+
unless @testing
|
18
|
+
exit 1 if on_completion
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
# For test purposes, returns true if validation failed rather
|
24
|
+
# than exiting the process
|
25
|
+
def test_process(node)
|
26
|
+
@testing = true
|
27
|
+
process(node)
|
28
|
+
on_completion
|
29
|
+
end
|
30
|
+
|
21
31
|
def setup
|
22
32
|
end
|
23
33
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ATP
|
2
|
+
module Validators
|
3
|
+
class Jobs < Validator
|
4
|
+
def setup
|
5
|
+
@conflicting = []
|
6
|
+
@negative = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_completion
|
10
|
+
failed = false
|
11
|
+
unless @conflicting.empty?
|
12
|
+
Origen.log.error 'if_job and unless_job conditions cannot both be applied to the same tests'
|
13
|
+
Origen.log.error "The following conflicts were found in flow #{flow.name}:"
|
14
|
+
@conflicting.each do |a, b|
|
15
|
+
a_condition = a.to_a[1] ? 'if_job: ' : 'unless_job:'
|
16
|
+
b_condition = b.to_a[1] ? 'if_job: ' : 'unless_job:'
|
17
|
+
Origen.log.error " #{a_condition} #{a.source}"
|
18
|
+
Origen.log.error " #{b_condition} #{b.source}"
|
19
|
+
Origen.log.error ''
|
20
|
+
end
|
21
|
+
failed = true
|
22
|
+
end
|
23
|
+
|
24
|
+
unless @negative.empty?
|
25
|
+
Origen.log.error 'Job names should not be negated, use unless_job if you want to specify !JOB'
|
26
|
+
Origen.log.error "The following negative job names were found in flow #{flow.name}:"
|
27
|
+
@negative.each do |node|
|
28
|
+
Origen.log.error " #{node.to_a[0]} #{node.source}"
|
29
|
+
end
|
30
|
+
failed = true
|
31
|
+
end
|
32
|
+
|
33
|
+
failed
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_job(node)
|
37
|
+
jobs, state, *nodes = *node
|
38
|
+
jobs = [jobs].flatten
|
39
|
+
if jobs.any? { |j| j.to_s =~ /^(!|~)/ }
|
40
|
+
@negative << node
|
41
|
+
end
|
42
|
+
@stack ||= []
|
43
|
+
if !@stack.empty? && @stack.last[1] != state
|
44
|
+
@conflicting << [@stack.last[0], node]
|
45
|
+
else
|
46
|
+
@stack << [node, state]
|
47
|
+
process_all(node)
|
48
|
+
@stack.pop
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
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.3.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: 2016-
|
11
|
+
date: 2016-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -64,7 +64,6 @@ files:
|
|
64
64
|
- config/commands.rb
|
65
65
|
- config/version.rb
|
66
66
|
- lib/atp.rb
|
67
|
-
- lib/atp/and.rb
|
68
67
|
- lib/atp/ast/builder.rb
|
69
68
|
- lib/atp/ast/extractor.rb
|
70
69
|
- lib/atp/ast/factories.rb
|
@@ -73,12 +72,12 @@ files:
|
|
73
72
|
- lib/atp/formatter.rb
|
74
73
|
- lib/atp/formatters/basic.rb
|
75
74
|
- lib/atp/formatters/datalog.rb
|
76
|
-
- lib/atp/not.rb
|
77
|
-
- lib/atp/or.rb
|
78
75
|
- lib/atp/parser.rb
|
79
76
|
- lib/atp/processor.rb
|
77
|
+
- lib/atp/processors/add_ids.rb
|
80
78
|
- lib/atp/processors/condition.rb
|
81
79
|
- lib/atp/processors/condition_extractor.rb
|
80
|
+
- lib/atp/processors/marshal.rb
|
82
81
|
- lib/atp/processors/post_cleaner.rb
|
83
82
|
- lib/atp/processors/pre_cleaner.rb
|
84
83
|
- lib/atp/processors/relationship.rb
|
@@ -87,6 +86,7 @@ files:
|
|
87
86
|
- lib/atp/validator.rb
|
88
87
|
- lib/atp/validators/condition.rb
|
89
88
|
- lib/atp/validators/duplicate_ids.rb
|
89
|
+
- lib/atp/validators/jobs.rb
|
90
90
|
- lib/atp/validators/missing_ids.rb
|
91
91
|
- lib/tasks/atp.rake
|
92
92
|
- templates/web/archive.md.erb
|
data/lib/atp/and.rb
DELETED
data/lib/atp/not.rb
DELETED