origen_testers 0.51.2 → 0.51.3

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