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.
@@ -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
@@ -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
@@ -0,0 +1,4 @@
1
+ module ATP
2
+ module Validators
3
+ end
4
+ 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.1.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: 2015-07-07 00:00:00.000000000 Z
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.0.6
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.0.6
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/top_level.rb
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.freescale.net/atp
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.4.8
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
@@ -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.