origen_testers 0.51.2 → 0.51.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1ba41af6b65ac674916979e0732f2ec945cd3871a9764ed26eed0c1fc9ad9df
4
- data.tar.gz: 63be076e3b7dfc1dfa525b420b233b8a79eb33f6c86a06852f0069f01cfd7668
3
+ metadata.gz: 3762e544f419c1c77e9f1d670c7203cd44e9ad6fef0246463f62c77e8592be92
4
+ data.tar.gz: 3c2e4679fae95dbb6f9976be317bbcf6c9fe3f8eff113d40fbdafe68cea06973
5
5
  SHA512:
6
- metadata.gz: 13f984fad6402b0749eaa3029aa8ccecf3870f6e534c553884a6dc6de42a11b4383e268378ec84968b7e71ce2ed75b800fe9c8f7128f37c32e3b1b78a7d70ec7
7
- data.tar.gz: a4b421dfd78750be92b44112ca13506a6f281a98ee9f84faa3ccf49b08a4e1f32fecfe979aa7f2eafb4f66a1875a66ad092949d39bd7638ccdbfb6ba812308a6
6
+ metadata.gz: 563af43372ac16a7159e4f1ca6d8aa8aed2fc630dc9224f477cb427332f76ec9ada304428caa15695cf48e7923fa3243154de71bc12b737e170d5370946a44f3
7
+ data.tar.gz: 2674ab9dda1e9b8e6a7816d5cab6add7eb9dc44b037ac2b12ef46a5d2473324632034faf88cf34998d501140eda7545a7ac19a8e0710ffb062c5523f93bdff49
data/config/commands.rb CHANGED
@@ -175,7 +175,7 @@ when "tags"
175
175
  # Run the unit tests
176
176
  when "specs"
177
177
  require "rspec"
178
- exit RSpec::Core::Runner.run(['spec'])
178
+ exit RSpec::Core::Runner.run($ARGV.empty? ? ['spec'] : $ARGV)
179
179
 
180
180
  # Run the example-based (diff) tests
181
181
  when "examples", "test"
data/config/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
3
  MINOR = 51
4
- BUGFIX = 2
4
+ BUGFIX = 3
5
5
  DEV = nil
6
6
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
7
7
  end
@@ -19,7 +19,7 @@ module OrigenTesters
19
19
  # @return [Array] list of charz routines to be called under this profile
20
20
  # @!attribute charz_only
21
21
  # @return [Boolean] indicates if the point tests should or shouldn't be added to the flow
22
- attr_accessor :id, :name, :placement, :on_result, :enables, :flags, :routines, :charz_only, :and_enables, :and_flags
22
+ attr_accessor :id, :name, :placement, :on_result, :enables, :flags, :routines, :charz_only, :force_keep_parent, :and_enables, :and_flags
23
23
 
24
24
  def initialize(id, options, &block)
25
25
  @id = id
@@ -30,6 +30,7 @@ module OrigenTesters
30
30
  @placement ||= :inline
31
31
  @defined_routines = options.delete(:defined_routines)
32
32
  attrs_ok?
33
+ massage_gates
33
34
  end
34
35
 
35
36
  def attrs_ok?
@@ -91,6 +92,20 @@ module OrigenTesters
91
92
  end
92
93
  end
93
94
 
95
+ # convert hash gates to set convert their routines to type array if not already
96
+ def massage_gates
97
+ if @enables.is_a?(Hash)
98
+ @enables = {}.tap do |new_h|
99
+ @enables.each { |gates, routines| new_h[gates] = [routines].flatten }
100
+ end
101
+ end
102
+ if @flags.is_a?(Hash)
103
+ @flags = {}.tap do |new_h|
104
+ @flags.each { |gates, routines| new_h[gates] = [routines].flatten }
105
+ end
106
+ end
107
+ end
108
+
94
109
  def gate_check(gates, gate_type)
95
110
  case gates
96
111
  when Symbol, String
@@ -1,30 +1,59 @@
1
1
  module OrigenTesters
2
2
  module Charz
3
3
  # A charz session
4
- # contains the final combination of charz object (routines/profiles) and user options to determine how and what charz tests should be created
4
+ # contains a collection of the final combinations of charz object (routines/profiles) and user options to determine how and what charz tests should be created
5
5
  # the session should be checked in your interface to determine the current status and can be queried to make charz generation decisions
6
- class Session < Profile
6
+ class Session
7
+ # @!attribute id
8
+ # @return [Symbol] current session ID. Will be a concatenation of the instances' ids
9
+ # @!attribute instances
10
+ # @return [Array] list of active instances (which are essentially Profiles)
11
+ # @!attribute current_instance
12
+ # @return [Profile] Set when looping over instances via #loop_instances. The interface can query the charz_instance for more detailed info
13
+ # @!attribute valid
14
+ # @return [Boolean] whether or not the current session setup is valid, if not then charz wont be created
7
15
  # @!attribute defaults
8
16
  # @return [Hash] list of values to instantiate the inherited attributes from Profile with if not altered by the session update
9
- attr_accessor :defaults
17
+ # @!attribute stored_instance
18
+ # @return [Profile] This is to store the instance that the interface is storing. Its to support a legacy usecase of querying the session for instance level info during EOF
19
+ attr_accessor :id, :instances, :current_instance, :valid, :defaults, :stored_instance
10
20
 
