test-kitchen 1.3.1 → 1.4.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +2 -0
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +45 -0
  5. data/Rakefile +15 -0
  6. data/features/kitchen_action_commands.feature +12 -9
  7. data/features/kitchen_defaults.feature +38 -0
  8. data/features/kitchen_init_command.feature +0 -1
  9. data/features/kitchen_list_command.feature +2 -2
  10. data/features/kitchen_login_command.feature +7 -1
  11. data/features/kitchen_test_command.feature +4 -4
  12. data/lib/kitchen.rb +40 -11
  13. data/lib/kitchen/cli.rb +38 -22
  14. data/lib/kitchen/command/list.rb +5 -2
  15. data/lib/kitchen/config.rb +45 -18
  16. data/lib/kitchen/configurable.rb +137 -1
  17. data/lib/kitchen/data_munger.rb +248 -17
  18. data/lib/kitchen/driver.rb +1 -1
  19. data/lib/kitchen/driver/base.rb +1 -83
  20. data/lib/kitchen/driver/dummy.rb +0 -5
  21. data/lib/kitchen/driver/ssh_base.rb +177 -22
  22. data/lib/kitchen/instance.rb +140 -20
  23. data/lib/kitchen/logger.rb +43 -8
  24. data/lib/kitchen/login_command.rb +14 -5
  25. data/lib/kitchen/platform.rb +19 -0
  26. data/lib/kitchen/provisioner.rb +5 -3
  27. data/lib/kitchen/provisioner/base.rb +46 -48
  28. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -0
  29. data/lib/kitchen/provisioner/chef_base.rb +179 -286
  30. data/lib/kitchen/provisioner/chef_solo.rb +11 -5
  31. data/lib/kitchen/provisioner/chef_zero.rb +108 -94
  32. data/lib/kitchen/provisioner/dummy.rb +47 -0
  33. data/lib/kitchen/provisioner/shell.rb +45 -12
  34. data/lib/kitchen/rake_tasks.rb +1 -1
  35. data/lib/kitchen/ssh.rb +1 -1
  36. data/lib/kitchen/thor_tasks.rb +1 -1
  37. data/lib/kitchen/transport.rb +54 -0
  38. data/lib/kitchen/transport/base.rb +146 -0
  39. data/lib/kitchen/transport/dummy.rb +75 -0
  40. data/lib/kitchen/transport/ssh.rb +325 -0
  41. data/lib/kitchen/transport/winrm.rb +508 -0
  42. data/lib/kitchen/transport/winrm/command_executor.rb +188 -0
  43. data/lib/kitchen/transport/winrm/file_transporter.rb +454 -0
  44. data/lib/kitchen/transport/winrm/logging.rb +50 -0
  45. data/lib/kitchen/transport/winrm/template.rb +74 -0
  46. data/lib/kitchen/transport/winrm/tmp_zip.rb +187 -0
  47. data/lib/kitchen/verifier.rb +55 -0
  48. data/lib/kitchen/verifier/base.rb +191 -0
  49. data/lib/kitchen/verifier/busser.rb +266 -0
  50. data/lib/kitchen/verifier/dummy.rb +75 -0
  51. data/lib/kitchen/version.rb +1 -1
  52. data/spec/kitchen/cli_spec.rb +56 -0
  53. data/spec/kitchen/config_spec.rb +61 -20
  54. data/spec/kitchen/configurable_spec.rb +327 -1
  55. data/spec/kitchen/data_munger_spec.rb +777 -14
  56. data/spec/kitchen/driver/base_spec.rb +7 -38
  57. data/spec/kitchen/driver/dummy_spec.rb +0 -29
  58. data/spec/kitchen/driver/ssh_base_spec.rb +580 -236
  59. data/spec/kitchen/driver_spec.rb +1 -0
  60. data/spec/kitchen/instance_spec.rb +383 -83
  61. data/spec/kitchen/login_command_spec.rb +29 -10
  62. data/spec/kitchen/platform_spec.rb +58 -2
  63. data/spec/kitchen/provisioner/base_spec.rb +170 -18
  64. data/spec/kitchen/provisioner/chef_base_spec.rb +454 -104
  65. data/spec/kitchen/provisioner/chef_solo_spec.rb +307 -104
  66. data/spec/kitchen/provisioner/chef_zero_spec.rb +561 -230
  67. data/spec/kitchen/provisioner/dummy_spec.rb +91 -0
  68. data/spec/kitchen/provisioner/shell_spec.rb +158 -56
  69. data/spec/kitchen/provisioner_spec.rb +37 -0
  70. data/spec/kitchen/ssh_spec.rb +19 -19
  71. data/spec/kitchen/transport/base_spec.rb +89 -0
  72. data/spec/kitchen/transport/ssh_spec.rb +1147 -0
  73. data/spec/kitchen/transport/winrm/command_executor_spec.rb +400 -0
  74. data/spec/kitchen/transport/winrm/file_transporter_spec.rb +876 -0
  75. data/spec/kitchen/transport/winrm/logging_spec.rb +92 -0
  76. data/spec/kitchen/transport/winrm/template_spec.rb +51 -0
  77. data/spec/kitchen/transport/winrm/tmp_zip_spec.rb +132 -0
  78. data/spec/kitchen/transport/winrm_spec.rb +1069 -0
  79. data/spec/kitchen/transport_spec.rb +112 -0
  80. data/spec/kitchen/verifier/base_spec.rb +310 -0
  81. data/spec/kitchen/verifier/busser_spec.rb +540 -0
  82. data/spec/kitchen/verifier/dummy_spec.rb +91 -0
  83. data/spec/kitchen/verifier_spec.rb +120 -0
  84. data/spec/kitchen_spec.rb +7 -0
  85. data/spec/spec_helper.rb +8 -0
  86. data/spec/support/powershell_max_size_spec.rb +40 -0
  87. data/support/busser_install_command.ps1 +14 -0
  88. data/support/busser_install_command.sh +15 -0
  89. data/support/check_files.ps1.erb +48 -0
  90. data/support/chef_base_init_command.ps1 +18 -0
  91. data/support/chef_base_init_command.sh +2 -0
  92. data/support/chef_base_install_command.ps1 +76 -0
  93. data/support/chef_base_install_command.sh +137 -0
  94. data/support/chef_zero_prepare_command_legacy.ps1 +9 -0
  95. data/support/chef_zero_prepare_command_legacy.sh +10 -0
  96. data/support/decode_files.ps1.erb +61 -0
  97. data/test-kitchen.gemspec +2 -0
  98. metadata +97 -8
  99. data/lib/kitchen/busser.rb +0 -316
  100. data/spec/kitchen/busser_spec.rb +0 -490
  101. data/support/chef_helpers.sh +0 -16
