test_ids 0.8.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|