atp 0.1.0 → 0.2.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/{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
@@ -0,0 +1,43 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Runs at the very end of a processor run, to do some final cleanup,
|
4
|
+
# e.g. to assign generated IDs to tests that don't have one
|
5
|
+
class PostCleaner < Processor
|
6
|
+
# Returns a hash containing the IDs of all tests that have
|
7
|
+
# been used
|
8
|
+
attr_reader :ids
|
9
|
+
|
10
|
+
# Extracts all ID values of tests within the given AST
|
11
|
+
class ExtractTestIDs < Processor
|
12
|
+
attr_reader :results
|
13
|
+
|
14
|
+
def on_test(node)
|
15
|
+
id = node.children.find { |n| n.type == :id }
|
16
|
+
if id
|
17
|
+
@results ||= {}
|
18
|
+
@results[id] = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def process(node)
|
24
|
+
# On first call extract the test_result nodes from the given AST,
|
25
|
+
# then process as normal thereafter
|
26
|
+
if @first_call_done
|
27
|
+
result = super
|
28
|
+
else
|
29
|
+
@first_call_done = true
|
30
|
+
t = ExtractTestIDs.new
|
31
|
+
t.process(node)
|
32
|
+
@ids = t.results || {}
|
33
|
+
result = super
|
34
|
+
@first_call_done = false
|
35
|
+
end
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_test(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# Modifies the AST by performing some basic clean up, mainly to sanitize
|
4
|
+
# user input. For example it will ensure that all IDs are symbols, and that
|
5
|
+
# all names are lower-cased strings.
|
6
|
+
class PreCleaner < Processor
|
7
|
+
def initialize
|
8
|
+
@group_ids = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_id(node)
|
12
|
+
id = node.to_a.first
|
13
|
+
id = id.to_s.downcase.to_sym
|
14
|
+
node.updated(nil, [id])
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_group(node)
|
18
|
+
if id = node.children.find { |n| n.type == :id }
|
19
|
+
@group_ids << process(id).value
|
20
|
+
else
|
21
|
+
@group_ids << nil
|
22
|
+
end
|
23
|
+
group = node.updated(nil, process_all(node.children))
|
24
|
+
@group_ids.pop
|
25
|
+
group
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_test(node)
|
29
|
+
# Remove IDs nodes from test nodes if they refer to the ID of a parent group
|
30
|
+
if @group_ids.last
|
31
|
+
children = node.children.reject do |n|
|
32
|
+
if n.type == :id
|
33
|
+
@group_ids.last == process(n).value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
children = node.children
|
38
|
+
end
|
39
|
+
node.updated(nil, process_all(children))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module ATP
|
2
|
+
module Processors
|
3
|
+
# This processor will apply the relationships between tests, e.g. if testB should only
|
4
|
+
# execute if testA passes, then this processor will update the AST to make testA set
|
5
|
+
# a flag on pass, and then update testB to only run if that flag is set.
|
6
|
+
class Relationship < Processor
|
7
|
+
# Returns a hash containing the IDs of all tests that have dependents
|
8
|
+
attr_reader :test_results
|
9
|
+
|
10
|
+
# Extracts all test-result nodes from the given AST
|
11
|
+
class ExtractTestResults < Processor
|
12
|
+
attr_reader :results
|
13
|
+
|
14
|
+
def on_test_result(node)
|
15
|
+
ids, state, *children = *node
|
16
|
+
unless ids.is_a?(Array)
|
17
|
+
ids = [ids]
|
18
|
+
end
|
19
|
+
ids.each do |id|
|
20
|
+
results[id] ||= {}
|
21
|
+
if state
|
22
|
+
results[id][:passed] = true
|
23
|
+
else
|
24
|
+
results[id][:failed] = true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
process_all(children)
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_test_executed(node)
|
31
|
+
id, state, *children = *node
|
32
|
+
id, state = *node
|
33
|
+
results[id] ||= {}
|
34
|
+
results[id][:executed] = true
|
35
|
+
process_all(children)
|
36
|
+
end
|
37
|
+
|
38
|
+
def results
|
39
|
+
@results ||= {}.with_indifferent_access
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def process(node)
|
44
|
+
# On first call extract the test_result nodes from the given AST,
|
45
|
+
# then process as normal thereafter
|
46
|
+
if @first_call_done
|
47
|
+
result = super
|
48
|
+
else
|
49
|
+
@first_call_done = true
|
50
|
+
t = ExtractTestResults.new
|
51
|
+
t.process(node)
|
52
|
+
@test_results = t.results || {}
|
53
|
+
result = super
|
54
|
+
@first_call_done = false
|
55
|
+
end
|
56
|
+
result
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_pass_flag(id, node)
|
60
|
+
node = node.ensure_node_present(:on_pass)
|
61
|
+
node = node.ensure_node_present(:on_fail)
|
62
|
+
node.updated(nil, node.children.map do |n|
|
63
|
+
if n.type == :on_pass
|
64
|
+
n = n.add n1(:set_run_flag, "#{id}_PASSED")
|
65
|
+
elsif n.type == :on_fail
|
66
|
+
n.ensure_node_present(:continue)
|
67
|
+
else
|
68
|
+
n
|
69
|
+
end
|
70
|
+
end)
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_fail_flag(id, node)
|
74
|
+
node = node.ensure_node_present(:on_fail)
|
75
|
+
node.updated(nil, node.children.map do |n|
|
76
|
+
if n.type == :on_fail
|
77
|
+
n = n.add n1(:set_run_flag, "#{id}_FAILED")
|
78
|
+
n.ensure_node_present(:continue)
|
79
|
+
else
|
80
|
+
n
|
81
|
+
end
|
82
|
+
end)
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_executed_flag(id, node)
|
86
|
+
node = node.ensure_node_present(:on_fail)
|
87
|
+
node = node.ensure_node_present(:on_pass)
|
88
|
+
node.updated(nil, node.children.map do |n|
|
89
|
+
if n.type == :on_pass || n.type == :on_fail
|
90
|
+
n = n.add n1(:set_run_flag, "#{id}_RAN")
|
91
|
+
else
|
92
|
+
n
|
93
|
+
end
|
94
|
+
end)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set flags depending on the result on tests which have dependents later
|
98
|
+
# in the flow
|
99
|
+
def on_test(node)
|
100
|
+
nid = id(node)
|
101
|
+
# If this test has a dependent
|
102
|
+
if test_results[nid]
|
103
|
+
node = add_pass_flag(nid, node) if test_results[nid][:passed]
|
104
|
+
node = add_fail_flag(nid, node) if test_results[nid][:failed]
|
105
|
+
node = add_executed_flag(nid, node) if test_results[nid][:executed]
|
106
|
+
end
|
107
|
+
if node.type == :group
|
108
|
+
node.updated(nil, process_all(node))
|
109
|
+
else
|
110
|
+
node
|
111
|
+
end
|
112
|
+
end
|
113
|
+
alias_method :on_group, :on_test
|
114
|
+
|
115
|
+
# Remove test_result nodes and replace with references to the flags set
|
116
|
+
# up stream by the parent node
|
117
|
+
def on_test_result(node)
|
118
|
+
children = node.children.dup
|
119
|
+
id = children.shift
|
120
|
+
state = children.shift
|
121
|
+
if state
|
122
|
+
n(:run_flag, [id_to_flag(id, 'PASSED'), true] + process_all(children))
|
123
|
+
else
|
124
|
+
n(:run_flag, [id_to_flag(id, 'FAILED'), true] + process_all(children))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Remove test_result nodes and replace with references to the flags set
|
129
|
+
# up stream by the parent node
|
130
|
+
def on_test_executed(node)
|
131
|
+
children = node.children.dup
|
132
|
+
id = children.shift
|
133
|
+
state = children.shift
|
134
|
+
n(:run_flag, [id_to_flag(id, 'RAN'), state] + children)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns the ID of the give test node (if any), caller is responsible
|
138
|
+
# for only passing test nodes
|
139
|
+
def id(node)
|
140
|
+
if n = node.children.find { |c| c.type == :id }
|
141
|
+
n.children.first
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def id_to_flag(id, type)
|
146
|
+
if id.is_a?(Array)
|
147
|
+
id.map { |i| "#{i}_#{type}" }
|
148
|
+
else
|
149
|
+
"#{id}_#{type}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/atp/program.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module ATP
|
2
|
+
# Program is the top-level container for a collection of test flows
|
3
|
+
class Program
|
4
|
+
def flow(name)
|
5
|
+
flows[name] ||= Flow.new(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
def flows
|
9
|
+
@flows ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to?(*args)
|
13
|
+
flows.key?(args.first) || super
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(method, *args, &block) # :nodoc:
|
17
|
+
if f = flows[method]
|
18
|
+
define_singleton_method method do
|
19
|
+
f
|
20
|
+
end
|
21
|
+
f
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/atp/runner.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module ATP
|
2
|
+
# This class is responsible for executing the given test flow based on a given
|
3
|
+
# set of runtime conditions.
|
4
|
+
# A subset of the input AST will be returned containing only the nodes that would
|
5
|
+
# be hit when the flow is executed under the given conditions.
|
6
|
+
class Runner < Processor
|
7
|
+
def run(node, options = {})
|
8
|
+
@options = options
|
9
|
+
process(node)
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_flow(node)
|
13
|
+
@flow = []
|
14
|
+
process_all(node.children)
|
15
|
+
node.updated(nil, @flow)
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_flow_flag(node)
|
19
|
+
flag, enabled, *nodes = *node
|
20
|
+
if (enabled && flow_flags.include?(flag)) ||
|
21
|
+
(!enabled && !flow_flags.include?(flag))
|
22
|
+
process_all(nodes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_test(node)
|
27
|
+
if id = node.find(:id)
|
28
|
+
id = id.to_a[0]
|
29
|
+
if failed_test_ids.include?(id)
|
30
|
+
node = node.add(n0(:failed))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@flow << node
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_test_result(node)
|
37
|
+
id, passed, *nodes = *node
|
38
|
+
if (passed && !failed_test_ids.include?(id)) ||
|
39
|
+
(!passed && failed_test_ids.include?(id))
|
40
|
+
process_all(nodes)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def failed_test_ids
|
45
|
+
@failed_test_ids ||= [@options[:failed_test_id] || @options[:failed_test_ids]].flatten.compact
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns an array of enabled flow flags
|
49
|
+
def flow_flags
|
50
|
+
@flow_flags ||= [@options[:flow_flag] || @options[:flow_flags]].flatten.compact
|
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.2.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: 2016-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -16,14 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.2.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ast
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sexpistol
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.0'
|
27
55
|
description:
|
28
56
|
email:
|
29
57
|
- stephen.f.mcginty@gmail.com
|
@@ -32,13 +60,30 @@ extensions: []
|
|
32
60
|
extra_rdoc_files: []
|
33
61
|
files:
|
34
62
|
- config/application.rb
|
63
|
+
- config/boot.rb
|
35
64
|
- config/commands.rb
|
36
|
-
- config/development.rb
|
37
|
-
- config/environment.rb
|
38
|
-
- config/users.rb
|
39
65
|
- config/version.rb
|
40
66
|
- lib/atp.rb
|
41
|
-
- lib/atp/
|
67
|
+
- lib/atp/and.rb
|
68
|
+
- lib/atp/ast/builder.rb
|
69
|
+
- lib/atp/ast/extractor.rb
|
70
|
+
- lib/atp/ast/factories.rb
|
71
|
+
- lib/atp/ast/node.rb
|
72
|
+
- lib/atp/flow.rb
|
73
|
+
- lib/atp/formatter.rb
|
74
|
+
- lib/atp/formatters/basic.rb
|
75
|
+
- lib/atp/formatters/datalog.rb
|
76
|
+
- lib/atp/not.rb
|
77
|
+
- lib/atp/or.rb
|
78
|
+
- lib/atp/parser.rb
|
79
|
+
- lib/atp/processor.rb
|
80
|
+
- lib/atp/processors/condition.rb
|
81
|
+
- lib/atp/processors/post_cleaner.rb
|
82
|
+
- lib/atp/processors/pre_cleaner.rb
|
83
|
+
- lib/atp/processors/relationship.rb
|
84
|
+
- lib/atp/program.rb
|
85
|
+
- lib/atp/runner.rb
|
86
|
+
- lib/atp/validators/condition.rb
|
42
87
|
- lib/tasks/atp.rake
|
43
88
|
- templates/web/archive.md.erb
|
44
89
|
- templates/web/contact.md.erb
|
@@ -46,7 +91,7 @@ files:
|
|
46
91
|
- templates/web/layouts/_basic.html.erb
|
47
92
|
- templates/web/partials/_navbar.html.erb
|
48
93
|
- templates/web/release_notes.md.erb
|
49
|
-
homepage: http://origen.
|
94
|
+
homepage: http://origen-sdk.org/atp
|
50
95
|
licenses: []
|
51
96
|
metadata: {}
|
52
97
|
post_install_message:
|
@@ -65,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
110
|
version: 1.8.11
|
66
111
|
requirements: []
|
67
112
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
113
|
+
rubygems_version: 2.2.2
|
69
114
|
signing_key:
|
70
115
|
specification_version: 4
|
71
116
|
summary: An abstract test program model for Origen
|
data/config/development.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# This file is similar to environment.rb and will be loaded
|
2
|
-
# automatically at the start of each invocation of Origen.
|
3
|
-
#
|
4
|
-
# However the major difference is that it will not be loaded
|
5
|
-
# if the application is imported by a 3rd party app - in that
|
6
|
-
# case only environment.rb is loaded.
|
7
|
-
#
|
8
|
-
# Therefore this file should be used to load anything you need
|
9
|
-
# to setup a development environment for this app, normally
|
10
|
-
# this would be used to load some dummy classes to instantiate
|
11
|
-
# your objects so that they can be tested and/or interacted with
|
12
|
-
# in the console.
|