@@ -0,0 +1,112 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Matt Wrock (<matt@mattwrock.com>)
4
+ #
5
+ # Copyright (C) 2014, Matt Wrock
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../spec_helper"
20
+
21
+ require "kitchen/configurable"
22
+ require "kitchen/errors"
23
+ require "kitchen/logging"
24
+ require "kitchen/transport"
25
+ require "kitchen/transport/base"
26
+
27
+ module Kitchen
28
+
29
+ module Transport
30
+
31
+ class Coolbeans < Kitchen::Transport::Base
32
+ end
33
+
34
+ class ItDepends < Kitchen::Transport::Base
35
+
36
+ attr_reader :verify_call_count
37
+
38
+ def initialize(config = {})
39
+ @verify_call_count = 0
40
+ super
41
+ end
42
+
43
+ def verify_dependencies
44
+ @verify_call_count += 1
45
+ end
46
+ end
47
+
48
+ class UnstableDepends < Kitchen::Transport::Base
49
+
50
+ def verify_dependencies
51
+ raise UserError, "Oh noes, you don't have software!"
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe Kitchen::Transport do
58
+
59
+ describe ".for_plugin" do
60
+
61
+ before do
62
+ Kitchen::Transport.stubs(:require).returns(true)
63
+ end
64
+
65
+ it "returns a transport object of the correct class" do
66
+ transport = Kitchen::Transport.for_plugin("coolbeans", {})
67
+
68
+ transport.must_be_kind_of Kitchen::Transport::Coolbeans
69
+ end
70
+
71
+ it "returns a transport initialized with its config" do
72
+ transport = Kitchen::Transport.for_plugin("coolbeans", :foo => "bar")
73
+
74
+ transport[:foo].must_equal "bar"
75
+ end
76
+
77
+ it "calls #verify_dependencies on the transport object" do
78
+ transport = Kitchen::Transport.for_plugin("it_depends", {})
79
+
80
+ transport.verify_call_count.must_equal 1
81
+ end
82
+
83
+ it "calls #verify_dependencies once per transport require" do
84
+ Kitchen::Transport.stubs(:require).returns(true, false)
85
+ transport1 = Kitchen::Transport.for_plugin("it_depends", {})
86
+ transport1.verify_call_count.must_equal 1
87
+ transport2 = Kitchen::Transport.for_plugin("it_depends", {})
88
+
89
+ transport2.verify_call_count.must_equal 0
90
+ end
91
+
92
+ it "raises ClientError if the transport could not be required" do
93
+ Kitchen::Transport.stubs(:require).raises(LoadError)
94
+
95
+ proc { Kitchen::Transport.for_plugin("coolbeans", {}) }.
96
+ must_raise Kitchen::ClientError
97
+ end
98
+
99
+ it "raises ClientError if the transport's class constant was not found" do
100
+ # pretend require worked
101
+ Kitchen::Transport.stubs(:require).returns(true)
102
+
103
+ proc { Kitchen::Transport.for_plugin("nope", {}) }.
104
+ must_raise Kitchen::ClientError
105
+ end
106
+
107
+ it "raises UserError if #verify_dependencies failes" do
108
+ proc { Kitchen::Transport.for_plugin("unstable_depends", {}) }.
109
+ must_raise Kitchen::UserError
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,310 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2015, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../../spec_helper"
20
+
21
+ require "logger"
22
+ require "stringio"
23
+
24
+ require "kitchen/verifier/base"
25
+ require "kitchen/transport/base"
26
+
27
+ module Kitchen
28
+
29
+ module Verifier
30
+
31
+ class TestingDummy < Kitchen::Verifier::Base
32
+
33
+ attr_reader :called_create_sandbox, :called_cleanup_sandbox
34
+
35
+ def install_command
36
+ "install"
37
+ end
38
+
39
+ def init_command
40
+ "init"
41
+ end
42
+
43
+ def prepare_command
44
+ "prepare"
45
+ end
46
+
47
+ def run_command
48
+ "run"
49
+ end
50
+
51
+ def create_sandbox
52
+ @called_create_sandbox = true
53
+ end
54
+
55
+ def cleanup_sandbox
56
+ @called_cleanup_sandbox = true
57
+ end
58
+
59
+ def sandbox_path
60
+ "/tmp/sandbox"
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ describe Kitchen::Verifier::Base do
67
+
68
+ let(:logged_output) { StringIO.new }
69
+ let(:logger) { Logger.new(logged_output) }
70
+ let(:platform) { stub(:os_type => nil, :shell_type => nil) }
71
+ let(:suite) { stub(:name => "germany") }
72
+ let(:config) { Hash.new }
73
+
74
+ let(:transport) do
75
+ t = mock("transport")
76
+ t.responds_like_instance_of(Kitchen::Transport::Base)
77
+ t
78
+ end
79
+
80
+ let(:instance) do
81
+ stub(
82
+ :name => "coolbeans",
83
+ :to_str => "instance",
84
+ :logger => logger,
85
+ :platform => platform,
86
+ :suite => suite,
87
+ :transport => transport
88
+ )
89
+ end
90
+
91
+ let(:verifier) do
92
+ Kitchen::Verifier::Base.new(config).finalize_config!(instance)
93
+ end
94
+
95
+ describe "configuration" do
96
+
97
+ describe "for unix operating systems" do
98
+
99
+ before { platform.stubs(:os_type).returns("unix") }
100
+
101
+ it ":sudo defaults to true" do
102
+ verifier[:sudo].must_equal true
103
+ end
104
+
105
+ it ":root_path defaults to '/tmp/verifier'" do
106
+ verifier[:root_path].must_equal "/tmp/verifier"
107
+ end
108
+ end
109
+
110
+ describe "for windows operating systems" do
111
+
112
+ before { platform.stubs(:os_type).returns("windows") }
113
+
114
+ it ":sudo defaults to nil" do
115
+ verifier[:sudo].must_equal nil
116
+ end
117
+
118
+ it ":root_path defaults to $env:TEMP\\verifier" do
119
+ verifier[:root_path].must_equal "$env:TEMP\\verifier"
120
+ end
121
+ end
122
+
123
+ it ":suite_name defaults to the passed in suite name" do
124
+ verifier[:suite_name].must_equal "germany"
125
+ end
126
+
127
+ it ":http_proxy defaults to nil" do
128
+ verifier[:http_proxy].must_equal nil
129
+ end
130
+
131
+ it ":http_proxys defaults to nil" do
132
+ verifier[:https_proxy].must_equal nil
133
+ end
134
+ end
135
+
136
+ describe "#call" do
137
+
138
+ let(:state) { Hash.new }
139
+ let(:cmd) { verifier.call(state) }
140
+
141
+ let(:connection) do
142
+ c = mock("transport_connection")
143
+ c.responds_like_instance_of(Kitchen::Transport::Base::Connection)
144
+ c
145
+ end
146
+
147
+ let(:verifier) do
148
+ Kitchen::Verifier::TestingDummy.new(config).finalize_config!(instance)
149
+ end
150
+
151
+ before do
152
+ FakeFS.activate!
153
+ FileUtils.mkdir_p(File.join(verifier.sandbox_path, "stuff"))
154
+ transport.stubs(:connection).yields(connection)
155
+ connection.stubs(:execute)
156
+ connection.stubs(:upload)
157
+ end
158
+
159
+ after do
160
+ FakeFS.deactivate!
161
+ FakeFS::FileSystem.clear
162
+ end
163
+
164
+ it "creates the sandbox" do
165
+ verifier.expects(:create_sandbox)
166
+
167
+ cmd
168
+ end
169
+
170
+ it "ensures that the sandbox is cleanup up" do
171
+ transport.stubs(:connection).raises
172
+ verifier.expects(:cleanup_sandbox)
173
+
174
+ begin
175
+ cmd
176
+ rescue # rubocop:disable Lint/HandleExceptions
177
+ end
178
+ end
179
+
180
+ it "yields a connection given the state" do
181
+ state[:a] = "b"
182
+ transport.expects(:connection).with(state).yields(connection)
183
+
184
+ cmd
185
+ end
186
+
187
+ it "invokes the verifier commands over the transport" do
188
+ order = sequence("order")
189
+ connection.expects(:execute).with("install").in_sequence(order)
190
+ connection.expects(:execute).with("init").in_sequence(order)
191
+ connection.expects(:execute).with("prepare").in_sequence(order)
192
+ connection.expects(:execute).with("run").in_sequence(order)
193
+
194
+ cmd
195
+ end
196
+
197
+ it "logs to info" do
198
+ cmd
199
+
200
+ logged_output.string.
201
+ must_match(/INFO -- : Transferring files to instance$/)
202
+ end
203
+
204
+ it "uploads sandbox files" do
205
+ connection.expects(:upload).with(["/tmp/sandbox/stuff"], "/tmp/verifier")
206
+
207
+ cmd
208
+ end
209
+
210
+ it "logs to debug" do
211
+ cmd
212
+
213
+ logged_output.string.must_match(/DEBUG -- : Transfer complete$/)
214
+ end
215
+
216
+ it "raises an ActionFailed on transfer when TransportFailed is raised" do
217
+ connection.stubs(:upload).
218
+ raises(Kitchen::Transport::TransportFailed.new("dang"))
219
+
220
+ proc { cmd }.must_raise Kitchen::ActionFailed
221
+ end
222
+
223
+ it "raises an ActionFailed on execute when TransportFailed is raised" do
224
+ connection.stubs(:execute).
225
+ raises(Kitchen::Transport::TransportFailed.new("dang"))
226
+
227
+ proc { cmd }.must_raise Kitchen::ActionFailed
228
+ end
229
+ end
230
+
231
+ [:init_command, :install_command, :prepare_command, :run_command].each do |cmd|
232
+
233
+ it "has a #{cmd} method" do
234
+ verifier.public_send(cmd).must_be_nil
235
+ end
236
+ end
237
+
238
+ describe "sandbox" do
239
+
240
+ after do
241
+ begin
242
+ verifier.cleanup_sandbox
243
+ rescue # rubocop:disable Lint/HandleExceptions
244
+ end
245
+ end
246
+
247
+ it "raises ClientError if #sandbox_path is called before #create_sandbox" do
248
+ proc { verifier.sandbox_path }.must_raise Kitchen::ClientError
249
+ end
250
+
251
+ it "#create_sandbox creates a temporary directory" do
252
+ verifier.create_sandbox
253
+
254
+ File.directory?(verifier.sandbox_path).must_equal true
255
+ format("%o", File.stat(verifier.sandbox_path).mode)[1, 4].
256
+ must_equal "0755"
257
+ end
258
+
259
+ it "#create_sandbox logs an info message" do
260
+ verifier.create_sandbox
261
+
262
+ logged_output.string.must_match info_line("Preparing files for transfer")
263
+ end
264
+
265
+ it "#create_sandbox logs a debug message" do
266
+ verifier.create_sandbox
267
+
268
+ logged_output.string.
269
+ must_match debug_line_starting_with("Creating local sandbox in ")
270
+ end
271
+
272
+ it "#cleanup_sandbox deletes the sandbox directory" do
273
+ verifier.create_sandbox
274
+ verifier.cleanup_sandbox
275
+
276
+ File.directory?(verifier.sandbox_path).must_equal false
277
+ end
278
+
279
+ it "#cleanup_sandbox logs a debug message" do
280
+ verifier.create_sandbox
281
+ verifier.cleanup_sandbox
282
+
283
+ logged_output.string.
284
+ must_match debug_line_starting_with("Cleaning up local sandbox in ")
285
+ end
286
+
287
+ def info_line(msg)
288
+ %r{^I, .* : #{Regexp.escape(msg)}$}
289
+ end
290
+
291
+ def debug_line_starting_with(msg)
292
+ %r{^D, .* : #{Regexp.escape(msg)}}
293
+ end
294
+ end
295
+
296
+ describe "#sudo" do
297
+
298
+ it "if :sudo is set, prepend sudo command" do
299
+ config[:sudo] = true
300
+
301
+ verifier.send(:sudo, "wakka").must_equal("sudo -E wakka")
302
+ end
303
+
304
+ it "if :sudo is falsy, do not include sudo command" do
305
+ config[:sudo] = false
306
+
307
+ verifier.send(:sudo, "wakka").must_equal("wakka")
308
+ end
309
+ end
310
+ end
@@ -0,0 +1,540 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2014, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../../spec_helper"
20
+
21
+ require "kitchen"
22
+ require "kitchen/verifier/busser"
23
+
24
+ describe Kitchen::Verifier::Busser do
25
+
26
+ let(:logged_output) { StringIO.new }
27
+ let(:logger) { Logger.new(logged_output) }
28
+ let(:config) { Hash.new }
29
+ let(:platform) { stub(:os_type => nil, :shell_type => nil) }
30
+ let(:suite) { stub(:name => "germany") }
31
+
32
+ let(:instance) do
33
+ stub(
34
+ :name => "coolbeans",
35
+ :logger => logger,
36
+ :platform => platform,
37
+ :suite => suite,
38
+ :to_str => "instance"
39
+ )
40
+ end
41
+
42
+ let(:verifier) do
43
+ Kitchen::Verifier::Busser.new(config).finalize_config!(instance)
44
+ end
45
+
46
+ let(:files) do
47
+ {
48
+ "mondospec/charlie" => {
49
+ :content => "charlie",
50
+ :perms => "0764"
51
+ },
52
+ "minispec/beta" => {
53
+ :content => "beta",
54
+ :perms => "0644"
55
+ },
56
+ "abba/alpha" => {
57
+ :content => "alpha",
58
+ :perms => "0440"
59
+ }
60
+ }
61
+ end
62
+
63
+ let(:helper_files) do
64
+ {
65
+ "minispec/spec_helper" => {
66
+ :content => "helping",
67
+ :perms => "0644"
68
+ },
69
+ "abba/common" => {
70
+ :content => "yeppers",
71
+ :perms => "0664"
72
+ }
73
+ }
74
+ end
75
+
76
+ before do
77
+ @root = Dir.mktmpdir
78
+ config[:test_base_path] = @root
79
+ end
80
+
81
+ after do
82
+ FileUtils.remove_entry(@root)
83
+ end
84
+
85
+ # TODO: deal with this:
86
+ # it "raises a UserError if the suite name is 'helper'" do
87
+ # proc {
88
+ # Kitchen::Busser.new("helper", config)
89
+ # }.must_raise Kitchen::UserError
90
+ # end
91
+
92
+ describe "configuration" do
93
+
94
+ describe "for unix operating systems" do
95
+
96
+ before { platform.stubs(:os_type).returns("unix") }
97
+
98
+ it ":ruby_bindir defaults the an Omnibus Chef installation" do
99
+ verifier[:ruby_bindir].must_equal "/opt/chef/embedded/bin"
100
+ end
101
+
102
+ it ":busser_bin defaults to a binstub under :root_path" do
103
+ config[:root_path] = "/beep"
104
+
105
+ verifier[:busser_bin].must_equal "/beep/bin/busser"
106
+ end
107
+ end
108
+
109
+ describe "for windows operating systems" do
110
+
111
+ before { platform.stubs(:os_type).returns("windows") }
112
+
113
+ it ":ruby_bindir defaults the an Omnibus Chef installation" do
114
+ verifier[:ruby_bindir].
115
+ must_equal "$env:systemdrive\\opscode\\chef\\embedded\\bin"
116
+ end
117
+
118
+ it ":busser_bin defaults to a binstub under :root_path" do
119
+ config[:root_path] = "\\beep"
120
+
121
+ verifier[:busser_bin].must_equal "\\beep\\bin\\busser.bat"
122
+ end
123
+ end
124
+
125
+ it ":version defaults to 'busser'" do
126
+ verifier[:version].must_equal "busser"
127
+ end
128
+ end
129
+
130
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
131
+ def self.common_bourne_variable_specs
132
+ it "uses bourne shell" do
133
+ cmd.must_match(/\Ash -c '$/)
134
+ cmd.must_match(/'\Z/)
135
+ end
136
+
137
+ it "ends with a single quote" do
138
+ cmd.must_match(/'\Z/)
139
+ end
140
+
141
+ it "sets the BUSSER_ROOT environment variable" do
142
+ cmd.must_match regexify(%{BUSSER_ROOT="/r"; export BUSSER_ROOT})
143
+ end
144
+
145
+ it "sets the GEM_HOME environment variable" do
146
+ cmd.must_match regexify(%{GEM_HOME="/r/gems"; export GEM_HOME})
147
+ end
148
+
149
+ it "sets the GEM_PATH environment variable" do
150
+ cmd.must_match regexify(%{GEM_PATH="/r/gems"; export GEM_PATH})
151
+ end
152
+
153
+ it "sets the GEM_CACHE environment variable" do
154
+ cmd.must_match regexify(%{GEM_CACHE="/r/gems/cache"; export GEM_CACHE})
155
+ end
156
+ end
157
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
158
+
159
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
160
+ def self.common_powershell_variable_specs
161
+ it "sets the BUSSER_ROOT environment variable" do
162
+ cmd.must_match regexify(%{$env:BUSSER_ROOT = "\\r"})
163
+ end
164
+
165
+ it "sets the GEM_HOME environment variable" do
166
+ cmd.must_match regexify(%{$env:GEM_HOME = "\\r\\gems"})
167
+ end
168
+
169
+ it "sets the GEM_PATH environment variable" do
170
+ cmd.must_match regexify(%{$env:GEM_PATH = "\\r\\gems"})
171
+ end
172
+
173
+ it "sets the GEM_CACHE environment variable" do
174
+ cmd.must_match regexify(%{$env:GEM_CACHE = "\\r\\gems\\cache"})
175
+ end
176
+ end
177
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
178
+
179
+ describe "#install_command" do
180
+
181
+ let(:cmd) { verifier.install_command }
182
+
183
+ describe "with no suite test files" do
184
+
185
+ describe "for bourne shells" do
186
+
187
+ before { platform.stubs(:shell_type).returns("bourne") }
188
+
189
+ it "returns nil" do
190
+ cmd.must_equal nil
191
+ end
192
+ end
193
+
194
+ describe "for powershell shells on windows os types" do
195
+
196
+ before do
197
+ platform.stubs(:shell_type).returns("powershell")
198
+ platform.stubs(:os_type).returns("windows")
199
+ end
200
+
201
+ it "returns nil" do
202
+ cmd.must_equal nil
203
+ end
204
+ end
205
+ end
206
+
207
+ describe "with suite test files" do
208
+
209
+ describe "for bourne shells" do
210
+
211
+ before do
212
+ platform.stubs(:shell_type).returns("bourne")
213
+ create_test_files
214
+ config[:ruby_bindir] = "/rbd"
215
+ config[:root_path] = "/r"
216
+ end
217
+
218
+ common_bourne_variable_specs
219
+
220
+ it "sets path to ruby command" do
221
+ cmd.must_match regexify(%{ruby="/rbd/ruby"})
222
+ end
223
+
224
+ it "sets path to gem command" do
225
+ cmd.must_match regexify(%{gem="/rbd/gem"})
226
+ end
227
+
228
+ it "sets version for busser" do
229
+ config[:version] = "the_best"
230
+
231
+ cmd.must_match regexify(%{version="the_best"})
232
+ end
233
+
234
+ it "sets gem install arguments" do
235
+ cmd.must_match regexify(
236
+ %{gem_install_args="busser --no-rdoc --no-ri"})
237
+ end
238
+
239
+ it "prepends sudo for busser binstub command when :sudo is set" do
240
+ cmd.must_match regexify(%{busser="sudo -E /r/bin/busser"})
241
+ end
242
+
243
+ it "does not sudo for busser binstub command when :sudo is falsey" do
244
+ config[:sudo] = false
245
+
246
+ cmd.must_match regexify(%{busser="/r/bin/busser"})
247
+ end
248
+
249
+ it "sets the busser plugins list" do
250
+ cmd.must_match regexify(
251
+ %{plugins="busser-abba busser-minispec busser-mondospec"})
252
+ end
253
+ end
254
+
255
+ describe "for powershell shells on windows os types" do
256
+
257
+ before do
258
+ platform.stubs(:shell_type).returns("powershell")
259
+ platform.stubs(:os_type).returns("windows")
260
+ create_test_files
261
+ config[:ruby_bindir] = "\\rbd"
262
+ config[:root_path] = "\\r"
263
+ end
264
+
265
+ common_powershell_variable_specs
266
+
267
+ it "sets path to ruby command" do
268
+ cmd.must_match regexify(%{$ruby = "\\rbd\\ruby.exe"})
269
+ end
270
+
271
+ it "sets path to gem command" do
272
+ cmd.must_match regexify(%{$gem = "\\rbd\\gem"})
273
+ end
274
+
275
+ it "sets version for busser" do
276
+ config[:version] = "the_best"
277
+
278
+ cmd.must_match regexify(%{$version = "the_best"})
279
+ end
280
+
281
+ it "sets gem install arguments" do
282
+ cmd.must_match regexify(
283
+ %{$gem_install_args = "busser --no-rdoc --no-ri"})
284
+ end
285
+
286
+ it "sets path to busser binstub command" do
287
+ cmd.must_match regexify(%{$busser = "\\r\\bin\\busser.bat"})
288
+ end
289
+
290
+ it "sets the busser plugins list" do
291
+ cmd.must_match regexify(
292
+ %{$plugins = "busser-abba busser-minispec busser-mondospec"})
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ describe "#init_command" do
299
+
300
+ let(:cmd) { verifier.init_command }
301
+
302
+ describe "with no suite test files" do
303
+
304
+ describe "for bourne shells" do
305
+
306
+ before { platform.stubs(:shell_type).returns("bourne") }
307
+
308
+ it "returns nil" do
309
+ cmd.must_equal nil
310
+ end
311
+ end
312
+
313
+ describe "for powershell shells on windows os types" do
314
+
315
+ before do
316
+ platform.stubs(:shell_type).returns("powershell")
317
+ platform.stubs(:os_type).returns("windows")
318
+ end
319
+
320
+ it "returns nil" do
321
+ cmd.must_equal nil
322
+ end
323
+ end
324
+ end
325
+
326
+ describe "with suite test files" do
327
+
328
+ describe "for bourne shells" do
329
+
330
+ before do
331
+ platform.stubs(:shell_type).returns("bourne")
332
+ create_test_files
333
+ config[:ruby_bindir] = "/rbd"
334
+ config[:root_path] = "/r"
335
+ end
336
+
337
+ common_bourne_variable_specs
338
+
339
+ it "runs busser's suite cleanup with sudo, if set" do
340
+ config[:root_path] = "/b"
341
+ config[:sudo] = true
342
+
343
+ cmd.must_match regexify(%{sudo -E /b/bin/busser suite cleanup})
344
+ end
345
+
346
+ it "runs busser's suite cleanup without sudo, if falsey" do
347
+ config[:root_path] = "/b"
348
+ config[:sudo] = false
349
+
350
+ cmd.wont_match regexify(%{sudo -E /b/bin/busser suite cleanup})
351
+ cmd.must_match regexify(%{/b/bin/busser suite cleanup})
352
+ end
353
+ end
354
+
355
+ describe "for powershell shells on windows os types" do
356
+
357
+ before do
358
+ platform.stubs(:shell_type).returns("powershell")
359
+ platform.stubs(:os_type).returns("windows")
360
+ create_test_files
361
+ config[:ruby_bindir] = "\\rbd"
362
+ config[:root_path] = "\\r"
363
+ end
364
+
365
+ common_powershell_variable_specs
366
+
367
+ it "runs busser's suite cleanup" do
368
+ config[:root_path] = "\\b"
369
+
370
+ cmd.must_match regexify(%{& \\b\\bin\\busser.bat suite cleanup})
371
+ end
372
+ end
373
+ end
374
+ end
375
+
376
+ describe "#run_command" do
377
+
378
+ let(:cmd) { verifier.run_command }
379
+
380
+ describe "with no suite test files" do
381
+
382
+ describe "for bourne shells" do
383
+
384
+ before { platform.stubs(:shell_type).returns("bourne") }
385
+
386
+ it "returns nil" do
387
+ cmd.must_equal nil
388
+ end
389
+ end
390
+
391
+ describe "for powershell shells on windows os types" do
392
+
393
+ before do
394
+ platform.stubs(:shell_type).returns("powershell")
395
+ platform.stubs(:os_type).returns("windows")
396
+ end
397
+
398
+ it "returns nil" do
399
+ cmd.must_equal nil
400
+ end
401
+ end
402
+ end
403
+
404
+ describe "with suite test files" do
405
+
406
+ describe "for bourne shells" do
407
+
408
+ before do
409
+ platform.stubs(:shell_type).returns("bourne")
410
+ create_test_files
411
+ config[:ruby_bindir] = "/rbd"
412
+ config[:root_path] = "/r"
413
+ end
414
+
415
+ common_bourne_variable_specs
416
+
417
+ it "uses sudo for busser test when configured" do
418
+ config[:sudo] = true
419
+ config[:busser_bin] = "/p/b"
420
+
421
+ cmd.must_match regexify("sudo -E /p/b test", :partial_line)
422
+ end
423
+
424
+ it "does not use sudo for busser test when configured" do
425
+ config[:sudo] = false
426
+ config[:busser_bin] = "/p/b"
427
+
428
+ cmd.must_match regexify("/p/b test", :partial_line)
429
+ cmd.wont_match regexify("sudo -E /p/b test", :partial_line)
430
+ end
431
+ end
432
+
433
+ describe "for powershell shells on windows os types" do
434
+
435
+ before do
436
+ platform.stubs(:shell_type).returns("powershell")
437
+ platform.stubs(:os_type).returns("windows")
438
+ create_test_files
439
+ config[:ruby_bindir] = "\\rbd"
440
+ config[:root_path] = "\\r"
441
+ end
442
+
443
+ common_powershell_variable_specs
444
+
445
+ it "runs busser's test" do
446
+ config[:root_path] = "\\b"
447
+
448
+ cmd.must_match regexify(%{& \\b\\bin\\busser.bat test})
449
+ end
450
+ end
451
+ end
452
+ end
453
+
454
+ describe "#create_sandbox" do
455
+
456
+ before do
457
+ create_test_files
458
+ end
459
+
460
+ it "copies each suite file into the suites directory in sandbox" do
461
+ verifier.create_sandbox
462
+
463
+ files.each do |f, md|
464
+ file = sandbox_path("suites/#{f}")
465
+
466
+ file.file?.must_equal true
467
+ file.stat.mode.to_s(8)[2, 4].must_equal md[:perms]
468
+ IO.read(file).must_equal md[:content]
469
+ end
470
+ end
471
+
472
+ it "copies each helper file into the suites directory in sandbox" do
473
+ verifier.create_sandbox
474
+
475
+ helper_files.each do |f, md|
476
+ file = sandbox_path("suites/#{f}")
477
+
478
+ file.file?.must_equal true
479
+ file.stat.mode.to_s(8)[2, 4].must_equal md[:perms]
480
+ IO.read(file).must_equal md[:content]
481
+ end
482
+ end
483
+
484
+ def sandbox_path(path)
485
+ Pathname.new(verifier.sandbox_path).join(path)
486
+ end
487
+ end
488
+
489
+ describe "Busser legacy behavior for code calling old method names" do
490
+
491
+ let(:busser) { verifier }
492
+
493
+ it "responds to #setup_cmd which calls #install_command" do
494
+ busser.stubs(:install_command).returns("install")
495
+
496
+ busser.setup_cmd.must_equal "install"
497
+ end
498
+
499
+ it "responds to #run_cmd which calls #run_command" do
500
+ busser.stubs(:run_command).returns("run")
501
+
502
+ busser.run_cmd.must_equal "run"
503
+ end
504
+
505
+ it "responds to #sync_cmd which logs a warning" do
506
+ busser.sync_cmd
507
+
508
+ logged_output.string.must_match warn_line_with(
509
+ "Legacy call to #sync_cmd cannot be preserved")
510
+ end
511
+ end
512
+
513
+ def create_file(file, content, perms)
514
+ FileUtils.mkdir_p(File.dirname(file))
515
+ File.open(file, "wb") { |f| f.write(content) }
516
+ FileUtils.chmod(perms.to_i(8), file)
517
+ end
518
+
519
+ def create_test_files
520
+ base = "#{config[:test_base_path]}/germany"
521
+ hbase = "#{config[:test_base_path]}/helpers"
522
+
523
+ files.map { |f, md| [File.join(base, f), md] }.each do |f, md|
524
+ create_file(f, md[:content], md[:perms])
525
+ end
526
+ helper_files.map { |f, md| [File.join(hbase, f), md] }.each do |f, md|
527
+ create_file(f, md[:content], md[:perms])
528
+ end
529
+ end
530
+
531
+ def regexify(str, line = :whole_line)
532
+ r = Regexp.escape(str)
533
+ r = "^\s*#{r}$" if line == :whole_line
534
+ Regexp.new(r)
535
+ end
536
+
537
+ def warn_line_with(msg)
538
+ %r{^W, .* : #{Regexp.escape(msg)}}
539
+ end
540
+ end