11
21
  def initialize(options = {})
12
- @id = :current_charz_session
22
+ @id = :empty_session
23
+ @instances = []
24
+ @current_instance = nil
25
+ @stored_instance = nil
13
26
  @active = false
14
27
  @valid = false
15
- if options[:defaults]
16
- @defaults = options[:defaults]
17
- else
18
- @defaults = {
19
- placement: :inline,
20
- on_result: nil,
21
- enables: nil,
22
- flags: nil,
23
- enables_and: nil,
24
- name: 'charz',
25
- charz_only: false
26
- }
27
- end
28
+ @defaults = {
29
+ placement: :inline,
30
+ routines: [],
31
+ on_result: nil,
32
+ enables: nil,
33
+ flags: nil,
34
+ enables_and: false,
35
+ and_enables: false,
36
+ flags_and: false,
37
+ and_flags: false,
38
+ name: 'charz',
39
+ charz_only: false,
40
+ force_keep_parent: false
41
+ }.merge((options[:defaults] || {}))
42
+ end
43
+
44
+ def on_result?
45
+ instances.any? { |charz_instance| !charz_instance.on_result.nil? }
46
+ end
47
+
48
+ def charz_only?
49
+ any_only = instances.any?(&:charz_only)
50
+ any_force = instances.any?(&:force_keep_parent)
51
+ !any_force && any_only && !on_result?
52
+ end
53
+
54
+ def charz_only
55
+ Origen.log.deprecate '#charz_only has been deprecated in favor of #charz_only? It is no longer an attribute, instead a runtime calculation.'
56
+ charz_only?
28
57
  end
29
58
 
30
59
  # Pauses the current session's activity while maintaining everthing else about the sessions state
@@ -32,6 +61,11 @@ module OrigenTesters
32
61
  @active = false
33
62
  end
34
63
 
64
+ def active?
65
+ !!@active
66
+ end
67
+ alias_method :active, :active?
68
+
35
69
  # Resume activity, if the session is valid
36
70
  def resume
37
71
  if @valid
@@ -39,72 +73,103 @@ module OrigenTesters
39
73
  end
40
74
  end
41
75
 
42
- # Takes a Routine or Profile, and queries it to setup the session's attributes
76
+ def current_instance
77
+ instance = @current_instance || instances.first
78
+ if instance.nil? && @stored_instance
79
+ Origen.log.deprecate '@current_instance had to source @stored_instance. This likely means charz_session.<some_attr> is being queried when the newer charz_instance.<some_attr> should be instead'
80
+ instance = @stored_instance
81
+ end
82
+ instance
83
+ end
84
+
85
+ def loop_instances
86
+ instances.each do |charz_instance|
87
+ @current_instance = charz_instance
88
+ yield
89
+ @current_instance = nil
90
+ end
91
+ end
92
+
93
+ # Takes a CharzTuple and queries it to setup an instance's attributes
43
94
  # the attributes values can be set from 3 different sources, in order of priority (first is most important):
44
95
  # - options
45
- # - charz object
96
+ # - charz object (Profile or Routine)
46
97
  # - defaults
47
98
  #
48
99
  # If the resulting session is invalid, @valid will turn false. Otherwise, the session becomes active
49
- def update(charz_obj, options)
100
+ def update(charz_tuples)
101
+ @instances = []
50
102
  @valid = false
51
- if charz_obj.nil?
103
+ if charz_tuples.nil? || charz_tuples.empty?
52
104
  @active = false
53
105
  @valid = false
106
+ @current_instance = nil
54
107
  return @valid
55
108
  end
56
- @defined_routines = options.delete(:defined_routines)
109
+ @defined_routines = charz_tuples.map(&:defined_routines).flatten.uniq.compact
57
110
 
58
- if charz_obj.and_flags
59
- @and_flags = charz_obj.and_flags
60
- else
61
- @and_flags = false
62
- end
63
- if charz_obj.and_enables
64
- @and_enables = charz_obj.and_enables
65
- else
66
- @and_enables = false
111
+ charz_tuples.each do |charz_tuple|
112
+ profile_options = assign_by_priority(charz_tuple)
113
+ @instances << Profile.new(charz_tuple.obj.id, profile_options.merge(defined_routines: @defined_routines))
67
114
  end
68
- assign_by_priority(:placement, charz_obj, options)
69
- assign_by_priority(:on_result, charz_obj, options)
70
- assign_by_priority(:enables, charz_obj, options)
71
- assign_by_priority(:flags, charz_obj, options)
72
- assign_by_priority(:routines, charz_obj, options)
73
- assign_by_priority(:name, charz_obj, options)
74
- assign_by_priority(:charz_only, charz_obj, options)
75
- attrs_ok?
76
- massage_gates
115
+ @id = instances.map(&:id).join('_').to_sym
77
116
  @active = true
78
117
  @valid = true
79
118
  end
80
119
 
81
120
  private
82
121
 
