test_ids 1.1.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/application.rb +1 -1
- data/config/shared_commands.rb +1 -1
- data/config/version.rb +2 -3
- data/lib/test_ids/allocator.rb +32 -14
- data/lib/test_ids/commands/clear.rb +6 -0
- data/lib/test_ids/git.rb +46 -40
- data/lib/test_ids.rb +86 -0
- metadata +33 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cc056bd639bd5288a0ed73842d5790de1beaf2d8ef53aefe004376fd2647ca2
|
4
|
+
data.tar.gz: 75ee0869b2c5d8a9e0e0ec75d9125bd8ad5286a1490af80e95ddcd986874b12e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca98189aaf0d39ba9b4f7acac86354e5f6afa2c537dc3e6f70ebcce6413e607aeca2ed722f548c761432306729163c1b893ca4a10bbf2b711b217cd2418bfc58
|
7
|
+
data.tar.gz: 86b3b1023d650d963adf0cc4998dda002bec9bd925b4ac20e414f4215a765101ca7c8e5a8dfd84024eec4808e17fb61ca425a150218357955c622dc5d22d0bfc
|
data/config/application.rb
CHANGED
@@ -83,7 +83,7 @@ class TestIdsApplication < Origen::Application
|
|
83
83
|
puts "All tests passing, proceeding with release process!"
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
# To enabled source-less pattern generation create a class (for example PatternDispatcher)
|
88
88
|
# to generate the pattern. This should return false if the requested pattern has been
|
89
89
|
# dispatched, otherwise Origen will proceed with looking up a pattern source as normal.
|
data/config/shared_commands.rb
CHANGED
@@ -17,7 +17,7 @@ when "test_ids:clear", "test_ids:repair"
|
|
17
17
|
else
|
18
18
|
@plugin_commands << <<-EOT
|
19
19
|
test_ids:rollback Rollback the TestIds store to the given commit ID
|
20
|
-
test_ids:clear Clear the assignment database for bins, softbins, numbers or all
|
20
|
+
test_ids:clear Clear the assignment database for bins, softbins, numbers, ranges or all for the given configuration database ID
|
21
21
|
test_ids:repair Repair the given database, see -h for more
|
22
22
|
EOT
|
23
23
|
|
data/config/version.rb
CHANGED
data/lib/test_ids/allocator.rb
CHANGED
@@ -28,11 +28,26 @@ module TestIds
|
|
28
28
|
# If a numeric number is passed to the softbin, it uses that number.
|
29
29
|
# The configuration for the TestId plugin needs to pass in the bin number and the options from the test flow
|
30
30
|
# For this method to work as intended.
|
31
|
-
|
32
|
-
|
31
|
+
# This will handle the following range inputs:
|
32
|
+
# - Range, Ex: 0..10
|
33
|
+
# - Array, Ex: [0..10, 20..30]
|
34
|
+
def next_in_range(range_definition, options)
|
35
|
+
if range_definition.is_a?(Range)
|
36
|
+
range = range_definition.to_a
|
37
|
+
elsif range_definition.is_a?(Array)
|
38
|
+
range = []
|
39
|
+
range_definition.each do |range_element|
|
40
|
+
range += range_element.is_a?(Integer) ? [range_element] : range_element.step(options[:size]).to_a
|
41
|
+
end
|
42
|
+
if range.uniq.size != range.size
|
43
|
+
Origen.log.error "Duplicate or overlapping range has been detected in configuration: \'#{TestIds.current_configuration.id}\'."
|
44
|
+
fail
|
45
|
+
end
|
46
|
+
end
|
47
|
+
range_item(range, range_definition, options)
|
33
48
|
end
|
34
49
|
|
35
|
-
def range_item(range, options)
|
50
|
+
def range_item(range, range_definition, options)
|
36
51
|
# This is the actual fix, it should now not be dependent on the json file being read in, instead the store pointers
|
37
52
|
# will be utilized to get the correct number assigned from the range.
|
38
53
|
if store['pointers']['ranges'].nil?
|
@@ -43,33 +58,33 @@ module TestIds
|
|
43
58
|
end
|
44
59
|
orig_options = options.dup
|
45
60
|
# Check the database to see if the passed in range has already been included in the database hash
|
46
|
-
if rangehash.key?(:"#{
|
61
|
+
if rangehash.key?(:"#{range_definition}")
|
47
62
|
# Read out the database hash to see what the last_softbin given out was for that range.
|
48
63
|
# This hash is updated whenever a new softbin is assigned, so it should have the updated values for each range.
|
49
|
-
previous_assigned_value = rangehash[:"#{
|
64
|
+
previous_assigned_value = rangehash[:"#{range_definition}"].to_i
|
50
65
|
# Now calculate the new pointer.
|
51
|
-
@pointer = previous_assigned_value
|
66
|
+
@pointer = range.index(previous_assigned_value) + 1
|
52
67
|
# Check if the last_softbin given out is the same as the range[@pointer],
|
53
68
|
# if so increment pointer by softbin size, default size is 1, config.softbins.size is configurable.
|
54
69
|
# from example above, pointer was calculated as 1,range[1] is 10101 and is same as last_softbin, so pointer is incremented
|
55
70
|
# and new value is assigned to the softbin.
|
56
|
-
if previous_assigned_value == range
|
71
|
+
if previous_assigned_value == range[@pointer]
|
57
72
|
@pointer += options[:size]
|
58
|
-
assigned_value = range
|
73
|
+
assigned_value = range[@pointer]
|
59
74
|
else
|
60
75
|
# Because of the pointer calculations above, I don't think it will ever reach here, has not in my test cases so far!
|
61
|
-
assigned_value = range
|
76
|
+
assigned_value = range[@pointer]
|
62
77
|
end
|
63
78
|
# Now update the database pointers to point to the lastest assigned softbin for a given range.
|
64
|
-
rangehash.merge!(:"#{
|
79
|
+
rangehash.merge!(:"#{range_definition}" => "#{range[@pointer]}")
|
65
80
|
else
|
66
81
|
# This is the case for a brand new range that has not been passed before
|
67
82
|
# We start from the first value as the assigned softbin and update the database to reflect.
|
68
83
|
@pointer = 0
|
69
|
-
rangehash.merge!(:"#{
|
70
|
-
assigned_value = range
|
84
|
+
rangehash.merge!(:"#{range_definition}" => "#{range[@pointer]}")
|
85
|
+
assigned_value = range[@pointer]
|
71
86
|
end
|
72
|
-
unless !assigned_value.nil? &&
|
87
|
+
unless !assigned_value.nil? && range.include?(assigned_value)
|
73
88
|
Origen.log.error 'Assigned value not in range'
|
74
89
|
fail
|
75
90
|
end
|
@@ -281,7 +296,7 @@ module TestIds
|
|
281
296
|
end
|
282
297
|
end
|
283
298
|
|
284
|
-
# Clear the :bins, :softbins and/or :numbers by setting the options for each item
|
299
|
+
# Clear the :bins, :softbins and/or :numbers and/or :ranges by setting the options for each item
|
285
300
|
def clear(options)
|
286
301
|
if options[:softbin] || options[:softbins]
|
287
302
|
store['assigned']['softbins'] = {}
|
@@ -301,6 +316,9 @@ module TestIds
|
|
301
316
|
store['pointers']['numbers'] = nil
|
302
317
|
store['references']['numbers'] = {}
|
303
318
|
end
|
319
|
+
if options[:range] || options[:ranges]
|
320
|
+
store['pointers']['ranges'] = nil
|
321
|
+
end
|
304
322
|
end
|
305
323
|
|
306
324
|
# Saves the current allocator state to the repository
|
@@ -18,6 +18,7 @@ Examples: origen test_ids:clear --bins # Clear the bins in
|
|
18
18
|
opts.on('--bins', 'Clear the bin database') { options[:bins] = true }
|
19
19
|
opts.on('--softbins', 'Clear the softbin database') { options[:softbins] = true }
|
20
20
|
opts.on('--numbers', 'Clear the test number database') { options[:numbers] = true }
|
21
|
+
opts.on('--ranges', 'Clear the ranges database') { options[:ranges] = true }
|
21
22
|
# opts.on('-pl', '--plugin PLUGIN_NAME', String, 'Set current plugin') { |pl_n| options[:current_plugin] = pl_n }
|
22
23
|
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
23
24
|
app_options.each do |app_option|
|
@@ -38,6 +39,11 @@ begin
|
|
38
39
|
# Get the commit before the lock to give the user later
|
39
40
|
rollback_id = git.repo.object('HEAD^').sha[0, 11]
|
40
41
|
a = TestIds.load_allocator(ARGV.first)
|
42
|
+
if a.nil?
|
43
|
+
Origen.log.error "No configuration file could be found for file ID: '#{ARGV.first}'!"
|
44
|
+
Origen.log.warn 'By default, the correct ID to pass in will need to match the filename in the form: store_<file id>.json'
|
45
|
+
fail
|
46
|
+
end
|
41
47
|
a.clear(options)
|
42
48
|
a.save
|
43
49
|
ensure
|
data/lib/test_ids/git.rb
CHANGED
@@ -50,26 +50,28 @@ module TestIds
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def initialize(options)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
53
|
+
if !(TestIds.lsf_manual_init_shutdown) && Origen.running_locally?
|
54
|
+
unless File.exist?("#{options[:local]}/.git")
|
55
|
+
FileUtils.rm_rf(options[:local]) if File.exist?(options[:local])
|
56
|
+
FileUtils.mkdir_p(options[:local])
|
57
|
+
Dir.chdir options[:local] do
|
58
|
+
`git clone #{options[:remote]} .`
|
59
|
+
unless File.exist?('lock.json')
|
60
|
+
# Should really try to use the Git driver for this
|
61
|
+
exec 'touch lock.json'
|
62
|
+
exec 'git add lock.json'
|
63
|
+
exec 'git commit -m "Initial commit"'
|
64
|
+
exec 'git push'
|
65
|
+
end
|
64
66
|
end
|
65
67
|
end
|
68
|
+
@local = options[:local]
|
69
|
+
@repo = ::Git.open(options[:local])
|
70
|
+
# Get rid of any local edits coming in here, this is only called once at the start
|
71
|
+
# of the program generation run.
|
72
|
+
# No need to pull latest as that will be done when we obtain a lock.
|
73
|
+
@repo.reset_hard
|
66
74
|
end
|
67
|
-
@local = options[:local]
|
68
|
-
@repo = ::Git.open(options[:local])
|
69
|
-
# Get rid of any local edits coming in here, this is only called once at the start
|
70
|
-
# of the program generation run.
|
71
|
-
# No need to pull latest as that will be done when we obtain a lock.
|
72
|
-
@repo.reset_hard
|
73
75
|
end
|
74
76
|
|
75
77
|
# Roll the repo back to the given commit ID
|
@@ -108,11 +110,13 @@ module TestIds
|
|
108
110
|
end
|
109
111
|
|
110
112
|
def publish
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
if !(TestIds.lsf_manual_init_shutdown) && Origen.running_locally?
|
114
|
+
Origen.profile 'Publishing the test IDs store' do
|
115
|
+
release_lock
|
116
|
+
repo.add # Checkin everything
|
117
|
+
repo.commit('Publishing latest store')
|
118
|
+
repo.push('origin', 'master', force: true)
|
119
|
+
end
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
@@ -124,23 +128,25 @@ module TestIds
|
|
124
128
|
end
|
125
129
|
|
126
130
|
def get_lock
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
131
|
+
if !(TestIds.lsf_manual_init_shutdown) && Origen.running_locally?
|
132
|
+
return if @lock_open
|
133
|
+
Origen.profile 'Obtaining test IDs lock' do
|
134
|
+
until available_to_lock?(@repo)
|
135
|
+
puts
|
136
|
+
puts "Waiting for lock, currently locked by #{lock_user} (the lock will expire in less than #{lock_minutes_remaining} #{'minute'.pluralize(lock_minutes_remaining)} if not released before that)"
|
137
|
+
puts
|
138
|
+
sleep 5
|
139
|
+
end
|
140
|
+
data = {
|
141
|
+
'user' => User.current.name,
|
142
|
+
'expires' => (Time.now + minutes(5)).to_f
|
143
|
+
}
|
144
|
+
write('lock.json', JSON.pretty_generate(data))
|
145
|
+
repo.commit('Obtaining lock')
|
146
|
+
repo.push('origin')
|
134
147
|
end
|
135
|
-
|
136
|
-
'user' => User.current.name,
|
137
|
-
'expires' => (Time.now + minutes(5)).to_f
|
138
|
-
}
|
139
|
-
write('lock.json', JSON.pretty_generate(data))
|
140
|
-
repo.commit('Obtaining lock')
|
141
|
-
repo.push('origin')
|
148
|
+
@lock_open = true
|
142
149
|
end
|
143
|
-
@lock_open = true
|
144
150
|
end
|
145
151
|
|
146
152
|
def release_lock
|
@@ -151,11 +157,11 @@ module TestIds
|
|
151
157
|
write('lock.json', JSON.pretty_generate(data))
|
152
158
|
end
|
153
159
|
|
154
|
-
def available_to_lock?
|
160
|
+
def available_to_lock?(repo_to_use)
|
155
161
|
result = false
|
156
162
|
Origen.profile 'Checking for lock' do
|
157
|
-
|
158
|
-
|
163
|
+
repo_to_use.fetch
|
164
|
+
repo_to_use.reset_hard('origin/master')
|
159
165
|
if lock_content && lock_user && lock_user != User.current.name
|
160
166
|
result = Time.now.to_f > lock_expires
|
161
167
|
else
|
data/lib/test_ids.rb
CHANGED
@@ -239,10 +239,78 @@ module TestIds
|
|
239
239
|
@publish = val ? :save : :dont_save
|
240
240
|
end
|
241
241
|
|
242
|
+
def lsf_manual_init_shutdown
|
243
|
+
if @lsf_manual_init_shutdown
|
244
|
+
true
|
245
|
+
end
|
246
|
+
false
|
247
|
+
end
|
248
|
+
|
242
249
|
def next_in_range(range, options)
|
243
250
|
current_configuration.allocator.next_in_range(range, options)
|
244
251
|
end
|
245
252
|
|
253
|
+
def lsf_init(git_repo, lsf_publish)
|
254
|
+
@lsf_manual_init_shutdown = true
|
255
|
+
local_var_git_database_dir = "#{Origen.app.imports_directory}/test_ids/#{Pathname.new(git_repo).basename}"
|
256
|
+
FileUtils.mkdir_p(local_var_git_database_dir)
|
257
|
+
unless File.exist?("#{local_var_git_database_dir}/.git")
|
258
|
+
FileUtils.rm_rf(local_var_git_database_dir) if File.exist?(local_var_git_database_dir)
|
259
|
+
FileUtils.mkdir_p(local_var_git_database_dir)
|
260
|
+
Dir.chdir local_var_git_database_dir do
|
261
|
+
`git clone #{git_repo} .`
|
262
|
+
unless File.exist?('lock.json')
|
263
|
+
# Should really try to use the Git driver for this
|
264
|
+
exec 'touch lock.json'
|
265
|
+
exec 'git add lock.json'
|
266
|
+
exec 'git commit -m "Initial commit"'
|
267
|
+
exec 'git push'
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
@local = local_var_git_database_dir
|
272
|
+
@repo = ::Git.open(local_var_git_database_dir)
|
273
|
+
# Get rid of any local edits coming in here, this is only called once at the start
|
274
|
+
# of the program generation run.
|
275
|
+
# No need to pull latest as that will be done when we obtain a lock.
|
276
|
+
@repo.reset_hard
|
277
|
+
@git = Git.new(local: local_var_git_database_dir, remote: @repo)
|
278
|
+
if lsf_publish
|
279
|
+
return if @lock_open
|
280
|
+
Origen.profile 'Obtaining test IDs lock' do
|
281
|
+
until @git.available_to_lock?(@repo)
|
282
|
+
puts
|
283
|
+
puts "Waiting for lock, currently locked by #{@git.lock_user} (the lock will expire in less than #{@git.lock_minutes_remaining} #{'minute'.pluralize(@git.lock_minutes_remaining)} if not released before that)"
|
284
|
+
puts
|
285
|
+
sleep 5
|
286
|
+
end
|
287
|
+
data = {
|
288
|
+
'user' => User.current.name,
|
289
|
+
'expires' => (Time.now + @git.minutes(5)).to_f
|
290
|
+
}
|
291
|
+
@git.write('lock.json', JSON.pretty_generate(data))
|
292
|
+
repo.commit('Obtaining lock')
|
293
|
+
repo.push('origin')
|
294
|
+
end
|
295
|
+
@lock_open = true
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def lsf_shutdown(lsf_publish)
|
300
|
+
if lsf_publish
|
301
|
+
Origen.profile 'Publishing the test IDs store' do
|
302
|
+
data = {
|
303
|
+
'user' => nil,
|
304
|
+
'expires' => nil
|
305
|
+
}
|
306
|
+
@git.write('lock.json', JSON.pretty_generate(data))
|
307
|
+
repo.add # Checkin everything
|
308
|
+
repo.commit('Publishing latest store')
|
309
|
+
repo.push('origin', 'master', force: true)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
246
314
|
## When set to true, all numbers generated will be checked to see if they comply
|
247
315
|
## with the current configuration, and if not they will be re-assigned based on the
|
248
316
|
## current configuration
|
@@ -257,6 +325,24 @@ module TestIds
|
|
257
325
|
# @reallocate_non_compliant = val
|
258
326
|
# end
|
259
327
|
|
328
|
+
# Reset everything related to the TestIds module
|
329
|
+
# only needed for cases where running several targets
|
330
|
+
# back to back, e.g. for regression testing
|
331
|
+
def reset_everything(are_you_sure: false)
|
332
|
+
if are_you_sure
|
333
|
+
@repo = nil # accessor
|
334
|
+
@git = nil # accessor
|
335
|
+
@git_database_dir = nil
|
336
|
+
@git_initialized = nil
|
337
|
+
@configuration = nil
|
338
|
+
@configuration_id = nil
|
339
|
+
@bin_config = nil
|
340
|
+
@softbin_config = nil
|
341
|
+
@number_config = nil
|
342
|
+
@publish = nil
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
260
346
|
private
|
261
347
|
|
262
348
|
def on_origen_shutdown
|
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: 1.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McGinty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -16,14 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.57.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.57.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dentaku
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-inflector
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: origen_testers
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
128
|
- !ruby/object:Gem::Version
|
101
129
|
version: 1.8.11
|
102
130
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
131
|
+
rubygems_version: 3.2.31
|
104
132
|
signing_key:
|
105
133
|
specification_version: 4
|
106
134
|
summary: Origen plugin to assign and track test program bins and test numbers
|