test_ids 0.8.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/commands.rb +2 -0
- data/config/version.rb +3 -3
- data/lib/test_ids.rb +87 -17
- data/lib/test_ids/allocator.rb +186 -277
- data/lib/test_ids/configuration.rb +32 -14
- data/lib/test_ids/origen_testers/flow.rb +9 -6
- data/lib/test_ids_dev/interface.rb +9 -3
- data/program/prb1.rb +12 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ed0f63265007afb642078d96f8acd7362495c85
|
4
|
+
data.tar.gz: 748add426abaf38bdc4c8e3577736d28d97d09b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e5823734dc64272dd90f73196100e21434b3c9a5d05519929d90a2262712d99108a9cbf9efc378813307e1a8450f50ef4efdfb237ca07486de7d12b30738eb0
|
7
|
+
data.tar.gz: 73ffa02f9b035e7f94ba1ccd0eb91fef83cc115c8489884bac20221ff538137d84926d40d5c331eb01fb8684b399b3641468fa7f03147eab61c59939bbdf3344
|
data/config/commands.rb
CHANGED
@@ -33,6 +33,8 @@ when "examples", "test"
|
|
33
33
|
# Program generator integration test
|
34
34
|
ARGV = %w(program/prb1.rb -t default -e default -r approved)
|
35
35
|
load "#{Origen.top}/lib/origen/commands/program.rb"
|
36
|
+
ARGV = %W(program/prb1.rb -t dut2 -o #{Origen.root}/output/dut2 -e default -r approved/dut2)
|
37
|
+
load "#{Origen.top}/lib/origen/commands/program.rb"
|
36
38
|
|
37
39
|
if Origen.app.stats.changed_files == 0 &&
|
38
40
|
Origen.app.stats.new_files == 0 &&
|
data/config/version.rb
CHANGED
data/lib/test_ids.rb
CHANGED
@@ -24,12 +24,57 @@ module TestIds
|
|
24
24
|
# returned will be the same as would be injected into flow.test.
|
25
25
|
def allocate(instance, options = {})
|
26
26
|
opts = options.dup
|
27
|
+
inject_flow_id(opts)
|
27
28
|
current_configuration.allocator.allocate(instance, opts)
|
28
29
|
{ bin: opts[:bin], bin_size: opts[:bin_size], softbin: opts[:softbin], softbin_size: opts[:softbin_size],
|
29
30
|
number: opts[:number], number_size: opts[:number_size]
|
30
31
|
}
|
31
32
|
end
|
32
33
|
|
34
|
+
# Similar to allocate, but allocates a test number only, i.e. no bin or softbin
|
35
|
+
def allocate_number(instance, options = {})
|
36
|
+
opts = options.dup
|
37
|
+
opts[:bin] = :none
|
38
|
+
opts[:softbin] = :none
|
39
|
+
inject_flow_id(opts)
|
40
|
+
current_configuration.allocator.allocate(instance, opts)
|
41
|
+
{
|
42
|
+
number: opts[:number], number_size: opts[:number_size]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Similar to allocate, but allocates a softbin number only, i.e. no bin or test number
|
47
|
+
def allocate_softbin(instance, options = {})
|
48
|
+
opts = options.dup
|
49
|
+
opts[:bin] = :none
|
50
|
+
opts[:number] = :none
|
51
|
+
inject_flow_id(opts)
|
52
|
+
current_configuration.allocator.allocate(instance, opts)
|
53
|
+
{
|
54
|
+
softbin: opts[:softbin], softbin_size: opts[:softbin_size]
|
55
|
+
}
|
56
|
+
end
|
57
|
+
alias_method :allocate_soft_bin, :allocate_softbin
|
58
|
+
|
59
|
+
# Similar to allocate, but allocates a bin number only, i.e. no softbin or test number
|
60
|
+
def allocate_bin(instance, options = {})
|
61
|
+
opts = options.dup
|
62
|
+
opts[:softbin] = :none
|
63
|
+
opts[:number] = :none
|
64
|
+
inject_flow_id(opts)
|
65
|
+
current_configuration.allocator.allocate(instance, opts)
|
66
|
+
{
|
67
|
+
softbin: opts[:bin], softbin_size: opts[:bin_size]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def inject_flow_id(options)
|
73
|
+
if Origen.interface_loaded?
|
74
|
+
options[:test_ids_flow_id] = Origen.interface.flow.id
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
33
78
|
# Load an existing allocator, which will be loaded with a configuration based on what has
|
34
79
|
# been serialized into the database if present, otherwise it will have an empty configuration.
|
35
80
|
# Returns nil if the given database can not be found.
|
@@ -47,9 +92,11 @@ module TestIds
|
|
47
92
|
configuration(@configuration_id)
|
48
93
|
end
|
49
94
|
|
50
|
-
def configuration(id)
|
95
|
+
def configuration(id, fail_on_missing = true)
|
51
96
|
return @configuration[id] if @configuration && @configuration[id]
|
52
|
-
|
97
|
+
if fail_on_missing
|
98
|
+
fail('You have to create the configuration first before you can access it')
|
99
|
+
end
|
53
100
|
end
|
54
101
|
alias_method :config, :configuration
|
55
102
|
|
@@ -73,26 +120,46 @@ module TestIds
|
|
73
120
|
initialize_git
|
74
121
|
end
|
75
122
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
123
|
+
# Switch the current configuration to the given ID
|
124
|
+
def config=(id)
|
125
|
+
unless @configuration[id]
|
126
|
+
fail "The TestIds configuration '#{id}' has not been defined yet!"
|
127
|
+
end
|
128
|
+
@configuration_id = id
|
129
|
+
end
|
130
|
+
|
131
|
+
def bin_config=(id)
|
132
|
+
@bin_config = id
|
133
|
+
end
|
134
|
+
|
135
|
+
def bin_config
|
136
|
+
@bin_config ? configuration(@bin_config, false) : current_configuration
|
137
|
+
end
|
81
138
|
|
82
|
-
|
139
|
+
def softbin_config=(id)
|
140
|
+
@softbin_config = id
|
141
|
+
end
|
83
142
|
|
84
|
-
|
143
|
+
def softbin_config
|
144
|
+
@softbin_config ? configuration(@softbin_config, false) : current_configuration
|
145
|
+
end
|
85
146
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# new.allocator.instance_variable_set('@config', new)
|
90
|
-
# @configuration[@configuration_id] = new
|
147
|
+
def number_config=(id)
|
148
|
+
@number_config = id
|
149
|
+
end
|
91
150
|
|
92
|
-
|
151
|
+
def number_config
|
152
|
+
@number_config ? configuration(@number_config, false) : current_configuration
|
153
|
+
end
|
93
154
|
|
94
|
-
#
|
95
|
-
#
|
155
|
+
# Temporarily switches the current configuration to the given ID for the
|
156
|
+
# duration of the given block, then switches it back to what it was
|
157
|
+
def with_config(id)
|
158
|
+
orig = @configuration_id
|
159
|
+
@configuration_id = id
|
160
|
+
yield
|
161
|
+
@configuration_id = orig
|
162
|
+
end
|
96
163
|
|
97
164
|
def configured?
|
98
165
|
!!@configuration_id
|
@@ -205,6 +272,9 @@ module TestIds
|
|
205
272
|
|
206
273
|
def clear_configuration_id
|
207
274
|
@configuration_id = nil
|
275
|
+
@bin_config = nil
|
276
|
+
@softbin_config = nil
|
277
|
+
@number_config = nil
|
208
278
|
end
|
209
279
|
|
210
280
|
def testing=(val)
|
data/lib/test_ids/allocator.rb
CHANGED
@@ -8,12 +8,20 @@ module TestIds
|
|
8
8
|
class Allocator
|
9
9
|
STORE_FORMAT_REVISION = 2
|
10
10
|
|
11
|
-
attr_reader :config
|
12
|
-
|
13
11
|
def initialize(configuration)
|
14
12
|
@config = configuration
|
15
13
|
end
|
16
14
|
|
15
|
+
def config(type = nil)
|
16
|
+
if type
|
17
|
+
type = type.to_s
|
18
|
+
type.chop! if type[-1] == 's'
|
19
|
+
TestIds.send("#{type}_config") || @config
|
20
|
+
else
|
21
|
+
@config
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
17
25
|
# Allocates a softbin number from the range specified in the test flow
|
18
26
|
# It also keeps a track of the last softbin assigned out from a particular range
|
19
27
|
# and uses that to increment the pointers accordingly.
|
@@ -73,137 +81,96 @@ module TestIds
|
|
73
81
|
assigned_value
|
74
82
|
end
|
75
83
|
|
76
|
-
#
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# should be reserved
|
87
|
-
if (options[:bin].is_a?(Symbol) || options[:bin].is_a?(String)) && options[:bin] != :none
|
88
|
-
bin_id = options[:bin].to_s
|
84
|
+
# Returns an array containing :bin, :softbin, :number in the order that they should be calculated in order to fulfil
|
85
|
+
# the requirements of the current configuration and the given options.
|
86
|
+
# If an item is not required (e.g. if set to :none in the options), then it will not be present in the array.
|
87
|
+
def allocation_order(options)
|
88
|
+
items = []
|
89
|
+
items_required = 0
|
90
|
+
if allocation_required?(:bin, options) ||
|
91
|
+
(allocation_required?(:softbin, options) && config(:softbin).softbins.needs?(:bin)) ||
|
92
|
+
(allocation_required?(:number, options) && config(:number).numbers.needs?(:bin))
|
93
|
+
items_required += 1
|
89
94
|
else
|
90
|
-
|
95
|
+
bin_done = true
|
91
96
|
end
|
92
|
-
if (
|
93
|
-
|
97
|
+
if allocation_required?(:softbin, options) ||
|
98
|
+
(allocation_required?(:bin, options) && config(:bin).bins.needs?(:softbin)) ||
|
99
|
+
(allocation_required?(:number, options) && config(:number).numbers.needs?(:softbin))
|
100
|
+
items_required += 1
|
94
101
|
else
|
95
|
-
|
102
|
+
softbin_done = true
|
96
103
|
end
|
97
|
-
if (
|
98
|
-
|
104
|
+
if allocation_required?(:number, options) ||
|
105
|
+
(allocation_required?(:bin, options) && config(:bin).bins.needs?(:number)) ||
|
106
|
+
(allocation_required?(:softbin, options) && config(:softbin).softbins.needs?(:number))
|
107
|
+
items_required += 1
|
99
108
|
else
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
bin['number'] = options[:bin]
|
115
|
-
bin['size'] = bin_size
|
116
|
-
store['manually_assigned']['bins'][options[:bin].to_s] = true
|
117
|
-
# Regenerate the bin if the original allocation has since been applied
|
118
|
-
# manually elsewhere
|
119
|
-
elsif store['manually_assigned']['bins'][bin['number'].to_s]
|
120
|
-
bin['number'] = nil
|
121
|
-
bin['size'] = nil
|
122
|
-
# Also regenerate these as they could be a function of the bin
|
123
|
-
if config.softbins.function?
|
124
|
-
softbin['number'] = nil
|
125
|
-
softbin['size'] = nil
|
126
|
-
end
|
127
|
-
if config.numbers.function?
|
128
|
-
number['number'] = nil
|
129
|
-
number['size'] = nil
|
130
|
-
end
|
131
|
-
end
|
132
|
-
if options[:softbin] && options[:softbin].is_a?(Numeric)
|
133
|
-
softbin['number'] = options[:softbin]
|
134
|
-
softbin['size'] = softbin_size
|
135
|
-
store['manually_assigned']['softbins'][options[:softbin].to_s] = true
|
136
|
-
elsif store['manually_assigned']['softbins'][softbin['number'].to_s]
|
137
|
-
softbin['number'] = nil
|
138
|
-
softbin['size'] = nil
|
139
|
-
# Also regenerate the number as it could be a function of the softbin
|
140
|
-
if config.numbers.function?
|
141
|
-
number['number'] = nil
|
142
|
-
number['size'] = nil
|
143
|
-
end
|
144
|
-
end
|
145
|
-
if options[:number] && options[:number].is_a?(Numeric)
|
146
|
-
number['number'] = options[:number]
|
147
|
-
number['size'] = number_size
|
148
|
-
store['manually_assigned']['numbers'][options[:number].to_s] = true
|
149
|
-
elsif store['manually_assigned']['numbers'][number['number'].to_s]
|
150
|
-
number['number'] = nil
|
151
|
-
number['size'] = nil
|
152
|
-
# Also regenerate the softbin as it could be a function of the number
|
153
|
-
if config.softbins.function?
|
154
|
-
softbin['number'] = nil
|
155
|
-
softbin['size'] = nil
|
109
|
+
number_done = true
|
110
|
+
end
|
111
|
+
items_required.times do |i|
|
112
|
+
if !bin_done && (!config(:bin).bins.needs?(:softbin) || softbin_done) && (!config(:bin).bins.needs?(:number) || number_done)
|
113
|
+
items << :bin
|
114
|
+
bin_done = true
|
115
|
+
elsif !softbin_done && (!config(:softbin).softbins.needs?(:bin) || bin_done) && (!config(:softbin).softbins.needs?(:number) || number_done)
|
116
|
+
items << :softbin
|
117
|
+
softbin_done = true
|
118
|
+
elsif !number_done && (!config(:number).numbers.needs?(:bin) || bin_done) && (!config(:number).numbers.needs?(:softbin) || softbin_done)
|
119
|
+
items << :number
|
120
|
+
number_done = true
|
121
|
+
else
|
122
|
+
fail "Couldn't work out whether to generate next on iteration #{i} of #{items_required}, already picked: #{items}"
|
156
123
|
end
|
157
124
|
end
|
125
|
+
items
|
126
|
+
end
|
158
127
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
if (config.softbins.algorithm && config.softbins.algorithm.to_s =~ /n/) ||
|
166
|
-
(config.softbins.callback && !config.numbers.function?)
|
167
|
-
number['number'] ||= allocate_number(options.merge(bin: bin['number'], size: number_size))
|
168
|
-
number['size'] ||= number_size
|
169
|
-
softbin['number'] ||= allocate_softbin(options.merge(bin: bin['number'], number: number['number'], size: softbin_size))
|
170
|
-
softbin['size'] ||= softbin_size
|
171
|
-
else
|
172
|
-
softbin['number'] ||= allocate_softbin(options.merge(bin: bin['number'], size: softbin_size))
|
173
|
-
softbin['size'] ||= softbin_size
|
174
|
-
number['number'] ||= allocate_number(options.merge(bin: bin['number'], softbin: softbin['number'], size: number_size))
|
175
|
-
number['size'] ||= number_size
|
176
|
-
end
|
128
|
+
# Main method to inject generated bin and test numbers, the given
|
129
|
+
# options instance is modified accordingly
|
130
|
+
def allocate(instance, options)
|
131
|
+
orig_options = options.dup
|
132
|
+
clean(options)
|
133
|
+
name = extract_test_name(instance, options)
|
177
134
|
|
178
|
-
|
179
|
-
time = Time.now.to_f
|
180
|
-
bin_size.times do |i|
|
181
|
-
store['references']['bins'][(bin['number'] + i).to_s] = time if bin['number'] && options[:bin] != :none
|
182
|
-
end
|
183
|
-
softbin_size.times do |i|
|
184
|
-
store['references']['softbins'][(softbin['number'] + i).to_s] = time if softbin['number'] && options[:softbin] != :none
|
185
|
-
end
|
186
|
-
number_size.times do |i|
|
187
|
-
store['references']['numbers'][(number['number'] + i).to_s] = time if number['number'] && options[:number] != :none
|
188
|
-
end
|
135
|
+
nones = []
|
189
136
|
|
190
|
-
#
|
191
|
-
|
192
|
-
options[
|
193
|
-
|
137
|
+
# Record any :nones that are present for later
|
138
|
+
[:bin, :softbin, :number].each do |type|
|
139
|
+
nones << type if options[type] == :none
|
140
|
+
config(type).allocator.instance_variable_set('@needs_regenerated', {})
|
194
141
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
142
|
+
|
143
|
+
allocation_order(options).each do |type|
|
144
|
+
config(type).allocator.send(:_allocate, type, name, options)
|
198
145
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
146
|
+
|
147
|
+
# Turn any :nones into nils in the returned options
|
148
|
+
nones.each do |type|
|
149
|
+
options[type] = nil
|
150
|
+
options["#{type}_size"] = nil
|
202
151
|
end
|
203
152
|
|
204
153
|
options
|
205
154
|
end
|
206
155
|
|
156
|
+
# Merge the given other store into the current one, it is assumed that both are formatted
|
157
|
+
# from the same (latest) revision
|
158
|
+
def merge_store(other_store)
|
159
|
+
store['pointers'] = store['pointers'].merge(other_store['pointers'])
|
160
|
+
@last_bin = store['pointers']['bins']
|
161
|
+
@last_softbin = store['pointers']['softbins']
|
162
|
+
@last_number = store['pointers']['numbers']
|
163
|
+
store['assigned']['bins'] = store['assigned']['bins'].merge(other_store['assigned']['bins'])
|
164
|
+
store['assigned']['softbins'] = store['assigned']['softbins'].merge(other_store['assigned']['softbins'])
|
165
|
+
store['assigned']['numbers'] = store['assigned']['numbers'].merge(other_store['assigned']['numbers'])
|
166
|
+
store['manually_assigned']['bins'] = store['manually_assigned']['bins'].merge(other_store['manually_assigned']['bins'])
|
167
|
+
store['manually_assigned']['softbins'] = store['manually_assigned']['softbins'].merge(other_store['manually_assigned']['softbins'])
|
168
|
+
store['manually_assigned']['numbers'] = store['manually_assigned']['numbers'].merge(other_store['manually_assigned']['numbers'])
|
169
|
+
store['references']['bins'] = store['references']['bins'].merge(other_store['references']['bins'])
|
170
|
+
store['references']['softbins'] = store['references']['softbins'].merge(other_store['references']['softbins'])
|
171
|
+
store['references']['numbers'] = store['references']['numbers'].merge(other_store['references']['numbers'])
|
172
|
+
end
|
173
|
+
|
207
174
|
def store
|
208
175
|
@store ||= begin
|
209
176
|
if file && File.exist?(file)
|
@@ -267,7 +234,7 @@ module TestIds
|
|
267
234
|
{ 'bins' => 'bins', 'softbins' => 'softbins', 'numbers' => 'test_numbers' }.each do |type, name|
|
268
235
|
if !config.send(type).function? && store['pointers'][type] == 'done'
|
269
236
|
Origen.log.info "Checking for missing #{name}..."
|
270
|
-
recovered = add_missing_references(config.send
|
237
|
+
recovered = add_missing_references(config.send, store['references'][type])
|
271
238
|
if recovered == 0
|
272
239
|
Origen.log.info " All #{name} are already available."
|
273
240
|
else
|
@@ -396,6 +363,72 @@ module TestIds
|
|
396
363
|
|
397
364
|
private
|
398
365
|
|
366
|
+
def _allocate(type, name, options)
|
367
|
+
type_plural = "#{type}s"
|
368
|
+
conf = config.send(type_plural)
|
369
|
+
|
370
|
+
# First work out the test ID to be used for each of the numbers, and how many numbers
|
371
|
+
# should be reserved
|
372
|
+
if (options[type].is_a?(Symbol) || options[type].is_a?(String)) && options[type] != :none
|
373
|
+
id = options[type].to_s
|
374
|
+
else
|
375
|
+
id = name
|
376
|
+
end
|
377
|
+
id = "#{id}_#{options[:index]}" if options[:index]
|
378
|
+
id = "#{id}_#{options[:test_ids_flow_id]}" if config.unique_by_flow?
|
379
|
+
|
380
|
+
val = store['assigned'][type_plural][id] ||= {}
|
381
|
+
|
382
|
+
if options[type].is_a?(Integer)
|
383
|
+
unless val['number'] == options[type]
|
384
|
+
store['manually_assigned']["#{type}s"][options[type].to_s] = true
|
385
|
+
val['number'] = options[type]
|
386
|
+
end
|
387
|
+
else
|
388
|
+
# Will be set if an upstream dependent type has been marked for regeneration by the code below
|
389
|
+
if @needs_regenerated[type]
|
390
|
+
val['number'] = nil
|
391
|
+
val['size'] = nil
|
392
|
+
# Regenerate the number if the original allocation has since been applied manually elsewhere
|
393
|
+
elsif store['manually_assigned'][type_plural][val['number'].to_s]
|
394
|
+
val['number'] = nil
|
395
|
+
val['size'] = nil
|
396
|
+
# Also regenerate these as they could be a function of the number we just invalidated
|
397
|
+
([:bin, :softbin, :number] - [type]).each do |t|
|
398
|
+
if config.send("#{t}s").needs?(type)
|
399
|
+
@needs_regenerated[t] = true
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
if size = options["#{type}_size".to_sym]
|
406
|
+
val['size'] = size
|
407
|
+
end
|
408
|
+
|
409
|
+
# Generate the missing ones
|
410
|
+
val['size'] ||= conf.size
|
411
|
+
val['number'] ||= allocate_item(type, options.merge(size: val['size']))
|
412
|
+
|
413
|
+
# Record that there has been a reference to the final numbers
|
414
|
+
time = Time.now.to_f
|
415
|
+
val['size'].times do |i|
|
416
|
+
store['references'][type_plural][(val['number'] + i).to_s] = time if val['number'] && options[type] != :none
|
417
|
+
end
|
418
|
+
|
419
|
+
# Update the supplied options hash that will be forwarded to the program generator
|
420
|
+
options[type] = val['number']
|
421
|
+
options["#{type}_size".to_sym] = val['size']
|
422
|
+
end
|
423
|
+
|
424
|
+
def allocation_required?(type, options)
|
425
|
+
if options[type] == :none
|
426
|
+
false
|
427
|
+
else
|
428
|
+
!config(type).send("#{type}s").empty?
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
399
432
|
def remove_invalid_references(config_item, references, manually_assigned)
|
400
433
|
removed = 0
|
401
434
|
references.each do |num, time|
|
@@ -435,161 +468,34 @@ module TestIds
|
|
435
468
|
recovered
|
436
469
|
end
|
437
470
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
return nil if config.bins.empty? && !config.bins.callback
|
445
|
-
if store['pointers']['bins'] == 'done'
|
446
|
-
reclaim_bin(options)
|
447
|
-
elsif callback = config.bins.callback
|
448
|
-
callback.call(options)
|
449
|
-
else
|
450
|
-
b = config.bins.include.next(after: @last_bin, size: options[:size])
|
451
|
-
@last_bin = nil
|
452
|
-
while b && (store['manually_assigned']['bins'][b.to_s] || config.bins.exclude.include?(b))
|
453
|
-
b = config.bins.include.next(size: options[:size])
|
454
|
-
end
|
455
|
-
# When no bin is returned it means we have used them all, all future generation
|
456
|
-
# now switches to reclaim mode
|
457
|
-
if b
|
458
|
-
store['pointers']['bins'] = b
|
459
|
-
else
|
460
|
-
store['pointers']['bins'] = 'done'
|
461
|
-
reclaim_bin(options)
|
462
|
-
end
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
def reclaim_bin(options)
|
467
|
-
store['references']['bins'] = store['references']['bins'].sort_by { |k, v| v }.to_h
|
468
|
-
if options[:size] == 1
|
469
|
-
store['references']['bins'].first[0].to_i
|
470
|
-
else
|
471
|
-
reclaim(store['references']['bins'], options)
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
def allocate_softbin(options)
|
476
|
-
bin = options[:bin]
|
477
|
-
num = options[:number]
|
478
|
-
return nil if config.softbins.empty?
|
479
|
-
if config.softbins.algorithm
|
480
|
-
algo = config.softbins.algorithm.to_s.downcase
|
481
|
-
if algo.to_s =~ /^[b\dxn]+$/
|
471
|
+
def allocate_item(type, options)
|
472
|
+
type_plural = "#{type}s"
|
473
|
+
conf = config.send(type_plural)
|
474
|
+
if conf.algorithm
|
475
|
+
algo = conf.algorithm.to_s.downcase
|
476
|
+
if algo.to_s =~ /^[bsn\dx]+$/
|
482
477
|
number = algo.to_s
|
483
|
-
bin
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
number = number.sub(/b+/, bin.rjust(max_bin_size, '0'))
|
490
|
-
end
|
491
|
-
if number =~ /(n+)/
|
492
|
-
num = num.to_s
|
493
|
-
max_num_size = Regexp.last_match(1).size
|
494
|
-
if num.size > max_num_size
|
495
|
-
fail "Test number (#{num}) overflows the softbin number algorithm (#{algo})"
|
496
|
-
end
|
497
|
-
number = number.sub(/n+/, num.rjust(max_num_size, '0'))
|
498
|
-
end
|
499
|
-
if number =~ /(x+)/
|
500
|
-
max_counter_size = Regexp.last_match(1).size
|
501
|
-
refs = store['references']['softbins']
|
502
|
-
i = 0
|
503
|
-
possible = []
|
504
|
-
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0'))
|
505
|
-
possible << proposal
|
506
|
-
while refs[proposal] && i.to_s.size <= max_counter_size
|
507
|
-
i += 1
|
508
|
-
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0'))
|
509
|
-
possible << proposal
|
510
|
-
end
|
511
|
-
# Overflowed, need to go search for the oldest duplicate now
|
512
|
-
if i.to_s.size > max_counter_size
|
513
|
-
i = 0
|
514
|
-
# Not the most efficient search algorithm, but this should be hit very rarely
|
515
|
-
# and even then only to generate the bin the first time around
|
516
|
-
p = refs.sort_by { |bin, last_used| last_used }.find do |bin, last_used|
|
517
|
-
possible.include?(bin)
|
478
|
+
([:bin, :softbin, :number] - [type]).each do |t|
|
479
|
+
if number =~ /(#{t.to_s[0]}+)/
|
480
|
+
max_size = Regexp.last_match(1).size
|
481
|
+
num = options[t].to_s
|
482
|
+
if num.size > max_size
|
483
|
+
fail "The allocated number, #{num}, overflows the #{t} field in the #{type} algorithm - #{algo}"
|
518
484
|
end
|
519
|
-
|
485
|
+
number = number.sub(/#{t.to_s[0]}+/, num.rjust(max_size, '0'))
|
520
486
|
end
|
521
|
-
number = proposal
|
522
|
-
end
|
523
|
-
else
|
524
|
-
fail "Unknown softbin algorithm: #{algo}"
|
525
|
-
end
|
526
|
-
number.to_i
|
527
|
-
elsif callback = config.softbins.callback
|
528
|
-
callback.call(bin, options)
|
529
|
-
else
|
530
|
-
if store['pointers']['softbins'] == 'done'
|
531
|
-
reclaim_softbin(options)
|
532
|
-
else
|
533
|
-
b = config.softbins.include.next(after: @last_softbin, size: options[:size])
|
534
|
-
@last_softbin = nil
|
535
|
-
while b && (store['manually_assigned']['softbins'][b.to_s] || config.softbins.exclude.include?(b))
|
536
|
-
b = config.softbins.include.next(size: options[:size])
|
537
|
-
end
|
538
|
-
# When no softbin is returned it means we have used them all, all future generation
|
539
|
-
# now switches to reclaim mode
|
540
|
-
if b
|
541
|
-
store['pointers']['softbins'] = b
|
542
|
-
else
|
543
|
-
store['pointers']['softbins'] = 'done'
|
544
|
-
reclaim_softbin(options)
|
545
487
|
end
|
546
|
-
end
|
547
|
-
end
|
548
|
-
end
|
549
|
-
|
550
|
-
def reclaim_softbin(options)
|
551
|
-
store['references']['softbins'] = store['references']['softbins'].sort_by { |k, v| v }.to_h
|
552
|
-
if options[:size] == 1
|
553
|
-
store['references']['softbins'].first[0].to_i
|
554
|
-
else
|
555
|
-
reclaim(store['references']['softbins'], options)
|
556
|
-
end
|
557
|
-
end
|
558
488
|
|
559
|
-
def allocate_number(options)
|
560
|
-
bin = options[:bin]
|
561
|
-
softbin = options[:softbin]
|
562
|
-
return nil if config.numbers.empty?
|
563
|
-
if config.numbers.algorithm
|
564
|
-
algo = config.numbers.algorithm.to_s.downcase
|
565
|
-
if algo.to_s =~ /^[bs\dx]+$/
|
566
|
-
number = algo.to_s
|
567
|
-
bin = bin.to_s
|
568
|
-
if number =~ /(b+)/
|
569
|
-
max_bin_size = Regexp.last_match(1).size
|
570
|
-
if bin.size > max_bin_size
|
571
|
-
fail "Bin number (#{bin}) overflows the test number algorithm (#{algo})"
|
572
|
-
end
|
573
|
-
number = number.sub(/b+/, bin.rjust(max_bin_size, '0'))
|
574
|
-
end
|
575
|
-
softbin = softbin.to_s
|
576
|
-
if number =~ /(s+)/
|
577
|
-
max_softbin_size = Regexp.last_match(1).size
|
578
|
-
if softbin.size > max_softbin_size
|
579
|
-
fail "Softbin number (#{softbin}) overflows the test number algorithm (#{algo})"
|
580
|
-
end
|
581
|
-
number = number.sub(/s+/, softbin.rjust(max_softbin_size, '0'))
|
582
|
-
end
|
583
489
|
if number =~ /(x+)/
|
584
490
|
max_counter_size = Regexp.last_match(1).size
|
585
|
-
refs = store['references'][
|
491
|
+
refs = store['references'][type_plural]
|
586
492
|
i = 0
|
587
493
|
possible = []
|
588
|
-
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0'))
|
494
|
+
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0')).to_i.to_s
|
589
495
|
possible << proposal
|
590
496
|
while refs[proposal] && i.to_s.size <= max_counter_size
|
591
497
|
i += 1
|
592
|
-
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0'))
|
498
|
+
proposal = number.sub(/x+/, i.to_s.rjust(max_counter_size, '0')).to_i.to_s
|
593
499
|
possible << proposal
|
594
500
|
end
|
595
501
|
# Overflowed, need to go search for the oldest duplicate now
|
@@ -604,39 +510,42 @@ module TestIds
|
|
604
510
|
end
|
605
511
|
number = proposal
|
606
512
|
end
|
607
|
-
number.to_i
|
608
513
|
else
|
609
|
-
fail "
|
514
|
+
fail "Illegal algorithm: #{algo}"
|
610
515
|
end
|
611
|
-
|
612
|
-
|
516
|
+
number.to_i
|
517
|
+
elsif callback = conf.callback
|
518
|
+
callback.call(options)
|
613
519
|
else
|
614
|
-
if store['pointers'][
|
615
|
-
|
520
|
+
if store['pointers'][type_plural] == 'done'
|
521
|
+
reclaim_item(type, options)
|
616
522
|
else
|
617
|
-
b =
|
618
|
-
@
|
619
|
-
while b && (store['manually_assigned'][
|
620
|
-
b =
|
523
|
+
b = conf.include.next(after: instance_variable_get("@last_#{type}"), size: options[:size])
|
524
|
+
instance_variable_set("@last_#{type}", nil)
|
525
|
+
while b && (store['manually_assigned'][type_plural][b.to_s] || conf.exclude.include?(b))
|
526
|
+
b = conf.include.next(size: options[:size])
|
621
527
|
end
|
622
528
|
# When no number is returned it means we have used them all, all future generation
|
623
529
|
# now switches to reclaim mode
|
624
530
|
if b
|
625
|
-
store['pointers'][
|
531
|
+
store['pointers'][type_plural] = b + (options[:size] || 1) - 1
|
532
|
+
b
|
626
533
|
else
|
627
|
-
store['pointers'][
|
628
|
-
|
534
|
+
store['pointers'][type_plural] = 'done'
|
535
|
+
reclaim_item(type, options)
|
629
536
|
end
|
630
537
|
end
|
631
538
|
end
|
632
539
|
end
|
633
540
|
|
634
|
-
def
|
635
|
-
|
541
|
+
def reclaim_item(type, options)
|
542
|
+
type_plural = "#{type}s"
|
543
|
+
store['references'][type_plural] = store['references'][type_plural].sort_by { |k, v| v }.to_h
|
636
544
|
if options[:size] == 1
|
637
|
-
store['references'][
|
545
|
+
v = store['references'][type_plural].first
|
546
|
+
v[0].to_i if v
|
638
547
|
else
|
639
|
-
reclaim(store['references'][
|
548
|
+
reclaim(store['references'][type_plural], options)
|
640
549
|
end
|
641
550
|
end
|
642
551
|
|
@@ -1,22 +1,29 @@
|
|
1
1
|
module TestIds
|
2
2
|
class Configuration
|
3
3
|
class Item
|
4
|
-
attr_accessor :include, :exclude, :algorithm, :size
|
4
|
+
attr_accessor :include, :exclude, :algorithm, :size, :needs
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@include = BinArray.new
|
8
8
|
@exclude = BinArray.new
|
9
|
+
@needs = []
|
9
10
|
@size = 1
|
10
11
|
end
|
11
12
|
|
12
|
-
def callback(&block)
|
13
|
+
def callback(options = {}, &block)
|
13
14
|
if block_given?
|
15
|
+
@needs += Array(options[:needs])
|
14
16
|
@callback = block
|
15
17
|
else
|
16
18
|
@callback
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
22
|
+
def needs?(type)
|
23
|
+
!!(!empty? && function? && (needs.include?(type) ||
|
24
|
+
(algorithm && (algorithm.to_s =~ /#{type.to_s[0]}/i))))
|
25
|
+
end
|
26
|
+
|
20
27
|
def empty?
|
21
28
|
include.empty? && exclude.empty? && !algorithm && !callback
|
22
29
|
end
|
@@ -36,6 +43,7 @@ module TestIds
|
|
36
43
|
def freeze
|
37
44
|
@include.freeze
|
38
45
|
@exclude.freeze
|
46
|
+
@needs.freeze
|
39
47
|
super
|
40
48
|
end
|
41
49
|
|
@@ -88,18 +96,23 @@ module TestIds
|
|
88
96
|
@id
|
89
97
|
end
|
90
98
|
|
91
|
-
def bins(&block)
|
99
|
+
def bins(options = {}, &block)
|
92
100
|
@bins ||= Item.new
|
93
101
|
if block_given?
|
94
|
-
@bins.callback(&block)
|
102
|
+
@bins.callback(options, &block)
|
95
103
|
end
|
96
104
|
@bins
|
97
105
|
end
|
98
106
|
|
99
|
-
|
107
|
+
# An alias for config.bins.algorithm=
|
108
|
+
def bins=(val)
|
109
|
+
bins.algorithm = val
|
110
|
+
end
|
111
|
+
|
112
|
+
def softbins(options = {}, &block)
|
100
113
|
@softbins ||= Item.new
|
101
114
|
if block_given?
|
102
|
-
@softbins.callback(&block)
|
115
|
+
@softbins.callback(options, &block)
|
103
116
|
end
|
104
117
|
@softbins
|
105
118
|
end
|
@@ -109,10 +122,10 @@ module TestIds
|
|
109
122
|
softbins.algorithm = val
|
110
123
|
end
|
111
124
|
|
112
|
-
def numbers(&block)
|
125
|
+
def numbers(options = {}, &block)
|
113
126
|
@numbers ||= Item.new
|
114
127
|
if block_given?
|
115
|
-
@numbers.callback(&block)
|
128
|
+
@numbers.callback(options, &block)
|
116
129
|
end
|
117
130
|
@numbers
|
118
131
|
end
|
@@ -123,18 +136,23 @@ module TestIds
|
|
123
136
|
end
|
124
137
|
|
125
138
|
def send_to_ate=(val)
|
126
|
-
@send_to_ate = val
|
139
|
+
@send_to_ate = !!val
|
127
140
|
end
|
128
141
|
|
129
|
-
def send_to_ate
|
130
|
-
@send_to_ate
|
142
|
+
def send_to_ate?
|
143
|
+
defined?(@send_to_ate) ? @send_to_ate : true
|
144
|
+
end
|
145
|
+
|
146
|
+
def unique_by_flow=(val)
|
147
|
+
@unique_by_flow = !!val
|
148
|
+
end
|
149
|
+
|
150
|
+
def unique_by_flow?
|
151
|
+
@unique_by_flow || false
|
131
152
|
end
|
132
153
|
|
133
154
|
def validate!
|
134
155
|
unless validated?
|
135
|
-
if bins.algorithm
|
136
|
-
fail 'The TestIds bins configuration cannot be set to an algorithm, only a range set by bins.include and bins.exclude is permitted'
|
137
|
-
end
|
138
156
|
@validated = true
|
139
157
|
freeze
|
140
158
|
end
|
@@ -7,13 +7,16 @@ module OrigenTesters
|
|
7
7
|
# test numbers
|
8
8
|
alias_method :_orig_test, :test
|
9
9
|
def test(instance, options = {})
|
10
|
-
if TestIds.configured? && options[:test_ids] != :notrack
|
11
|
-
TestIds.current_configuration.allocator.allocate(instance, options)
|
12
|
-
end
|
13
10
|
if TestIds.configured?
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
unless options[:test_ids] == :notrack
|
12
|
+
options[:test_ids_flow_id] = id
|
13
|
+
|
14
|
+
TestIds.current_configuration.allocator.allocate(instance, options)
|
15
|
+
|
16
|
+
unless TestIds.current_configuration.send_to_ate?
|
17
|
+
BIN_OPTS.each do |opt|
|
18
|
+
options.delete(opt)
|
19
|
+
end
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
@@ -5,17 +5,23 @@ module TestIdsDev
|
|
5
5
|
def initialize(options = {})
|
6
6
|
case dut.test_ids
|
7
7
|
when 1
|
8
|
-
TestIds.configure do |config|
|
8
|
+
TestIds.configure id: :cfg1 do |config|
|
9
9
|
# Example of testing remote repo
|
10
10
|
# config.repo = 'ssh://git@sw-stash.freescale.net/~r49409/test_ids_repo.git'
|
11
11
|
config.bins.include << 3
|
12
12
|
config.bins.include << (10..20)
|
13
13
|
config.bins.exclude << 15
|
14
14
|
config.softbins = :bbbxx
|
15
|
-
config.numbers do |
|
16
|
-
softbin * 100
|
15
|
+
config.numbers needs: :softbin do |options|
|
16
|
+
options[:softbin] * 100
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
when 2
|
21
|
+
TestIds.configure id: :cfg2 do |config|
|
22
|
+
config.bins.include << (5..16)
|
23
|
+
config.softbins = :bbxxx
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
data/program/prb1.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
Flow.create do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
if dut.test_ids == 2
|
3
|
+
func :t1, bin: 11
|
4
|
+
func :t2, bin: 11
|
5
|
+
func :t3, bin: 11
|
6
|
+
func :t4, bin: 11
|
7
|
+
func :t5, bin: 11
|
8
|
+
else
|
9
|
+
func :t1
|
10
|
+
func :t2
|
11
|
+
func :t3
|
12
|
+
func :t3, bin: :none, sbin: :none
|
13
|
+
end
|
7
14
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_ids
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.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: 2018-
|
11
|
+
date: 2018-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
101
|
version: 1.8.11
|
102
102
|
requirements: []
|
103
103
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.6.
|
104
|
+
rubygems_version: 2.6.14.1
|
105
105
|
signing_key:
|
106
106
|
specification_version: 4
|
107
107
|
summary: Origen plugin to assign and track test program bins and test numbers
|