83
- # convert hash gates to set convert their routines to type array if not already
84
- def massage_gates
85
- if @enables.is_a?(Hash)
86
- @enables = {}.tap do |new_h|
87
- @enables.each { |gates, routines| new_h[gates] = [routines].flatten }
88
- end
89
- end
90
- if @flags.is_a?(Hash)
91
- @flags = {}.tap do |new_h|
92
- @flags.each { |gates, routines| new_h[gates] = [routines].flatten }
122
+ def assign_by_priority(charz_tuple)
123
+ options = charz_tuple.options
124
+ charz_obj = charz_tuple.obj
125
+ instance_options = {}
126
+ get_instance_setting_keys(charz_obj).each do |ivar|
127
+ if options.keys.include?(ivar)
128
+ instance_options[ivar] = options[ivar]
129
+ elsif charz_obj.send(ivar)
130
+ instance_options[ivar] = charz_obj.send(ivar)
131
+ elsif @defaults.keys.include?(ivar)
132
+ instance_options[ivar] = @defaults[ivar]
133
+ else
134
+ Origen.log.error "Charz Session: No value could be determined for #{ivar}"
135
+ fail
93
136
  end
94
137
  end
138
+ instance_options
95
139
  end
96
140
 
97
- # see initialize
98
- def assign_by_priority(ivar, charz_obj, options)
99
- if options.keys.include?(ivar)
100
- instance_variable_set("@#{ivar}", options[ivar])
101
- elsif charz_obj.send(ivar)
102
- instance_variable_set("@#{ivar}", charz_obj.send(ivar))
103
- elsif @defaults.keys.include?(ivar)
104
- instance_variable_set("@#{ivar}", @defaults[ivar])
141
+ def get_instance_setting_keys(charz_obj)
142
+ keys = charz_obj.instance_variables | @defaults.keys
143
+ keys.map! { |k| k.to_s.sub('@', '').to_sym }
144
+ keys -= [:id]
145
+ keys
146
+ end
147
+
148
+ def method_missing(method, *args, &block)
149
+ deprecated_methods = [
150
+ :name,
151
+ :placement,
152
+ :on_result,
153
+ :enables,
154
+ :flags,
155
+ :routines,
156
+ :and_enables,
157
+ :enables_and,
158
+ :and_flags,
159
+ :flags_and,
160
+ :charz_only,
161
+ :force_keep_parent
162
+ ]
163
+ if deprecated_methods.include?(method.to_sym) || deprecated_methods.include?(method.to_s[0..-2].to_sym)
164
+ Origen.log.deprecate "charz_session.#{method} has been deprecated. Please query charz_instance.#{method} instead."
165
+ if current_instance.nil? && !valid
166
+ Origen.log.error "blocked call of 'charz_session.#{method}'!"
167
+ Origen.log.warn 'The charz instance attributes are no longer accessible when the session is invalid!'
168
+ else
169
+ current_instance.send(method, *args, &block)
170
+ end
105
171
  else
106
- Origen.log.error "Charz Session: No value could be determined for #{ivar}"
107
- fail
172
+ super
108
173
  end
109
174
  end
110
175
  end
@@ -3,6 +3,7 @@ Dir.glob("#{File.dirname(__FILE__)}/charz/**/*.rb").sort.each do |file|
3
3
  end
4
4
  module OrigenTesters
5
5
  module Charz
6
+ CharzTuple = Struct.new(:obj, :options, :defined_routines, keyword_init: true)
6
7
  # @!attribute charz_stack
7
8
  # @return [Array] FILO queue of charz session defining data
8
9
  # @!attribute charz_routines
@@ -11,13 +12,15 @@ module OrigenTesters
11
12
  # @return [Hash] user defined charz profiles
12
13
  # @!attribute charz_session
13
14
  # @return [Session] current charz session, based on data in the top of the charz_stack
15
+ # @!attribute charz_instance
16
+ # @return [Session] current charz instance of the session. If there is not a current instance, will return the first instance of the session instance stack
14
17
  # @!attribute eof_charz_tests
15
18
  # @return [Array] charz tests to be added at the end of the flow
16
19
  # @!attribute skip_group_eof_charz_tests
17
20
  # @return [Boolean] whether or not to wrap eof charz tests in a group
18
21
  # @!attribute eof_charz_tests_group_name
19
22
  # @return [String, Symbol] group name to be used to for eof charz tests
20
- attr_accessor :charz_stack, :charz_routines, :charz_profiles, :charz_session, :eof_charz_tests, :skip_group_eof_charz_tests, :eof_charz_tests_group_name
23
+ attr_accessor :charz_stack, :charz_routines, :charz_profiles, :charz_session, :charz_instance, :eof_charz_tests, :skip_group_eof_charz_tests, :eof_charz_tests_group_name
21
24
 
22
25
  def charz_stack
23
26
  @charz_stack ||= []
@@ -35,6 +38,21 @@ module OrigenTesters
35
38
  @charz_session ||= Session.new
36
39
  end
37
40
 
41
+ # If there is a current instance present, that should always be used. However when running EOF charz,
42
+ # the instance to be used is no longer set, so instead of referencing the session, use the one that we've
43
+ # stored already
44
+ def charz_instance
45
+ unless charz_session.current_instance.nil?
46
+ set_charz_instance(charz_session.current_instance)
47
+ end
48
+ @charz_instance
49
+ end
50
+
51
+ def set_charz_instance(instance)
52
+ @charz_instance = instance
53
+ charz_session.stored_instance = instance
54
+ end
55
+
38
56
  def eof_charz_tests
39
57
  @eof_charz_tests ||= []
40
58
  end
@@ -106,12 +124,12 @@ module OrigenTesters
106
124
 
