puppetlabs-onceover 5.0.3 → 5.0.5
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/.gitignore +4 -0
- data/.rubocop_todo.yml +35 -15
- data/CHANGELOG.md +398 -3
- data/Gemfile +21 -1
- data/lib/puppetlabs-onceover/cli/plugins.rb +3 -3
- data/lib/puppetlabs-onceover/controlrepo.rb +8 -7
- data/lib/puppetlabs-onceover/rake_tasks.rb +2 -2
- data/lib/puppetlabs-onceover/vendored_modules.rb +29 -32
- data/lib/puppetlabs-onceover/version.rb +1 -1
- data/spec/fixtures/controlrepos/deploy_test/Puppetfile +3 -0
- data/spec/fixtures/controlrepos/deploy_test/a_dir/nested_file.txt +1 -0
- data/spec/fixtures/controlrepos/deploy_test/a_symlink +1 -0
- data/spec/fixtures/controlrepos/deploy_test/environment.conf +1 -0
- data/spec/fixtures/controlrepos/deploy_test/regular_file.txt +1 -0
- data/spec/puppetlabs-onceover/beaker_spec.rb +293 -0
- data/spec/puppetlabs-onceover/class_spec.rb +89 -0
- data/spec/puppetlabs-onceover/cli/run_spec.rb +80 -0
- data/spec/puppetlabs-onceover/cli/show_spec.rb +67 -0
- data/spec/puppetlabs-onceover/cli_spec.rb +79 -0
- data/spec/puppetlabs-onceover/controlrepo_spec.rb +787 -5
- data/spec/puppetlabs-onceover/deploy_spec.rb +246 -0
- data/spec/puppetlabs-onceover/group_spec.rb +121 -0
- data/spec/puppetlabs-onceover/logger_spec.rb +30 -0
- data/spec/puppetlabs-onceover/node_spec.rb +124 -0
- data/spec/puppetlabs-onceover/rake_tasks_spec.rb +179 -0
- data/spec/puppetlabs-onceover/rspec/formatters_spec.rb +361 -0
- data/spec/puppetlabs-onceover/runner_spec.rb +307 -0
- data/spec/puppetlabs-onceover/test_spec.rb +177 -0
- data/spec/puppetlabs-onceover/testconfig_spec.rb +451 -0
- data/spec/puppetlabs-onceover/vendored_modules_spec.rb +293 -0
- data/spec/puppetlabs-onceover/version_spec.rb +10 -0
- data/spec/spec_helper.rb +8 -0
- metadata +23 -2
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/controlrepo' # side effect: defines top-level #logger
|
|
3
|
+
require 'puppetlabs-onceover/test'
|
|
4
|
+
require 'puppetlabs-onceover/rspec/formatters'
|
|
5
|
+
require 'puppetlabs-onceover/runner'
|
|
6
|
+
|
|
7
|
+
describe PuppetlabsOnceover::Runner do
|
|
8
|
+
let(:repo) do
|
|
9
|
+
double(
|
|
10
|
+
'repo',
|
|
11
|
+
tempdir: '/tmp/onceover-runner-spec',
|
|
12
|
+
environmentpath: 'etc/puppetlabs/code/environments',
|
|
13
|
+
hiera_config: nil,
|
|
14
|
+
root: '/tmp/onceover-runner-spec-root'
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def build_config(overrides = {})
|
|
19
|
+
double(
|
|
20
|
+
'config',
|
|
21
|
+
{
|
|
22
|
+
copy_spec_files: nil,
|
|
23
|
+
write_rakefile: nil,
|
|
24
|
+
write_spec_helper: nil,
|
|
25
|
+
write_spec_helper_acceptance: nil,
|
|
26
|
+
spec_tests: [],
|
|
27
|
+
verify_spec_test: nil,
|
|
28
|
+
run_filters: [],
|
|
29
|
+
write_spec_test: nil,
|
|
30
|
+
acceptance_tests: [],
|
|
31
|
+
verify_acceptance_test: nil,
|
|
32
|
+
write_acceptance_tests: nil,
|
|
33
|
+
create_fixtures_symlinks: nil,
|
|
34
|
+
filter_tags: nil,
|
|
35
|
+
fail_fast: false,
|
|
36
|
+
opts: {},
|
|
37
|
+
formatters: []
|
|
38
|
+
}.merge(overrides)
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
let(:config) { build_config }
|
|
43
|
+
|
|
44
|
+
before do
|
|
45
|
+
# Avoid any real filesystem churn from FileUtils calls in #prepare!
|
|
46
|
+
allow(FileUtils).to receive(:rm_rf)
|
|
47
|
+
allow(FileUtils).to receive(:rm_f)
|
|
48
|
+
allow(FileUtils).to receive(:mkdir_p)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#initialize' do
|
|
52
|
+
it 'wraps a single symbol mode into an array' do
|
|
53
|
+
runner = described_class.new(repo, config, :spec)
|
|
54
|
+
expect(runner.instance_variable_get(:@mode)).to eq([:spec])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'accepts an array of modes as-is' do
|
|
58
|
+
runner = described_class.new(repo, config, [:spec, :acceptance])
|
|
59
|
+
expect(runner.instance_variable_get(:@mode)).to eq([:spec, :acceptance])
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'defaults the mode to spec and acceptance' do
|
|
63
|
+
runner = described_class.new(repo, config)
|
|
64
|
+
expect(runner.instance_variable_get(:@mode)).to eq([:spec, :acceptance])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'sets an empty command prefix when BUNDLE_GEMFILE is not set' do
|
|
68
|
+
original = ENV.delete('BUNDLE_GEMFILE')
|
|
69
|
+
runner = described_class.new(repo, config)
|
|
70
|
+
expect(runner.instance_variable_get(:@command_prefix)).to eq('')
|
|
71
|
+
ENV['BUNDLE_GEMFILE'] = original if original
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'sets a bundle exec command prefix when BUNDLE_GEMFILE is set' do
|
|
75
|
+
original = ENV.fetch('BUNDLE_GEMFILE', nil)
|
|
76
|
+
ENV['BUNDLE_GEMFILE'] = 'Gemfile'
|
|
77
|
+
runner = described_class.new(repo, config)
|
|
78
|
+
expect(runner.instance_variable_get(:@command_prefix)).to eq('bundle exec ')
|
|
79
|
+
if original
|
|
80
|
+
ENV['BUNDLE_GEMFILE'] = original
|
|
81
|
+
else
|
|
82
|
+
ENV.delete('BUNDLE_GEMFILE')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe '#prepare!' do
|
|
88
|
+
it 'runs the spec test path when mode includes :spec' do
|
|
89
|
+
runner = described_class.new(repo, config, :spec)
|
|
90
|
+
|
|
91
|
+
expect(config).to receive(:spec_tests).at_least(:once).and_return(['sometest'])
|
|
92
|
+
expect(config).to receive(:verify_spec_test).with(repo, 'sometest')
|
|
93
|
+
expect(PuppetlabsOnceover::Test).to receive(:deduplicate).with(['sometest']).and_return(['sometest'])
|
|
94
|
+
expect(config).to receive(:run_filters).with(['sometest']).and_return(['sometest'])
|
|
95
|
+
expect(config).to receive(:write_spec_test).with("#{repo.tempdir}/spec/classes", 'sometest')
|
|
96
|
+
expect(config).not_to receive(:acceptance_tests)
|
|
97
|
+
|
|
98
|
+
runner.prepare!
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'runs the acceptance test path when mode includes :acceptance' do
|
|
102
|
+
runner = described_class.new(repo, config, :acceptance)
|
|
103
|
+
|
|
104
|
+
expect(config).to receive(:acceptance_tests).at_least(:once).and_return(['sometest'])
|
|
105
|
+
expect(config).to receive(:verify_acceptance_test).with(repo, 'sometest')
|
|
106
|
+
expect(PuppetlabsOnceover::Test).to receive(:deduplicate).with(['sometest']).and_return(['sometest'])
|
|
107
|
+
expect(config).to receive(:run_filters).with(['sometest']).and_return(['sometest'])
|
|
108
|
+
expect(config).to receive(:write_acceptance_tests).with("#{repo.tempdir}/spec/acceptance", ['sometest'])
|
|
109
|
+
expect(config).not_to receive(:spec_tests)
|
|
110
|
+
|
|
111
|
+
runner.prepare!
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'runs neither test path when mode is empty' do
|
|
115
|
+
runner = described_class.new(repo, config, [])
|
|
116
|
+
|
|
117
|
+
expect(config).not_to receive(:spec_tests)
|
|
118
|
+
expect(config).not_to receive(:acceptance_tests)
|
|
119
|
+
|
|
120
|
+
runner.prepare!
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'skips the hiera rewrite when hiera_config is nil' do
|
|
124
|
+
runner = described_class.new(repo, config, [])
|
|
125
|
+
expect(File).not_to receive(:write)
|
|
126
|
+
runner.prepare!
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'rewrites a plain (non-hash) hiera_config setting untouched and writes hiera.yaml' do
|
|
130
|
+
hiera_repo = double(
|
|
131
|
+
'repo',
|
|
132
|
+
tempdir: '/tmp/onceover-runner-spec',
|
|
133
|
+
environmentpath: 'etc/puppetlabs/code/environments',
|
|
134
|
+
hiera_config: { 'version' => 5 },
|
|
135
|
+
root: '/tmp/onceover-runner-spec-root'
|
|
136
|
+
)
|
|
137
|
+
runner = described_class.new(hiera_repo, config, [])
|
|
138
|
+
|
|
139
|
+
expect(File).to receive(:write).with(
|
|
140
|
+
"#{hiera_repo.tempdir}/#{hiera_repo.environmentpath}/production/hiera.yaml",
|
|
141
|
+
{ 'version' => 5 }.to_yaml
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
runner.prepare!
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'rewrites the datadir of a hierarchy hash entry to point at the tempdir' do
|
|
148
|
+
hiera_config = {
|
|
149
|
+
'hierarchy' => { datadir: 'hieradata' }
|
|
150
|
+
}
|
|
151
|
+
hiera_repo = double(
|
|
152
|
+
'repo',
|
|
153
|
+
tempdir: '/tmp/onceover-runner-spec',
|
|
154
|
+
environmentpath: 'etc/puppetlabs/code/environments',
|
|
155
|
+
hiera_config: hiera_config,
|
|
156
|
+
root: '/tmp/onceover-runner-spec-root'
|
|
157
|
+
)
|
|
158
|
+
runner = described_class.new(hiera_repo, config, [])
|
|
159
|
+
|
|
160
|
+
expected_datadir = "#{hiera_repo.tempdir}/#{hiera_repo.environmentpath}/production/hieradata"
|
|
161
|
+
|
|
162
|
+
expect(File).to receive(:write) do |path, contents|
|
|
163
|
+
expect(path).to eq("#{hiera_repo.tempdir}/#{hiera_repo.environmentpath}/production/hiera.yaml")
|
|
164
|
+
expect(contents).to include(expected_datadir)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
runner.prepare!
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'leaves a hash entry without a :datadir key untouched' do
|
|
171
|
+
hiera_config = {
|
|
172
|
+
'hierarchy' => { other_key: 'value' }
|
|
173
|
+
}
|
|
174
|
+
hiera_repo = double(
|
|
175
|
+
'repo',
|
|
176
|
+
tempdir: '/tmp/onceover-runner-spec',
|
|
177
|
+
environmentpath: 'etc/puppetlabs/code/environments',
|
|
178
|
+
hiera_config: hiera_config,
|
|
179
|
+
root: '/tmp/onceover-runner-spec-root'
|
|
180
|
+
)
|
|
181
|
+
runner = described_class.new(hiera_repo, config, [])
|
|
182
|
+
|
|
183
|
+
expect(File).to receive(:write) do |_path, contents|
|
|
184
|
+
expect(contents).not_to include('/tmp/onceover-runner-spec/etc')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
runner.prepare!
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
describe '#run_spec!' do
|
|
192
|
+
let(:backticks_double) do
|
|
193
|
+
double('backticks_runner', run: double('process', join: double('joined', status: double('status', exitstatus: 0))))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
before do
|
|
197
|
+
allow(Backticks::Runner).to receive(:new).and_return(backticks_double)
|
|
198
|
+
allow(Dir).to receive(:chdir).and_yield
|
|
199
|
+
allow($stderr).to receive(:isatty).and_return(false)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'runs rake spec:standalone in standalone mode and exits with the status code' do
|
|
203
|
+
runner = described_class.new(repo, config, :spec)
|
|
204
|
+
logger.level = :info
|
|
205
|
+
|
|
206
|
+
expect(runner).to receive(:exit).with(0)
|
|
207
|
+
runner.run_spec!
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'runs rake parallel_spec when opts[:parallel] is set' do
|
|
211
|
+
parallel_config = build_config(opts: { parallel: true })
|
|
212
|
+
runner = described_class.new(repo, parallel_config, :spec)
|
|
213
|
+
logger.level = :info
|
|
214
|
+
|
|
215
|
+
expect(runner).to receive(:run_command).with(anything, 'rake', 'parallel_spec').and_call_original
|
|
216
|
+
allow(runner).to receive(:exit)
|
|
217
|
+
runner.run_spec!
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it 'skips the RUBYOPT warning-suppression dance when logger level is debug (zero)' do
|
|
221
|
+
runner = described_class.new(repo, config, :spec)
|
|
222
|
+
logger.level = :debug
|
|
223
|
+
|
|
224
|
+
previous = ENV.fetch('RUBYOPT', nil)
|
|
225
|
+
expect(runner).to receive(:exit).with(0)
|
|
226
|
+
runner.run_spec!
|
|
227
|
+
expect(ENV.fetch('RUBYOPT', nil)).to eq(previous)
|
|
228
|
+
logger.level = :info
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'appends filter tags and fail-fast to CI_SPEC_OPTIONS when configured' do
|
|
232
|
+
tagged_config = build_config(filter_tags: ['sometag'], fail_fast: true)
|
|
233
|
+
runner = described_class.new(repo, tagged_config, :spec)
|
|
234
|
+
logger.level = :info
|
|
235
|
+
|
|
236
|
+
allow(runner).to receive(:exit)
|
|
237
|
+
runner.run_spec!
|
|
238
|
+
expect(ENV.fetch('CI_SPEC_OPTIONS', nil)).to include('--tag sometag')
|
|
239
|
+
expect(ENV.fetch('CI_SPEC_OPTIONS', nil)).to include('--fail-fast')
|
|
240
|
+
ENV.delete('CI_SPEC_OPTIONS')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'prints a parallel summary when the parallel formatter is configured' do
|
|
244
|
+
formatter_config = build_config(formatters: ['PuppetlabsOnceoverFormatterParallel'])
|
|
245
|
+
runner = described_class.new(repo, formatter_config, :spec)
|
|
246
|
+
logger.level = :info
|
|
247
|
+
|
|
248
|
+
formatter_double = double('formatter', output_results: nil)
|
|
249
|
+
expect(PuppetlabsOnceoverFormatterParallel).to receive(:new).with($stdout).and_return(formatter_double)
|
|
250
|
+
expect(formatter_double).to receive(:output_results).with("#{repo.tempdir}/parallel")
|
|
251
|
+
|
|
252
|
+
allow(runner).to receive(:exit)
|
|
253
|
+
runner.run_spec!
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
describe '#run_acceptance!' do
|
|
258
|
+
let(:backticks_double) do
|
|
259
|
+
double('backticks_runner', run: double('process', join: double('joined', status: double('status', exitstatus: 1))))
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
before do
|
|
263
|
+
allow(Backticks::Runner).to receive(:new).and_return(backticks_double)
|
|
264
|
+
allow(Dir).to receive(:chdir).and_yield
|
|
265
|
+
allow($stderr).to receive(:isatty).and_return(false)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'warns about deprecation and runs rake acceptance' do
|
|
269
|
+
# NOTE: `result` in the source is assigned only inside the Dir.chdir
|
|
270
|
+
# block and then read again after the block returns -- that's normal
|
|
271
|
+
# Ruby block-local scoping, so `result` is actually undefined at the
|
|
272
|
+
# `exit result.status.exitstatus` line and this method always raises
|
|
273
|
+
# NameError there in real usage. That's a pre-existing bug in
|
|
274
|
+
# lib/puppetlabs-onceover/runner.rb, not something we can cover
|
|
275
|
+
# without changing production behavior, so we assert the crash
|
|
276
|
+
# instead of the (unreachable) exit call.
|
|
277
|
+
runner = described_class.new(repo, config, :acceptance)
|
|
278
|
+
|
|
279
|
+
expect(runner).to receive(:warn).with(/DEPRECATION/)
|
|
280
|
+
expect { runner.run_acceptance! }.to raise_error(NameError, /result/)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
describe '#run_command' do
|
|
285
|
+
it 'sets STDERR raw when a tty and cooked afterwards' do
|
|
286
|
+
runner = described_class.new(repo, config, :spec)
|
|
287
|
+
backticks_double = double('backticks_runner', run: double('process', join: double('joined')))
|
|
288
|
+
allow(Backticks::Runner).to receive(:new).and_return(backticks_double)
|
|
289
|
+
allow($stderr).to receive(:isatty).and_return(true)
|
|
290
|
+
expect($stderr).to receive(:raw!)
|
|
291
|
+
expect($stderr).to receive(:cooked!)
|
|
292
|
+
|
|
293
|
+
runner.run_command('rake', 'spec:standalone')
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it 'does not touch STDERR raw/cooked state when not a tty' do
|
|
297
|
+
runner = described_class.new(repo, config, :spec)
|
|
298
|
+
backticks_double = double('backticks_runner', run: double('process', join: double('joined')))
|
|
299
|
+
allow(Backticks::Runner).to receive(:new).and_return(backticks_double)
|
|
300
|
+
allow($stderr).to receive(:isatty).and_return(false)
|
|
301
|
+
expect($stderr).not_to receive(:raw!)
|
|
302
|
+
expect($stderr).not_to receive(:cooked!)
|
|
303
|
+
|
|
304
|
+
runner.run_command('rake', 'spec:standalone')
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/test'
|
|
3
|
+
require 'puppetlabs-onceover/class'
|
|
4
|
+
require 'puppetlabs-onceover/node'
|
|
5
|
+
require 'puppetlabs-onceover/group'
|
|
6
|
+
require 'puppetlabs-onceover/testconfig'
|
|
7
|
+
require 'puppetlabs-onceover/controlrepo'
|
|
8
|
+
|
|
9
|
+
describe "PuppetlabsOnceover::Test" do
|
|
10
|
+
before(:each) do
|
|
11
|
+
PuppetlabsOnceover::Class.class_variable_set(:@@all, [])
|
|
12
|
+
PuppetlabsOnceover::Node.class_variable_set(:@@all, [])
|
|
13
|
+
PuppetlabsOnceover::Group.class_variable_set(:@@all, [])
|
|
14
|
+
PuppetlabsOnceover::Test.class_variable_set(:@@all, [])
|
|
15
|
+
logger.level = :fatal
|
|
16
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:node_a) { PuppetlabsOnceover::Node.new('node_a') }
|
|
20
|
+
let(:node_b) { PuppetlabsOnceover::Node.new('node_b') }
|
|
21
|
+
let(:class_a) { PuppetlabsOnceover::Class.new('role::a') }
|
|
22
|
+
let(:class_b) { PuppetlabsOnceover::Class.new('role::b') }
|
|
23
|
+
|
|
24
|
+
describe "#initialize" do
|
|
25
|
+
it "merges in the default test_config (check_idempotency/runs_before_idempotency)" do
|
|
26
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
27
|
+
expect(test.test_config['check_idempotency']).to eq(true)
|
|
28
|
+
expect(test.test_config['runs_before_idempotency']).to eq(1)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "lets explicit test_config values override the defaults" do
|
|
32
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, { 'check_idempotency' => false })
|
|
33
|
+
expect(test.test_config['check_idempotency']).to eq(false)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "removes 'classes' from the stored test_config" do
|
|
37
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, { 'classes' => 'whatever' })
|
|
38
|
+
expect(test.test_config).not_to have_key('classes')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "normalizes a single tag string into an array" do
|
|
42
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, { 'tags' => 'sometag' })
|
|
43
|
+
expect(test.tags).to eq(['sometag'])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "leaves an array of tags as-is" do
|
|
47
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, { 'tags' => %w[a b] })
|
|
48
|
+
expect(test.tags).to eq(%w[a b])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "defaults tags to an empty array when absent" do
|
|
52
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
53
|
+
expect(test.tags).to eq([])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "resolving the 'on_this' (node) argument" do
|
|
57
|
+
it "accepts a group name and expands it to its member nodes" do
|
|
58
|
+
PuppetlabsOnceover::Group.new('nodegroup', [node_a, node_b])
|
|
59
|
+
test = PuppetlabsOnceover::Test.new('nodegroup', class_a, {})
|
|
60
|
+
expect(test.nodes).to eq([node_a, node_b])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "accepts a plain node name" do
|
|
64
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
65
|
+
expect(test.nodes).to eq([node_a])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "raises when the node/group cannot be found" do
|
|
69
|
+
expect do
|
|
70
|
+
PuppetlabsOnceover::Test.new('no_such_node_or_group', class_a, {})
|
|
71
|
+
end.to raise_error(RuntimeError, /was not found in the list of nodes or groups/)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "resolving the 'test_this' (classes) argument" do
|
|
76
|
+
it "accepts a group name and expands it to its member classes" do
|
|
77
|
+
PuppetlabsOnceover::Group.new('classgroup', [class_a, class_b])
|
|
78
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, 'classgroup', {})
|
|
79
|
+
expect(test.classes).to eq([class_a, class_b])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "accepts a plain class name" do
|
|
83
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a.name, {})
|
|
84
|
+
expect(test.classes).to eq([class_a])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "raises when given a string that matches neither a class nor a group" do
|
|
88
|
+
expect do
|
|
89
|
+
PuppetlabsOnceover::Test.new(node_a.name, 'no_such_class_or_group', {})
|
|
90
|
+
end.to raise_error(RuntimeError, /was not found in the list of classes or groups/)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "accepts a subtractive include/exclude hash" do
|
|
94
|
+
PuppetlabsOnceover::Group.new('all_classes', [class_a, class_b])
|
|
95
|
+
PuppetlabsOnceover::Group.new('excluded', [class_b])
|
|
96
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, { 'include' => 'all_classes', 'exclude' => 'excluded' }, {})
|
|
97
|
+
expect(test.classes).to eq([class_a])
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "accepts a Class object directly" do
|
|
101
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
102
|
+
expect(test.classes).to eq([class_a])
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "#eql?" do
|
|
108
|
+
it "is true when both nodes and classes match once sorted" do
|
|
109
|
+
t1 = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
110
|
+
t2 = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
111
|
+
expect(t1.eql?(t2)).to eq(true)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "is false when the classes differ" do
|
|
115
|
+
t1 = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
116
|
+
t2 = PuppetlabsOnceover::Test.new(node_a.name, class_b, {})
|
|
117
|
+
expect(t1.eql?(t2)).to eq(false)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe "#to_s" do
|
|
122
|
+
it "uses the singular class and node name when there is only one of each" do
|
|
123
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
124
|
+
expect(test.to_s).to eq("role__a_on_node_a")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "summarizes as N_classes when there are multiple classes" do
|
|
128
|
+
PuppetlabsOnceover::Group.new('classgroup', [class_a, class_b])
|
|
129
|
+
test = PuppetlabsOnceover::Test.new(node_a.name, 'classgroup', {})
|
|
130
|
+
expect(test.to_s).to eq("2_classes_on_node_a")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "summarizes as N_nodes when there are multiple nodes" do
|
|
134
|
+
PuppetlabsOnceover::Group.new('nodegroup', [node_a, node_b])
|
|
135
|
+
test = PuppetlabsOnceover::Test.new('nodegroup', class_a, {})
|
|
136
|
+
expect(test.to_s).to eq("role__a_on_2_nodes")
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe ".deduplicate" do
|
|
141
|
+
it "merges duplicate node/class combinations into a single test, keeping non-default config" do
|
|
142
|
+
t1 = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
143
|
+
t2 = PuppetlabsOnceover::Test.new(node_a.name, class_a, { 'check_idempotency' => false })
|
|
144
|
+
|
|
145
|
+
deduped = PuppetlabsOnceover::Test.deduplicate([t1, t2])
|
|
146
|
+
expect(deduped.length).to eq(1)
|
|
147
|
+
expect(deduped.first.test_config['check_idempotency']).to eq(false)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "leaves distinct node/class combinations as separate tests" do
|
|
151
|
+
t1 = PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
152
|
+
t2 = PuppetlabsOnceover::Test.new(node_b.name, class_b, {})
|
|
153
|
+
|
|
154
|
+
deduped = PuppetlabsOnceover::Test.deduplicate([t1, t2])
|
|
155
|
+
expect(deduped.length).to eq(2)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "handles tests with multiple nodes/classes by expanding every combination" do
|
|
159
|
+
PuppetlabsOnceover::Group.new('nodegroup', [node_a, node_b])
|
|
160
|
+
PuppetlabsOnceover::Group.new('classgroup', [class_a, class_b])
|
|
161
|
+
t1 = PuppetlabsOnceover::Test.new('nodegroup', 'classgroup', {})
|
|
162
|
+
|
|
163
|
+
deduped = PuppetlabsOnceover::Test.deduplicate([t1])
|
|
164
|
+
# 2 nodes x 2 classes = 4 distinct combinations
|
|
165
|
+
expect(deduped.length).to eq(4)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe ".all" do
|
|
170
|
+
# Unlike Class/Node/Group, Test#initialize never appends `self` to @@all,
|
|
171
|
+
# so .all is always empty in practice -- documenting actual behavior here.
|
|
172
|
+
it "returns the (always empty) @@all class variable, since #initialize never appends to it" do
|
|
173
|
+
PuppetlabsOnceover::Test.new(node_a.name, class_a, {})
|
|
174
|
+
expect(PuppetlabsOnceover::Test.all).to eq([])
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|