test_ids 0.6.1 → 0.7.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 +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
|