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
@@ -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.
|