test_ids 0.6.1 → 0.7.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 +5 -7
- data/config/version.rb +2 -2
- data/lib/test_ids/allocator.rb +190 -47
- data/lib/test_ids/bin_array.rb +19 -4
- data/lib/test_ids/configuration.rb +2 -1
- 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: a420dfdf8098943808de4f3f81202346fa8453c6
|
4
|
+
data.tar.gz: cd95837fd3c3086af0fb41fb3d9bcb71070725c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e402d3ac81c6d86bc5058ca6dd545ddf255c9bc1f68dd9d271f58099d6b1796a744df50067b91a2a69ebcf8e15758ebfa1eb332e476314da0e70563fb96f0c71
|
7
|
+
data.tar.gz: a41410e7b3ac45a93be182441fc0b4804ad1c4ef054dbbbb1af7cc66b5939310250695eb78fcb224dfad1923d1eed0bfd8badf1f6f80acf9a829bcfbd136eedf
|
data/config/commands.rb
CHANGED
@@ -13,13 +13,10 @@ aliases ={
|
|
13
13
|
# Now branch to the specific task code
|
14
14
|
case @command
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#require "commands/my_command" # Would load file lib/commands/my_command.rb
|
21
|
-
# You must always exit upon successfully capturing a command to prevent
|
22
|
-
# control flowing back to Origen
|
16
|
+
when "tags"
|
17
|
+
Dir.chdir Origen.root do
|
18
|
+
system("ripper-tags -R")
|
19
|
+
end
|
23
20
|
exit 0
|
24
21
|
|
25
22
|
# Example of how to make a command to run unit tests, this simply invokes RSpec on
|
@@ -63,6 +60,7 @@ else
|
|
63
60
|
# origen -h, you can do this be assigning the required text to @application_commands
|
64
61
|
# before handing control back to Origen. Un-comment the example below to get started.
|
65
62
|
@application_commands = <<-EOT
|
63
|
+
tags Build a tags file for this app
|
66
64
|
specs Run the specs (tests), -c will enable coverage
|
67
65
|
examples Run the examples (tests), -c will enable coverage
|
68
66
|
test Run both specs and examples, -c will enable coverage
|
data/config/version.rb
CHANGED
data/lib/test_ids/allocator.rb
CHANGED
@@ -5,6 +5,8 @@ module TestIds
|
|
5
5
|
# There is one allocator instance per configuration, and each has its own database
|
6
6
|
# file.
|
7
7
|
class Allocator
|
8
|
+
STORE_FORMAT_REVISION = 1
|
9
|
+
|
8
10
|
attr_reader :config
|
9
11
|
|
10
12
|
def initialize(configuration)
|
@@ -18,49 +20,109 @@ module TestIds
|
|
18
20
|
@callbacks = []
|
19
21
|
name = extract_test_name(instance, options)
|
20
22
|
name = "#{name}_#{options[:index]}" if options[:index]
|
21
|
-
|
22
|
-
|
23
|
+
|
24
|
+
# First work out the test ID to be used for each of the numbers, and how many numbers
|
25
|
+
# should be reserved
|
26
|
+
if (options[:bin].is_a?(Symbol) || options[:bin].is_a?(String)) && options[:bin] != :none
|
27
|
+
bin_id = options[:bin].to_s
|
28
|
+
else
|
29
|
+
bin_id = name
|
30
|
+
end
|
31
|
+
if (options[:softbin].is_a?(Symbol) || options[:softbin].is_a?(String)) && options[:softbin] != :none
|
32
|
+
softbin_id = options[:softbin].to_s
|
33
|
+
else
|
34
|
+
softbin_id = name
|
35
|
+
end
|
36
|
+
if (options[:number].is_a?(Symbol) || options[:number].is_a?(String)) && options[:number] != :none
|
37
|
+
number_id = options[:number].to_s
|
38
|
+
else
|
39
|
+
number_id = name
|
40
|
+
end
|
41
|
+
|
42
|
+
bin_size = options[:bin_size] || config.bins.size
|
43
|
+
softbin_size = options[:softbin_size] || config.softbins.size
|
44
|
+
number_size = options[:number_size] || config.numbers.size
|
45
|
+
|
46
|
+
bin = store['assigned']['bin'][bin_id] ||= {}
|
47
|
+
softbin = store['assigned']['softbin'][softbin_id] ||= {}
|
48
|
+
number = store['assigned']['number'][number_id] ||= {}
|
49
|
+
|
23
50
|
# If the user has supplied any of these, that number should be used
|
24
51
|
# and reserved so that it is not automatically generated later
|
25
52
|
if options[:bin] && options[:bin].is_a?(Numeric)
|
26
|
-
|
53
|
+
bin['number'] = options[:bin]
|
54
|
+
bin['size'] = bin_size
|
27
55
|
store['manually_assigned']['bin'][options[:bin].to_s] = true
|
28
56
|
# Regenerate the bin if the original allocation has since been applied
|
29
57
|
# manually elsewhere
|
30
|
-
elsif store['manually_assigned']['bin'][
|
31
|
-
|
58
|
+
elsif store['manually_assigned']['bin'][bin['number'].to_s]
|
59
|
+
bin['number'] = nil
|
60
|
+
bin['size'] = nil
|
32
61
|
# Also regenerate these as they could be a function of the bin
|
33
|
-
|
34
|
-
|
62
|
+
if config.softbins.function?
|
63
|
+
softbin['number'] = nil
|
64
|
+
softbin['size'] = nil
|
65
|
+
end
|
66
|
+
if config.numbers.function?
|
67
|
+
number['number'] = nil
|
68
|
+
number['size'] = nil
|
69
|
+
end
|
35
70
|
end
|
36
71
|
if options[:softbin] && options[:softbin].is_a?(Numeric)
|
37
|
-
|
72
|
+
softbin['number'] = options[:softbin]
|
73
|
+
softbin['size'] = softbin_size
|
38
74
|
store['manually_assigned']['softbin'][options[:softbin].to_s] = true
|
39
|
-
elsif store['manually_assigned']['softbin'][
|
40
|
-
|
75
|
+
elsif store['manually_assigned']['softbin'][softbin['number'].to_s]
|
76
|
+
softbin['number'] = nil
|
77
|
+
softbin['size'] = nil
|
41
78
|
# Also regenerate the number as it could be a function of the softbin
|
42
|
-
|
79
|
+
if config.numbers.function?
|
80
|
+
number['number'] = nil
|
81
|
+
number['size'] = nil
|
82
|
+
end
|
43
83
|
end
|
44
84
|
if options[:number] && options[:number].is_a?(Numeric)
|
45
|
-
|
85
|
+
number['number'] = options[:number]
|
86
|
+
number['size'] = number_size
|
46
87
|
store['manually_assigned']['number'][options[:number].to_s] = true
|
47
|
-
elsif store['manually_assigned']['number'][
|
48
|
-
|
88
|
+
elsif store['manually_assigned']['number'][number['number'].to_s]
|
89
|
+
number['number'] = nil
|
90
|
+
number['size'] = nil
|
49
91
|
end
|
92
|
+
|
50
93
|
# Otherwise generate the missing ones
|
51
|
-
|
52
|
-
|
53
|
-
|
94
|
+
bin['number'] ||= allocate_bin(size: bin_size)
|
95
|
+
bin['size'] ||= bin_size
|
96
|
+
softbin['number'] ||= allocate_softbin(bin: bin['number'], size: softbin_size)
|
97
|
+
softbin['size'] ||= softbin_size
|
98
|
+
number['number'] ||= allocate_number(bin: bin['number'], softbin: softbin['number'], size: number_size)
|
99
|
+
number['size'] ||= number_size
|
100
|
+
|
54
101
|
# Record that there has been a reference to the final numbers
|
55
102
|
time = Time.now.to_f
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
103
|
+
bin_size.times do |i|
|
104
|
+
store['references']['bin'][(bin['number'] + i).to_s] = time if bin['number'] && options[:bin] != :none
|
105
|
+
end
|
106
|
+
softbin_size.times do |i|
|
107
|
+
store['references']['softbin'][(softbin['number'] + i).to_s] = time if softbin['number'] && options[:softbin] != :none
|
108
|
+
end
|
109
|
+
number_size.times do |i|
|
110
|
+
store['references']['number'][(number['number'] + i).to_s] = time if number['number'] && options[:number] != :none
|
111
|
+
end
|
112
|
+
|
113
|
+
# Update the supplied options hash that will be forwarded to the program generator
|
114
|
+
unless options.delete(:bin) == :none
|
115
|
+
options[:bin] = bin['number']
|
116
|
+
options[:bin_size] = bin['size']
|
117
|
+
end
|
118
|
+
unless options.delete(:softbin) == :none
|
119
|
+
options[:softbin] = softbin['number']
|
120
|
+
options[:softbin_size] = softbin['size']
|
121
|
+
end
|
122
|
+
unless options.delete(:number) == :none
|
123
|
+
options[:number] = number['number']
|
124
|
+
options[:number_size] = number['size']
|
125
|
+
end
|
64
126
|
options
|
65
127
|
end
|
66
128
|
|
@@ -68,12 +130,30 @@ module TestIds
|
|
68
130
|
@store ||= begin
|
69
131
|
s = JSON.load(File.read(file)) if file && File.exist?(file)
|
70
132
|
if s
|
133
|
+
if s['format_revision'] != STORE_FORMAT_REVISION
|
134
|
+
# Upgrade the original store format
|
135
|
+
t = { 'bin' => {}, 'softbin' => {}, 'number' => {} }
|
136
|
+
s['tests'].each do |name, numbers|
|
137
|
+
t['bin'][name] = { 'number' => numbers['bin'], 'size' => 1 }
|
138
|
+
t['softbin'][name] = { 'number' => numbers['softbin'], 'size' => 1 }
|
139
|
+
t['number'][name] = { 'number' => numbers['number'], 'size' => 1 }
|
140
|
+
end
|
141
|
+
s = {
|
142
|
+
'format_revision' => STORE_FORMAT_REVISION,
|
143
|
+
'assigned' => t,
|
144
|
+
'manually_assigned' => s['manually_assigned'],
|
145
|
+
'pointers' => s['pointers'],
|
146
|
+
'references' => s['references']
|
147
|
+
}
|
148
|
+
end
|
71
149
|
@last_bin = s['pointers']['bin']
|
72
150
|
@last_softbin = s['pointers']['softbin']
|
73
151
|
@last_number = s['pointers']['number']
|
74
152
|
s
|
75
153
|
else
|
76
|
-
{
|
154
|
+
{
|
155
|
+
'format_revision' => STORE_FORMAT_REVISION,
|
156
|
+
'assigned' => { 'bin' => {}, 'softbin' => {}, 'number' => {} },
|
77
157
|
'manually_assigned' => { 'bin' => {}, 'softbin' => {}, 'number' => {} },
|
78
158
|
'pointers' => { 'bin' => nil, 'softbin' => nil, 'number' => nil },
|
79
159
|
'references' => { 'bin' => {}, 'softbin' => {}, 'number' => {} }
|
@@ -108,15 +188,15 @@ module TestIds
|
|
108
188
|
|
109
189
|
# Returns the next available bin in the pool, if they have all been given out
|
110
190
|
# the one that hasn't been used for the longest time will be given out
|
111
|
-
def allocate_bin
|
191
|
+
def allocate_bin(options)
|
112
192
|
return nil if config.bins.empty?
|
113
193
|
if store['pointers']['bin'] == 'done'
|
114
|
-
reclaim_bin
|
194
|
+
reclaim_bin(options)
|
115
195
|
else
|
116
|
-
b = config.bins.include.next(@last_bin)
|
196
|
+
b = config.bins.include.next(after: @last_bin, size: options[:size])
|
117
197
|
@last_bin = nil
|
118
198
|
while b && (store['manually_assigned']['bin'][b.to_s] || config.bins.exclude.include?(b))
|
119
|
-
b = config.bins.include.next
|
199
|
+
b = config.bins.include.next(size: options[:size])
|
120
200
|
end
|
121
201
|
# When no bin is returned it means we have used them all, all future generation
|
122
202
|
# now switches to reclaim mode
|
@@ -124,17 +204,22 @@ module TestIds
|
|
124
204
|
store['pointers']['bin'] = b
|
125
205
|
else
|
126
206
|
store['pointers']['bin'] = 'done'
|
127
|
-
reclaim_bin
|
207
|
+
reclaim_bin(options)
|
128
208
|
end
|
129
209
|
end
|
130
210
|
end
|
131
211
|
|
132
|
-
def reclaim_bin
|
212
|
+
def reclaim_bin(options)
|
133
213
|
store['references']['bin'] = store['references']['bin'].sort_by { |k, v| v }.to_h
|
134
|
-
|
214
|
+
if options[:size] == 1
|
215
|
+
store['references']['bin'].first[0].to_i
|
216
|
+
else
|
217
|
+
reclaim(store['references']['bin'], options)
|
218
|
+
end
|
135
219
|
end
|
136
220
|
|
137
|
-
def allocate_softbin(
|
221
|
+
def allocate_softbin(options)
|
222
|
+
bin = options[:bin]
|
138
223
|
return nil if config.softbins.empty?
|
139
224
|
if config.softbins.algorithm
|
140
225
|
algo = config.softbins.algorithm.to_s.downcase
|
@@ -180,12 +265,12 @@ module TestIds
|
|
180
265
|
callback.call(bin)
|
181
266
|
else
|
182
267
|
if store['pointers']['softbin'] == 'done'
|
183
|
-
reclaim_softbin
|
268
|
+
reclaim_softbin(options)
|
184
269
|
else
|
185
|
-
b = config.softbins.include.next(@last_softbin)
|
270
|
+
b = config.softbins.include.next(after: @last_softbin, size: options[:size])
|
186
271
|
@last_softbin = nil
|
187
272
|
while b && (store['manually_assigned']['softbin'][b.to_s] || config.softbins.exclude.include?(b))
|
188
|
-
b = config.softbins.include.next
|
273
|
+
b = config.softbins.include.next(size: options[:size])
|
189
274
|
end
|
190
275
|
# When no softbin is returned it means we have used them all, all future generation
|
191
276
|
# now switches to reclaim mode
|
@@ -193,18 +278,24 @@ module TestIds
|
|
193
278
|
store['pointers']['softbin'] = b
|
194
279
|
else
|
195
280
|
store['pointers']['softbin'] = 'done'
|
196
|
-
reclaim_softbin
|
281
|
+
reclaim_softbin(options)
|
197
282
|
end
|
198
283
|
end
|
199
284
|
end
|
200
285
|
end
|
201
286
|
|
202
|
-
def reclaim_softbin
|
287
|
+
def reclaim_softbin(options)
|
203
288
|
store['references']['softbin'] = store['references']['softbin'].sort_by { |k, v| v }.to_h
|
204
|
-
|
289
|
+
if options[:size] == 1
|
290
|
+
store['references']['softbin'].first[0].to_i
|
291
|
+
else
|
292
|
+
reclaim(store['references']['softbin'], options)
|
293
|
+
end
|
205
294
|
end
|
206
295
|
|
207
|
-
def allocate_number(
|
296
|
+
def allocate_number(options)
|
297
|
+
bin = options[:bin]
|
298
|
+
softbin = options[:softbin]
|
208
299
|
return nil if config.numbers.empty?
|
209
300
|
if config.numbers.algorithm
|
210
301
|
algo = config.numbers.algorithm.to_s.downcase
|
@@ -258,12 +349,12 @@ module TestIds
|
|
258
349
|
callback.call(bin, softbin)
|
259
350
|
else
|
260
351
|
if store['pointers']['number'] == 'done'
|
261
|
-
reclaim_number
|
352
|
+
reclaim_number(options)
|
262
353
|
else
|
263
|
-
b = config.numbers.include.next(@last_number)
|
354
|
+
b = config.numbers.include.next(after: @last_number, size: options[:size])
|
264
355
|
@last_number = nil
|
265
356
|
while b && (store['manually_assigned']['number'][b.to_s] || config.numbers.exclude.include?(b))
|
266
|
-
b = config.numbers.include.next
|
357
|
+
b = config.numbers.include.next(size: options[:size])
|
267
358
|
end
|
268
359
|
# When no number is returned it means we have used them all, all future generation
|
269
360
|
# now switches to reclaim mode
|
@@ -271,15 +362,67 @@ module TestIds
|
|
271
362
|
store['pointers']['number'] = b
|
272
363
|
else
|
273
364
|
store['pointers']['number'] = 'done'
|
274
|
-
reclaim_number
|
365
|
+
reclaim_number(options)
|
275
366
|
end
|
276
367
|
end
|
277
368
|
end
|
278
369
|
end
|
279
370
|
|
280
|
-
def reclaim_number
|
371
|
+
def reclaim_number(options)
|
281
372
|
store['references']['number'] = store['references']['number'].sort_by { |k, v| v }.to_h
|
282
|
-
|
373
|
+
if options[:size] == 1
|
374
|
+
store['references']['number'].first[0].to_i
|
375
|
+
else
|
376
|
+
reclaim(store['references']['number'], options)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
# Returns the oldest number in the given reference hash, however also supports a :size option
|
381
|
+
# and in that case it will look for the oldest contiguous range of the given size
|
382
|
+
def reclaim(refs, options)
|
383
|
+
a = []
|
384
|
+
i = 0 # Pointer to references hash, which is already sorted with oldest first
|
385
|
+
s = 0 # Largest contiguous size in the array of considered numbers
|
386
|
+
p = 0 # Pointer to start of a suitable contiguous section in the array
|
387
|
+
while s < options[:size] && i < refs.size
|
388
|
+
a << refs.keys[i].to_i
|
389
|
+
a.sort!
|
390
|
+
s, p = largest_contiguous_section(a)
|
391
|
+
i += 1
|
392
|
+
end
|
393
|
+
a[p]
|
394
|
+
end
|
395
|
+
|
396
|
+
def largest_contiguous_section(array)
|
397
|
+
max_ptr = 0
|
398
|
+
max_size = 0
|
399
|
+
p = nil
|
400
|
+
s = nil
|
401
|
+
prev = nil
|
402
|
+
array.each_with_index do |v, i|
|
403
|
+
if prev
|
404
|
+
if v == prev + 1
|
405
|
+
s += 1
|
406
|
+
else
|
407
|
+
if s > max_size
|
408
|
+
max_size = s
|
409
|
+
max_ptr = p
|
410
|
+
end
|
411
|
+
p = i
|
412
|
+
s = 1
|
413
|
+
end
|
414
|
+
prev = v
|
415
|
+
else
|
416
|
+
p = i
|
417
|
+
s = 1
|
418
|
+
prev = v
|
419
|
+
end
|
420
|
+
end
|
421
|
+
if s > max_size
|
422
|
+
max_size = s
|
423
|
+
max_ptr = p
|
424
|
+
end
|
425
|
+
[max_size, max_ptr]
|
283
426
|
end
|
284
427
|
|
285
428
|
def extract_test_name(instance, options)
|
data/lib/test_ids/bin_array.rb
CHANGED
@@ -5,7 +5,7 @@ module TestIds
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def <<(val)
|
8
|
-
@store
|
8
|
+
@store << val
|
9
9
|
@store = @store.sort do |a, b|
|
10
10
|
a = a.min if a.is_a?(Range)
|
11
11
|
b = b.min if b.is_a?(Range)
|
@@ -33,8 +33,9 @@ module TestIds
|
|
33
33
|
# when called the next time.
|
34
34
|
# A bin can optionally be supplied in which case the internal pointer will be reset and the
|
35
35
|
# next bin that occurs after the given number will be returned.
|
36
|
-
def next(
|
37
|
-
if after
|
36
|
+
def next(options = {})
|
37
|
+
if options[:after]
|
38
|
+
after = options[:after]
|
38
39
|
# Need to work out the pointer here as it is probably out of sync with the
|
39
40
|
# last value now
|
40
41
|
@pointer = nil
|
@@ -79,7 +80,21 @@ module TestIds
|
|
79
80
|
@next = v
|
80
81
|
end
|
81
82
|
end
|
82
|
-
|
83
|
+
if options[:size] && options[:size] > 1
|
84
|
+
# Check that all the numbers in the range to be reserved are included in the allocation,
|
85
|
+
# if not call again
|
86
|
+
included = true
|
87
|
+
options[:size].times { |i| included = false unless include?(@next + i) }
|
88
|
+
if included
|
89
|
+
n = @next
|
90
|
+
@next = @next + options[:size] - 1
|
91
|
+
n
|
92
|
+
else
|
93
|
+
self.next(after: @next, size: options[:size])
|
94
|
+
end
|
95
|
+
else
|
96
|
+
@next
|
97
|
+
end
|
83
98
|
end
|
84
99
|
|
85
100
|
def min
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module TestIds
|
2
2
|
class Configuration
|
3
3
|
class Item
|
4
|
-
attr_accessor :include, :exclude, :algorithm
|
4
|
+
attr_accessor :include, :exclude, :algorithm, :size
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@include = BinArray.new
|
8
8
|
@exclude = BinArray.new
|
9
|
+
@size = 1
|
9
10
|
end
|
10
11
|
|
11
12
|
def callback(&block)
|
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: 0.7.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: 2017-
|
11
|
+
date: 2017-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
99
|
version: 1.8.11
|
100
100
|
requirements: []
|
101
101
|
rubyforge_project:
|
102
|
-
rubygems_version: 2.
|
102
|
+
rubygems_version: 2.5.2
|
103
103
|
signing_key:
|
104
104
|
specification_version: 4
|
105
105
|
summary: Origen plugin to assign and track test program bins and test numbers
|