107
125
  # Queries the current charz session to see if its active, indicating point tests should be generating charz tests
108
126
  def charz_active?
109
- charz_session.active
127
+ charz_session.active?
110
128
  end
111
129
 
112
130
  # Queries the current charz session to see if point tests should skip generation, only adding the resulting charz test
113
131
  def charz_only?
114
- charz_active? && charz_session.charz_only
132
+ charz_active? && charz_session.charz_only?
115
133
  end
116
134
 
117
135
  # Pauses the current charz session, preventing point tests from generating charz tests even if the session is valid
@@ -129,10 +147,12 @@ module OrigenTesters
129
147
  # if not, the session will become inactive
130
148
  def charz_off
131
149
  charz_stack.pop
150
+ unless charz_session.update(charz_stack.last) || charz_stack.empty?
151
+ Origen.log.error 'charz_on failed to create a valid charz session'
152
+ fail
153
+ end
132
154
  if charz_stack.empty?
133
- update_charz_session(nil)
134
- else
135
- update_charz_session(*charz_stack.last)
155
+ set_charz_instance(nil)
136
156
  end
137
157
  end
138
158
 
@@ -145,36 +165,61 @@ module OrigenTesters
145
165
  # @param [Hash] options charz_on options
146
166
  # @option options [Symbol] :type (:profile) whether the charz_id refers to a charz profile or routine
147
167
  def charz_on(charz_id, options = {})
148
- options = {
149
- type: :profile
150
- }.merge(options)
151
- case options[:type]
152
- when :profile
153
- charz_obj = charz_profiles[charz_id]
154
- when :routine
155
- if charz_id.is_a?(Array)
156
- charz_obj = charz_routines[charz_id.first]
157
- options[:routines] = charz_id
158
- else
159
- charz_obj = charz_routines[charz_id]
160
- options[:routines] = [charz_id]
161
- end
162
- else
163
- Origen.log.error "Unknown charz object type #{options[:type]}, valid types: :profile, :routine"
168
+ charz_stack.push([get_charz_tuple(charz_id, options)])
169
+ unless charz_session.update(charz_stack.last)
170
+ Origen.log.error 'charz_on failed to create a valid charz session'
164
171
  fail
165
172
  end
166
- if charz_obj.nil?
167
- Origen.log.error "No #{options[:type]} found for charz_id: #{charz_id}"
168
- fail
173
+ if block_given?
174
+ yield
175
+ charz_off
169
176
  end
170
- charz_stack.push([charz_obj, options])
171
- unless update_charz_session(*charz_stack.last)
177
+ end
178
+
179
+ # Pushes a charz object (either a profile or a routine) onto the current sessions instance stack, along with any optional updates to modify that instance.
180
+ # This will result in subsequent charzable point tests in being processed against each of the current instances. In other words, this new push will not
181
+ # take priority over the current stack head, but instead append to it.
182
+ # Once pushed, the charz_session will attempt to update itself with the new data, failing if the resulting session is invalid
183
+ #
184
+ # If a block is passed, yield the block of tests to enable charz for those tests, then disable charz with a charz_off_truncate call
185
+ #
186
+ # @param [Symbol] charz_id either a routine or profile id. Method fails if the id can't be found in @charz_routines or @charz_profiles
187
+ # @param [Hash] options charz_on options
188
+ # @option options [Symbol] :type (:profile) whether the charz_id refers to a charz profile or routine
189
+ def charz_on_append(charz_id, options = {})
190
+ charz_tuple = get_charz_tuple(charz_id, options)
191
+
192
+ # take the current session and append to its instance stack
193
+ session = charz_stack.pop || []
194
+ session.push(charz_tuple)
195
+ charz_stack.push(session)
196
+
197
+ unless charz_session.update(charz_stack.last)
172
198
  Origen.log.error 'charz_on failed to create a valid charz session'
173
199
  fail
174
200
  end
175
201
  if block_given?
176
202
  yield
177
- charz_off
203
+ charz_off_truncate
204
+ end
205
+ end
206
+
207
+ # Removes the current sessions last instance. If the session only had one instance, this is functionally the same as charz_off
208
+ # If charz data is still on the stack afterward, the session will update to reflect the new data
209
+ # if not, the session will become inactive
210
+ def charz_off_truncate
211
+ session = charz_stack.pop || []
212
+ session.pop
213
+ unless session.empty?
214
+ charz_stack.push(session)
215
+ end
216
+
217
+ unless charz_session.update(charz_stack.last) || charz_stack.empty?
218
+ Origen.log.error 'charz_on failed to create a valid charz session'
219
+ fail
220
+ end
221
+ if charz_stack.empty?
222
+ set_charz_instance(nil)
178
223
  end
179
224
  end
180
225
 
@@ -196,8 +241,12 @@ module OrigenTesters
196
241
  end
197
242
  unless options[:id]
198
243
  if charz_active?
199
- if charz_session.on_result
200
- options[:id] = "#{parent_test_name}_charz_#{charz_session.name}".to_sym
244
+ if charz_session.on_result?
245
+ md5_id = Digest::MD5.new
246
+ md5_id << parent_test_name.to_s
247
+ md5_id << options.to_s
248
+ md5_id << charz_session.id.to_s
249
+ options[:id] = "auto_charz_id_#{md5_id}".to_sym
201
250
  end
202
251
  end
