atp 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/{environment.rb → boot.rb} +0 -0
- data/config/commands.rb +10 -10
- data/config/version.rb +1 -1
- data/lib/atp.rb +53 -9
- data/lib/atp/and.rb +11 -0
- data/lib/atp/ast/builder.rb +214 -0
- data/lib/atp/ast/extractor.rb +26 -0
- data/lib/atp/ast/factories.rb +13 -0
- data/lib/atp/ast/node.rb +71 -0
- data/lib/atp/flow.rb +140 -0
- data/lib/atp/formatter.rb +20 -0
- data/lib/atp/formatters/basic.rb +18 -0
- data/lib/atp/formatters/datalog.rb +20 -0
- data/lib/atp/not.rb +13 -0
- data/lib/atp/or.rb +11 -0
- data/lib/atp/parser.rb +26 -0
- data/lib/atp/processor.rb +38 -0
- data/lib/atp/processors/condition.rb +174 -0
- data/lib/atp/processors/post_cleaner.rb +43 -0
- data/lib/atp/processors/pre_cleaner.rb +43 -0
- data/lib/atp/processors/relationship.rb +154 -0
- data/lib/atp/program.rb +27 -0
- data/lib/atp/runner.rb +53 -0
- data/lib/atp/validators/condition.rb +4 -0
- metadata +55 -10
- data/config/development.rb +0 -12
- data/config/users.rb +0 -29
- data/lib/atp/top_level.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ca6eaefd174b135c5b39a8b2d287f24cd890814
|
4
|
+
data.tar.gz: 3c379de6d014a88c5dbec902ec85eda2d4d1abd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec297a8c950f05a49eaa17c359d5c35378aea3e9a1e39f88f3c72906968658dc22e61590357f83b462f25dab699a1577d7d334efdb26d126b0f3694a159eaa9f
|
7
|
+
data.tar.gz: 1fc8899484368c2fc172801ba5bae1968fd9488d52420d0f0c30e1275a9db41783ab2886536317ca5744e2b7222badee59a9e6d5006d373b827f6e90d3bb6d80
|
File without changes
|
data/config/commands.rb
CHANGED
@@ -29,13 +29,13 @@ when "my_command"
|
|
29
29
|
# control flowing back to Origen
|
30
30
|
exit 0
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
# Example of how to make a command to run unit tests, this simply invokes RSpec on
|
33
|
+
# the spec directory
|
34
|
+
when "specs"
|
35
|
+
ARGV.unshift "spec"
|
36
|
+
require "rspec"
|
37
|
+
require "rspec/autorun"
|
38
|
+
exit 0 # This will never be hit on a fail, RSpec will automatically exit 1
|
39
39
|
|
40
40
|
## Example of how to make a command to run diff-based tests
|
41
41
|
#when "examples"
|
@@ -68,9 +68,9 @@ else
|
|
68
68
|
# You probably want to also add the your commands to the help shown via
|
69
69
|
# origen -h, you can do this be assigning the required text to @application_commands
|
70
70
|
# before handing control back to Origen. Un-comment the example below to get started.
|
71
|
-
|
72
|
-
|
71
|
+
@application_commands = <<-EOT
|
72
|
+
specs Run the specs (tests), -c will enable coverage
|
73
|
+
EOT
|
73
74
|
# examples Run the examples (tests), -c will enable coverage
|
74
|
-
# EOT
|
75
75
|
|
76
76
|
end
|
data/config/version.rb
CHANGED
data/lib/atp.rb
CHANGED
@@ -1,15 +1,59 @@
|
|
1
1
|
require 'origen'
|
2
|
-
require_relative '../config/application.rb'
|
2
|
+
require_relative '../config/application.rb'
|
3
3
|
module ATP
|
4
|
+
autoload :Program, 'atp/program'
|
5
|
+
autoload :Flow, 'atp/flow'
|
6
|
+
autoload :Processor, 'atp/processor'
|
7
|
+
autoload :Runner, 'atp/runner'
|
8
|
+
autoload :Formatter, 'atp/formatter'
|
9
|
+
autoload :Parser, 'atp/parser'
|
10
|
+
autoload :AND, 'atp/and'
|
11
|
+
autoload :OR, 'atp/or'
|
12
|
+
autoload :NOT, 'atp/not'
|
4
13
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# you can do that one manually and the let the wildcard take care of the rest.
|
11
|
-
Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").sort.each do |file|
|
12
|
-
require file
|
14
|
+
module AST
|
15
|
+
autoload :Node, 'atp/ast/node'
|
16
|
+
autoload :Builder, 'atp/ast/builder'
|
17
|
+
autoload :Factories, 'atp/ast/factories'
|
18
|
+
autoload :Extractor, 'atp/ast/extractor'
|
13
19
|
end
|
14
20
|
|
21
|
+
# Processors actually modify the AST to clean and optimize the user input
|
22
|
+
# and to implement the flow control API
|
23
|
+
module Processors
|
24
|
+
autoload :Condition, 'atp/processors/condition'
|
25
|
+
autoload :Relationship, 'atp/processors/relationship'
|
26
|
+
autoload :PreCleaner, 'atp/processors/pre_cleaner'
|
27
|
+
autoload :PostCleaner, 'atp/processors/post_cleaner'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Summarizers extract summary data from the given AST
|
31
|
+
module Summarizers
|
32
|
+
end
|
33
|
+
|
34
|
+
# Validators are run on the processed AST to check it for common errors or
|
35
|
+
# logical issues that will prevent it being rendered to a test program format
|
36
|
+
module Validators
|
37
|
+
autoload :Condition, 'atp/validators/condition'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Formatters are run on the processed AST to display the flow or to render
|
41
|
+
# it to a different format
|
42
|
+
module Formatters
|
43
|
+
autoload :Basic, 'atp/formatters/basic'
|
44
|
+
autoload :Datalog, 'atp/formatters/datalog'
|
45
|
+
autoload :Graph, 'atp/formatters/graph'
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.or(*args)
|
49
|
+
OR.new(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.and(*args)
|
53
|
+
AND.new(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.not(*args)
|
57
|
+
NOT.new(*args)
|
58
|
+
end
|
15
59
|
end
|
data/lib/atp/and.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
module ATP
|
2
|
+
module AST
|
3
|
+
class Builder
|
4
|
+
include Factories
|
5
|
+
|
6
|
+
attr_reader :context
|
7
|
+
|
8
|
+
def flow
|
9
|
+
n0(:flow)
|
10
|
+
end
|
11
|
+
|
12
|
+
def name(str)
|
13
|
+
n(:name, str.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def log(str)
|
17
|
+
n(:log, str.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(str)
|
21
|
+
n(:render, str.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
def description(str)
|
25
|
+
n(:description, str.to_s)
|
26
|
+
end
|
27
|
+
|
28
|
+
def id(symbol)
|
29
|
+
n(:id, symbol.to_sym)
|
30
|
+
end
|
31
|
+
|
32
|
+
def flow_flag(name, enabled, node)
|
33
|
+
n(:flow_flag, name, enabled, node)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_result(id, passed, node)
|
37
|
+
n(:test_result, id, passed, node)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_executed(id, executed, node)
|
41
|
+
n(:test_executed, id, executed, node)
|
42
|
+
end
|
43
|
+
|
44
|
+
def group(group_name, nodes, options = {})
|
45
|
+
children = [name(group_name)]
|
46
|
+
|
47
|
+
children << id(options[:id].to_s.downcase.to_sym) if options[:id]
|
48
|
+
|
49
|
+
children << on_fail(options[:on_fail]) if options[:on_fail]
|
50
|
+
children << on_pass(options[:on_pass]) if options[:on_pass]
|
51
|
+
|
52
|
+
children << n(:members, *nodes)
|
53
|
+
group = n(:group, *children)
|
54
|
+
|
55
|
+
if options[:conditions]
|
56
|
+
apply_conditions(group, options[:conditions])
|
57
|
+
else
|
58
|
+
group
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def cz(setup, node)
|
63
|
+
n(:cz, setup, node)
|
64
|
+
end
|
65
|
+
|
66
|
+
def new_context
|
67
|
+
@context = { conditions: {} }
|
68
|
+
yield if block_given?
|
69
|
+
@context
|
70
|
+
end
|
71
|
+
|
72
|
+
CONDITION_KEYS = [
|
73
|
+
:if_enabled, :enabled, :enable_flag, :enable, :if_enable,
|
74
|
+
:unless_enabled, :not_enabled, :disabled, :disable, :unless_enable,
|
75
|
+
:if_failed, :unless_passed, :failed,
|
76
|
+
:if_passed, :unless_failed, :passed,
|
77
|
+
:if_ran, :if_executed,
|
78
|
+
:unless_ran, :unless_executed,
|
79
|
+
:job, :jobs, :if_job, :if_jobs,
|
80
|
+
:unless_job, :unless_jobs,
|
81
|
+
:if_any_failed, :unless_all_passed,
|
82
|
+
:if_all_failed, :unless_any_passed,
|
83
|
+
:if_any_passed, :unless_all_failed,
|
84
|
+
:if_all_passed, :unless_any_failed
|
85
|
+
]
|
86
|
+
|
87
|
+
def apply_conditions(node, conditions)
|
88
|
+
conditions.each do |key, value|
|
89
|
+
key = key.to_s.downcase.to_sym
|
90
|
+
context[:conditions][key] = value
|
91
|
+
case key
|
92
|
+
when :if_enabled, :enabled, :enable_flag, :enable, :if_enable
|
93
|
+
node = flow_flag(value, true, node)
|
94
|
+
when :unless_enabled, :not_enabled, :disabled, :disable, :unless_enable
|
95
|
+
node = flow_flag(value, false, node)
|
96
|
+
when :if_failed, :unless_passed, :failed
|
97
|
+
if value.is_a?(Array)
|
98
|
+
fail 'if_failed only accepts one ID, use if_any_failed or if_all_failed for multiple IDs'
|
99
|
+
end
|
100
|
+
node = test_result(value, false, node)
|
101
|
+
when :if_passed, :unless_failed, :passed
|
102
|
+
if value.is_a?(Array)
|
103
|
+
fail 'if_passed only accepts one ID, use if_any_passed or if_all_passed for multiple IDs'
|
104
|
+
end
|
105
|
+
node = test_result(value, true, node)
|
106
|
+
when :if_any_failed, :unless_all_passed
|
107
|
+
node = test_result(value, false, node)
|
108
|
+
when :if_all_failed, :unless_any_passed
|
109
|
+
node = value.reduce(nil) do |nodes, val|
|
110
|
+
test_result(val, false, nodes ? nodes : node)
|
111
|
+
end
|
112
|
+
when :if_any_passed, :unless_all_failed
|
113
|
+
node = test_result(value, true, node)
|
114
|
+
when :if_all_passed, :unless_any_failed
|
115
|
+
node = value.reduce(nil) do |nodes, val|
|
116
|
+
test_result(val, true, nodes ? nodes : node)
|
117
|
+
end
|
118
|
+
when :if_ran, :if_executed
|
119
|
+
node = test_executed(value, true, node)
|
120
|
+
when :unless_ran, :unless_executed
|
121
|
+
node = test_executed(value, false, node)
|
122
|
+
when :job, :jobs, :if_job, :if_jobs
|
123
|
+
# Make sure these are wrapped by an OR, AND jobs doesn't make sense anyway
|
124
|
+
unless value.is_a?(OR)
|
125
|
+
value = ATP.or(value)
|
126
|
+
end
|
127
|
+
node = n(:job, apply_boolean(value), node)
|
128
|
+
when :unless_job, :unless_jobs
|
129
|
+
# Make sure these are wrapped by an OR, AND jobs doesn't make sense anyway
|
130
|
+
unless value.is_a?(OR)
|
131
|
+
value = ATP.or(value)
|
132
|
+
end
|
133
|
+
node = n(:job, apply_boolean(ATP.not(value)), node)
|
134
|
+
else
|
135
|
+
fail "Unknown test condition attribute - #{key} (#{value})"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
node
|
139
|
+
end
|
140
|
+
|
141
|
+
def apply_boolean(value)
|
142
|
+
if value.is_a?(OR)
|
143
|
+
n(:or, *value.map { |v| apply_boolean(v) })
|
144
|
+
elsif value.is_a?(AND)
|
145
|
+
n(:and, *value.map { |v| apply_boolean(v) })
|
146
|
+
elsif value.is_a?(NOT)
|
147
|
+
n(:not, apply_boolean(value.value))
|
148
|
+
else
|
149
|
+
value
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test(object, options = {})
|
154
|
+
children = [n(:object, object)]
|
155
|
+
|
156
|
+
if n = (options[:name] || options[:tname] || options[:test_name])
|
157
|
+
children << name(n)
|
158
|
+
end
|
159
|
+
if n = (options[:number] || options[:num] || options[:tnum] || options[:test_number])
|
160
|
+
children << number(n)
|
161
|
+
end
|
162
|
+
d = options[:description] || options[:desc]
|
163
|
+
children << description(d) if d
|
164
|
+
children << id(options[:id].to_s.downcase.to_sym) if options[:id]
|
165
|
+
|
166
|
+
children << on_fail(options[:on_fail]) if options[:on_fail]
|
167
|
+
children << on_pass(options[:on_pass]) if options[:on_pass]
|
168
|
+
|
169
|
+
test = n(:test, *children)
|
170
|
+
|
171
|
+
if options[:conditions]
|
172
|
+
apply_conditions(test, options[:conditions])
|
173
|
+
else
|
174
|
+
test
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_fail(options = {})
|
179
|
+
children = []
|
180
|
+
if options[:bin] || options[:softbin]
|
181
|
+
children << set_result(:fail, bin: options[:bin], softbin: options[:softbin], description: options[:bin_description])
|
182
|
+
end
|
183
|
+
children << continue if options[:continue]
|
184
|
+
n(:on_fail, *children)
|
185
|
+
end
|
186
|
+
|
187
|
+
def on_pass(options = {})
|
188
|
+
children = []
|
189
|
+
if options[:bin] || options[:softbin]
|
190
|
+
children << set_result(:pass, bin: options[:bin], softbin: options[:softbin], description: options[:bin_description])
|
191
|
+
end
|
192
|
+
children << continue if options[:continue]
|
193
|
+
n(:on_pass, *children)
|
194
|
+
end
|
195
|
+
|
196
|
+
def set_result(type, options = {})
|
197
|
+
children = []
|
198
|
+
children << type
|
199
|
+
children << n(:bin, options[:bin]) if options[:bin]
|
200
|
+
children << n(:softbin, options[:softbin]) if options[:softbin]
|
201
|
+
children << n(:description, options[:description]) if options[:description]
|
202
|
+
n(:set_result, *children)
|
203
|
+
end
|
204
|
+
|
205
|
+
def number(val)
|
206
|
+
n(:number, val.to_i)
|
207
|
+
end
|
208
|
+
|
209
|
+
def continue
|
210
|
+
n0(:continue)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ast'
|
2
|
+
module ATP
|
3
|
+
module AST
|
4
|
+
class Extractor
|
5
|
+
include ::AST::Processor::Mixin
|
6
|
+
|
7
|
+
attr_reader :types
|
8
|
+
attr_reader :results
|
9
|
+
|
10
|
+
def process(node, types = nil)
|
11
|
+
if types
|
12
|
+
@types = types
|
13
|
+
@results = []
|
14
|
+
# node = AST::Node.new(:wrapper, node) unless node.respond_to?(:to_ast)
|
15
|
+
end
|
16
|
+
super(node) if node.respond_to?(:to_ast)
|
17
|
+
results
|
18
|
+
end
|
19
|
+
|
20
|
+
def handler_missing(node)
|
21
|
+
@results << node if types.include?(node.type)
|
22
|
+
process_all(node.children)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/atp/ast/node.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'ast'
|
2
|
+
module ATP
|
3
|
+
module AST
|
4
|
+
class Node < ::AST::Node
|
5
|
+
include Factories
|
6
|
+
|
7
|
+
def initialize(type, children = [], properties = {})
|
8
|
+
# Always use strings instead of symbols in the AST, makes serializing
|
9
|
+
# back and forward to a string easier
|
10
|
+
children = children.map { |c| c.is_a?(Symbol) ? c.to_s : c }
|
11
|
+
super type, children, properties
|
12
|
+
end
|
13
|
+
|
14
|
+
# Create a new node from the given S-expression (a string)
|
15
|
+
def self.from_sexp(sexp)
|
16
|
+
@parser ||= Parser.new
|
17
|
+
@parser.string_to_ast(sexp)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Adds an empty node of the given type to the children unless another
|
21
|
+
# node of the same type is already present
|
22
|
+
def ensure_node_present(type)
|
23
|
+
if children.any? { |n| n.type == type }
|
24
|
+
self
|
25
|
+
else
|
26
|
+
updated(nil, children + [n0(type)])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the value at the root of an AST node like this:
|
31
|
+
#
|
32
|
+
# node # => (module-def
|
33
|
+
# (module-name
|
34
|
+
# (SCALAR-ID "Instrument"))
|
35
|
+
#
|
36
|
+
# node.value # => "Instrument"
|
37
|
+
#
|
38
|
+
# No error checking is done and the caller is responsible for calling
|
39
|
+
# this only on compatible nodes
|
40
|
+
def value
|
41
|
+
val = children.first
|
42
|
+
val = val.children.first while val.respond_to?(:children)
|
43
|
+
val
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add the given nodes to the children
|
47
|
+
def add(*nodes)
|
48
|
+
updated(nil, children + nodes)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the first child node of the given type that is found
|
52
|
+
def find(type)
|
53
|
+
nodes = find_all(type)
|
54
|
+
nodes.first
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns an array containing all child nodes of the given type(s)
|
58
|
+
def find_all(*types)
|
59
|
+
Extractor.new.process(self, types)
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_h
|
63
|
+
h = {}
|
64
|
+
children.each do |node|
|
65
|
+
h[node.type] = node.children.map { |n| n.is_a?(AST::Node) ? n.to_h : n }
|
66
|
+
end
|
67
|
+
h
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|