203
252
  end
@@ -206,7 +255,7 @@ module OrigenTesters
206
255
  # Called after the relevant point test has been inserted into the flow
207
256
  # Takes the options used to build the previous point test as well as insert_charz_test specific options to then
208
257
  # drill down to the point of the flow where the charz test would go, at which point control is handed back to the user's
209
- # interface to handle creating and inserting the test
258
+ # interface to handle creating and inserting the test. This will occur for each instance in the current session's instance stack
210
259
  #
211
260
  # By default, this method will handle:
212
261
  # - the placement of the test (inline aka right after the point test, end of flow, or other)
@@ -224,25 +273,27 @@ module OrigenTesters
224
273
  current_id = options.delete(:id)
225
274
  options[:last_test_id] ||= current_id
226
275
  end
227
- case charz_session.placement
228
- when :inline
229
- create_charz_group(options, &block)
230
- when :eof
231
- # collect the current session and options into a proc, stored in eof_charz_tests to be called later
232
- current_session = charz_session.clone
233
- eof_charz_tests << proc do
234
- @charz_session = current_session
276
+ charz_session.loop_instances do
277
+ case charz_instance.placement
278
+ when :inline
235
279
  create_charz_group(options, &block)
236
- end
237
- else
238
- # inline is the default behavior, and eof (end of flow) has built in support.
239
- if respond_to?(:"create_#{charz_session.placement}_charz_tests")
240
- send(:"create_#{charz_session.placement}_charz_tests", options, &block)
241
- elsif respond_to?(:"insert_#{charz_session.placement}_charz_tests")
242
- send(:"insert_#{charz_session.placement}_charz_tests", options, &block)
280
+ when :eof
281
+ # collect the current instance and options into a proc, stored in eof_charz_tests to be called later
282
+ current_instance = charz_instance.clone
283
+ eof_charz_tests << proc do
284
+ set_charz_instance(current_instance)
285
+ create_charz_group(options, &block)
286
+ end
243
287
  else
244
- Origen.log.error "No handling specified for #{charz_session.placement} placement charz tests"
245
- fail
288
+ # inline is the default behavior, and eof (end of flow) has built in support.
289
+ if respond_to?(:"create_#{charz_instance.placement}_charz_tests")
290
+ send(:"create_#{charz_instance.placement}_charz_tests", options, &block)
291
+ elsif respond_to?(:"insert_#{charz_instance.placement}_charz_tests")
292
+ send(:"insert_#{charz_instance.placement}_charz_tests", options, &block)
293
+ else
294
+ Origen.log.error "No handling specified for #{charz_instance.placement} placement charz tests"
295
+ fail
296
+ end
246
297
  end
247
298
  end
248
299
  end
@@ -265,9 +316,29 @@ module OrigenTesters
265
316
 
266
317
  private
267
318
 
268
- # called by charz_on, updates the current session, and passes the available routines in for validity checks
269
- def update_charz_session(charz_obj, options = {})
270
- charz_session.update(charz_obj, options.merge(defined_routines: charz_routines.ids))
319
+ # helper method for charz_on and charz_on_append
320
+ def get_charz_tuple(charz_id, options)
321
+ options[:type] ||= :profile
322
+ case options[:type]
323
+ when :profile
324
+ charz_obj = charz_profiles[charz_id]
325
+ when :routine
326
+ if charz_id.is_a?(Array)
327
+ charz_obj = charz_routines[charz_id.first]
328
+ options[:routines] = charz_id
329
+ else
330
+ charz_obj = charz_routines[charz_id]
331
+ options[:routines] = [charz_id]
332
+ end
333
+ else
334
+ Origen.log.error "Unknown charz object type #{options[:type]}, valid types: :profile, :routine"
335
+ fail
336
+ end
337
+ if charz_obj.nil?
338
+ Origen.log.error "No #{options[:type]} found for charz_id: #{charz_id}"
339
+ fail
340
+ end
341
+ CharzTuple.new(obj: charz_obj, options: options, defined_routines: charz_routines.ids)
271
342
  end
272
343
 
273
344
  # called by insert_charz_tests
@@ -280,7 +351,7 @@ module OrigenTesters
280
351
  if options[:skip_group]
281
352
  process_on_result(options, &block)
282
353
  else
283
- group_name = options[:group_name] || "#{options[:parent_test_name]} charz #{charz_session.name}"
354
+ group_name = options[:group_name] || "#{options[:parent_test_name]} charz #{charz_instance.name}"
284
355
  group group_name.to_sym do
285
356
  process_on_result(options, &block)
286
357
  end
@@ -298,8 +369,8 @@ module OrigenTesters
298
369
  #
299
370
  # @see set_conditional_charz_id
300
371
  def process_on_result(options, &block)
301
- if charz_session.on_result
302
- case charz_session.on_result
372
+ if charz_instance.on_result
373
+ case charz_instance.on_result
303
374
  when :on_fail, :fail, :failed
304
375
  last_test_id = options[:last_test_id] || @last_test_id
305
376
  if_failed last_test_id do
@@ -311,10 +382,10 @@ module OrigenTesters
311
382
  process_gates(options, &block)
312
383
  end
313
384
  else
314
- if respond_to?(:"process_#{charz_session.placement}_charz_tests")
315
- send(:"process_#{charz_session.on_result}_charz_tests", options, &block)
385
+ if respond_to?(:"process_#{charz_instance.placement}_charz_tests")
386
+ send(:"process_#{charz_instance.on_result}_charz_tests", options, &block)
316
387
  else
317
- Origen.log.error "No handling specified for result #{charz_session.on_result} charz tests"
388
+ Origen.log.error "No handling specified for result #{charz_instance.on_result} charz tests"
318
389
  fail
319
390
  end
320
391
  end
@@ -338,29 +409,29 @@ module OrigenTesters
338
409
  # Pass an "and_if_true" variable for enables and flags? And use that to to decide what to do? Then we don't need 4.
339
410
  # But the hash has to be structured a different way for the enable_and (routine is key, enables is value.)
340
411
  def process_gates(options, &block)
341
- if options[:skip_gates] || !(charz_session.enables || charz_session.flags)
342
- charz_session.routines.each do |routine|
412
+ if options[:skip_gates] || !(charz_instance.enables || charz_instance.flags)
413
+ charz_instance.routines.each do |routine|
343
414
  block.call(options.merge(current_routine: routine))
344
415
  end
345
416
  else
346
- if charz_session.and_enables
347
- if charz_session.flags
417
+ if charz_instance.and_enables
418
+ if charz_instance.flags
348
419
  # Wrap all tests in flag, wrap some tests in anded enables.
349
- ungated_routines = charz_session.routines - charz_session.enables.keys
420
+ ungated_routines = charz_instance.routines - charz_instance.enables.keys
350
421
  ungated_routines.each do |routine|
351
- if_flag charz_session.flags do
422
+ if_flag charz_instance.flags do
352
423
  block.call(options.merge(current_routine: routine))
353
424
  end
354
425
  end
355
- gated_routines = charz_session.routines - ungated_routines
426
+ gated_routines = charz_instance.routines - ungated_routines
356
427
  # Build the proc which contains the nested if statements for each routine so they are anded.
357
428
  gated_routines.each do |routine|
358
429
  my_proc = -> do
359
- if_flag charz_session.flags do
430
+ if_flag charz_instance.flags do
360
431
  block.call(options.merge(current_routine: routine))
361
432
  end
362
433
  end
363
- charz_session.enables[routine].inject(my_proc) do |my_block, enable|
434
+ charz_instance.enables[routine].inject(my_proc) do |my_block, enable|
364
435
  lambda do
365
436
  if_enable :"#{enable}" do
366
437
  my_block.call
@@ -369,15 +440,15 @@ module OrigenTesters
369
440
  end.call
370
441
  end
371
442
  else
372
- ungated_routines = charz_session.routines - charz_session.enables.keys
443
+ ungated_routines = charz_instance.routines - charz_instance.enables.keys
373
444
  ungated_routines.each do |routine|
374
445
  block.call(options.merge(current_routine: routine))
375
446
  end
376
447
  # Build the proc which contains the nested if statements for each routine so they are anded.
377
- gated_routines = charz_session.routines - ungated_routines
448
+ gated_routines = charz_instance.routines - ungated_routines
378
449
  gated_routines.each do |routine|
379
450
  my_proc = -> { block.call(options.merge(current_routine: routine)) }
380
- charz_session.enables[routine].inject(my_proc) do |my_block, enable|
451
+ charz_instance.enables[routine].inject(my_proc) do |my_block, enable|
381
452
  lambda do
382
453
  if_enable :"#{enable}" do
383
454
  my_block.call
@@ -386,24 +457,24 @@ module OrigenTesters
386
457
  end.call
387
458
  end
388
459
  end
389
- elsif charz_session.and_flags
390
- if charz_session.enables
460
+ elsif charz_instance.and_flags
461
+ if charz_instance.enables
391
462
  # Wrap all tests in enable, some tests in anded flags.
392
- ungated_routines = charz_session.routines - charz_session.flags.keys
463
+ ungated_routines = charz_instance.routines - charz_instance.flags.keys
393
464
  ungated_routines.each do |routine|
394
- if_enable charz_session.enables do
465
+ if_enable charz_instance.enables do
395
466
  block.call(options.merge(current_routine: routine))
396
467
  end
397
468
  end
398
469
  # Build the proc which contains the nested if statemements for each routine so they are anded.
399
- gated_routines = charz_session.routines - ungated_routines
470
+ gated_routines = charz_instance.routines - ungated_routines
400
471
  gated_routines.each do |routine|
401
472
  my_proc = -> do
402
- if_enable charz_session.enables do
473
+ if_enable charz_instance.enables do
403
474
  block.call(options.merge(current_routine: routine))
404
475
  end
405
476
  end
406
- charz_session.flags[routine].inject(my_proc) do |my_block, flag|
477
+ charz_instance.flags[routine].inject(my_proc) do |my_block, flag|
407
478
  lambda do
408
479
  if_flag :"#{flag}" do
409
480
  my_block.call
@@ -412,15 +483,15 @@ module OrigenTesters
412
483
  end.call
413
484
  end
414
485
  else
415
- ungated_routines = charz_session.routines - charz_session.flags.keys
486
+ ungated_routines = charz_instance.routines - charz_instance.flags.keys
416
487
  ungated_routines.each do |routine|
417
488
  block.call(options.merge(current_routine: routine))
418
489
  end
419
490
  # Build the proc which contains the nested if statemements for each routine so they are anded.
420
- gated_routines = charz_session.routines - ungated_routines
491
+ gated_routines = charz_instance.routines - ungated_routines
421
492
  gated_routines.each do |routine|
422
493
  my_proc = -> { block.call(options.merge(current_routine: routine)) }
423
- charz_session.flags[routine].inject(my_proc) do |my_block, flag|
494
+ charz_instance.flags[routine].inject(my_proc) do |my_block, flag|
424
495
  lambda do
425
496
  if_flag :"#{flag}" do
426
497
  my_block.call
@@ -429,28 +500,28 @@ module OrigenTesters
429
500
  end.call
430
501
  end
431
502
  end
432
- elsif charz_session.enables && charz_session.flags
433
- if charz_session.enables.is_a?(Hash) && !charz_session.flags.is_a?(Hash)
503
+ elsif charz_instance.enables && charz_instance.flags
504
+ if charz_instance.enables.is_a?(Hash) && !charz_instance.flags.is_a?(Hash)
434
505
  # wrap all tests in flags, wrap specific tests in enables
435
- if_flag charz_session.flags do
436
- insert_hash_gates(options, charz_session.enables, :if_enable, &block)
506
+ if_flag charz_instance.flags do
507
+ insert_hash_gates(options, charz_instance.enables, :if_enable, &block)
437
508
  end
438
- elsif !charz_session.enables.is_a?(Hash) && charz_session.flags.is_a?(Hash)
509
+ elsif !charz_instance.enables.is_a?(Hash) && charz_instance.flags.is_a?(Hash)
439
510
  # wrap all tests in enables, wrap specific tests in flags
440
- if_enable charz_session.enables do
441
- insert_hash_gates(options, charz_session.flags, :if_flag, &block)
511
+ if_enable charz_instance.enables do
512
+ insert_hash_gates(options, charz_instance.flags, :if_flag, &block)
442
513
  end
443
- elsif charz_session.enables.is_a?(Hash) && charz_session.flags.is_a?(Hash)
514
+ elsif charz_instance.enables.is_a?(Hash) && charz_instance.flags.is_a?(Hash)
444
515
  # first insert the tests that are not tied to an enable or flag gate
445
- ungated_routines = charz_session.routines - (charz_session.enables.values.flatten | charz_session.flags.values.flatten)
516
+ ungated_routines = charz_instance.routines - (charz_instance.enables.values.flatten | charz_instance.flags.values.flatten)
446
517
  ungated_routines.each do |routine|
447
518
  block.call(options.merge(current_routine: routine))
448
519
  end
449
520
  # wrap tests in an enable gate, flag gate, or both
450
- gated_routines = charz_session.routines - ungated_routines
521
+ gated_routines = charz_instance.routines - ungated_routines
451
522
  gated_routines.each do |routine|
452
- enable = charz_session.enables.find { |gates, routines| routines.include?(routine) }&.first
453
- flag = charz_session.flags.find { |gates, routines| routines.include?(routine) }&.first
523
+ enable = charz_instance.enables.find { |gates, routines| routines.include?(routine) }&.first
524
+ flag = charz_instance.flags.find { |gates, routines| routines.include?(routine) }&.first
454
525
  if enable && flag
455
526
  if_enable enable do
456
527
  if_flag flag do
@@ -472,9 +543,9 @@ module OrigenTesters
472
543
  end
473
544
  else
474
545
  # both enable and flag is set, and both apply to all routines in session
475
- if_enable charz_session.enables do
476
- if_flag charz_session.flags do
477
- charz_session.routines.each do |routine|
546
+ if_enable charz_instance.enables do
547
+ if_flag charz_instance.flags do
548
+ charz_instance.routines.each do |routine|
478
549
  block.call(options.merge(current_routine: routine))
479
550
  end
480
551
  end
@@ -482,11 +553,11 @@ module OrigenTesters
482
553
  end
483
554
  else
484
555
  # only enables or flags is set, not both
485
- if charz_session.enables
486
- gates = charz_session.enables
556
+ if charz_instance.enables
557
+ gates = charz_instance.enables
487
558
  gate_method = :if_enable
488
- elsif charz_session.flags
489
- gates = charz_session.flags
559
+ elsif charz_instance.flags
560
+ gates = charz_instance.flags
490
561
  gate_method = :if_flag
491
562
  end
492
563
  if gates.is_a?(Hash)
@@ -495,7 +566,7 @@ module OrigenTesters
495
566
  else
496
567
  # wrap all tests in the indicated gates
497
568
  send(gate_method, gates) do
498
- charz_session.routines.each do |routine|
569
+ charz_instance.routines.each do |routine|
499
570
  block.call(options.merge(current_routine: routine))
500
571
  end
501
572
  end
@@ -507,7 +578,7 @@ module OrigenTesters
507
578
  # helper method for the process gates method above
508
579
  # handles wrapping routines in specific gates, and passing ungated routines back to the user
509
580
  def insert_hash_gates(options, gate_hash, gate_method, &block)
510
- ungated_routines = charz_session.routines - gate_hash.values.flatten
581
+ ungated_routines = charz_instance.routines - gate_hash.values.flatten
511
582
  ungated_routines.each do |routine|
512
583
  block.call(options.merge(current_routine: routine))
513
584
  end
data/program/charz.rb CHANGED
@@ -54,11 +54,16 @@ Flow.create interface: 'OrigenTesters::Test::Interface' do
54
54
 
55
55
  charz_on :complex_anded_flags, {flags: { routine1: [:my_flag1, :my_flag2]}}
56
56
  func_with_charz :func_complex_anded_flags
57
+ charz_on_append :routine2, { type: :routine }
58
+ func_with_charz :func_complex_anded_flags_add_simple_rt2
59
+ charz_off_truncate
57
60
  charz_off
58
61
 
59
62
  charz_on :complex_anded_enables, {enables: { routine1: [:my_enable1, :my_enable2]}}
60
63
  func_with_charz :func_complex_anded_enables
61
64
  charz_off
62
65
 
66
+
67
+
63
68
  end
64
69
  end
@@ -79,6 +79,63 @@ add_charz_profile :anded_enables do |profile|
79
79
  end
80
80
  ~~~
81
81
 
82
+ ### Flow API
83
+
84
+ Once your profiles and routines are initialized, the primary way of using the Charz API are through charz on/off calls as well as their append/truncate counterparts:
85
+
86
+ #### charz_on / charz_off
87
+
88
+ Pushes/pops a charz object (either a profile or a routine) onto the stack, along with any optional updates to modify the current session.
89
+ Once pushed, the charz_session will attempt to update itself with the new data, failing if the resulting session is invalid. The updates will be stored as an "instance" which
90
+ is essentially a dummy Profile, and placed inside the sessions instance stack, effectively making the charz_stack a 2D array.
91
+
92
+ Once an instance is pushed onto the stack, the session becomes active and valid, allowing your apps hooks to query that state to know if a charz test needs to be inserted.
93
+
94
+ Basic Usage:
95
+
96
+ ~~~ruby
97
+ # pushes the profile :my_profile onto the charz stack
98
+ charz_on :my_profile
99
+ # after you've updated your app to insert charz tests,
100
+ # this line will make two tests: point test and charz variant
101
+ func :my_test
102
+ # pops :my_profile off the charz stack
103
+ charz_off
104
+
105
+ # alternate block form, functionally identical
106
+ charz_on :my_profile do
107
+ func :my_test
108
+ end
109
+ ~~~
110
+
111
+ #### charz_on_append / charz_off_truncate
112
+
113
+ Very similar to the previous charz_on/off, the append/truncate instead operates in the 2nd dimension of the 2D array that is the charz stack.
114
+ Pushes/pops a charz object (either a profile or a routine) onto the current sessions instance stack, along with any optional updates to modify that instance.
115
+ This will result in subsequent charzable point tests in being processed against each of the current instances. In other words, this new push will not take
116
+ priority over the current stack head, but instead append to it.
117
+
118
+ Basic Usage:
119
+
120
+ ~~~ruby
121
+ # pushes the profile :my_profile onto the charz stack
122
+ charz_on :my_profile
123
+ # after you've updated your app to insert charz tests, this line will make two tests:
124
+ # point test and charz variant
125
+ func :my_test
126
+ # instead of pushing onto the charz stack itself,
127
+ # this will push :my_other_profile onto the instance stack of the current session,
128
+ # which is the at the head of the charz stack
129
+ charz_on_append :my_other_profile
130
+ # this line now makes 3 tests: the point test, a charz variant
131
+ # per :my_profile, and another per :my_other_profile
132
+ func :my_other_test
133
+ # pops the session of the stack, meaning both :my_profile and :my_other_profile
134
+ # are gone since they were in the same session alternately run charz_off_truncate
135
+ # to only remove :my_other_profile
136
+ charz_off
137
+ ~~~
138
+
82
139
  ### Charz Session
83
140
 
84
141
  The charz session (stored in your interfaces `@charz_session` attribute) monitors the current state of characterization at a given point in flow generation.
@@ -210,7 +267,10 @@ Where insert_current_charz_test is a method defined in the company charz flow me
210
267
 
211
268
  ### Flow Usage Examples
212
269
 
213
- Now that the interface has charz routines and profiles, lets look at how to use the API within the flow itself:
270
+ Now that the interface has charz routines and profiles, lets look at how to use the API within the flow itself. Basic usage is to make charz_on/off calls, which will set the
271
+ session to contain the called profile as the current instance to generate against.
272
+
273
+ Additionally if you would like to add additional profiles to the current session, you can use the `charz_on_append` (and its counter part: `charz_off_truncate`) to do so.
214
274
 
215
275
  ~~~ruby
216
276
  Flow.create(interface: 'MyApp:Interface') do
@@ -235,6 +295,19 @@ Flow.create(interface: 'MyApp:Interface') do
235
295
  func :my_test4
236
296
  end
237
297
 
298
+ # create profileA charz test variants of my_test5, as well as profileA and profileB charz variants of my_test6
299
+ # this would produce the following tests in order:
300
+ # my_test5
301
+ # my_test5_routineA
302
+ # my_test6
303
+ # my_test6_routineA
304
+ # my_test6_routineB
305
+ charz_on :profileA do
306
+ func :my_test5
307
+ charz_on_append :profileB
308
+ func :my_test6
309
+ end
310
+
238
311
  end
239
312
  ~~~
240
313
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_testers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.51.2
4
+ version: 0.51.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-20 00:00:00.000000000 Z
11
+ date: 2023-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen