test-kitchen 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +1 -1
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +20 -9
  5. data/CHANGELOG.md +219 -108
  6. data/Gemfile +10 -6
  7. data/Guardfile +38 -9
  8. data/README.md +11 -1
  9. data/Rakefile +21 -37
  10. data/bin/kitchen +4 -4
  11. data/features/kitchen_action_commands.feature +161 -0
  12. data/features/kitchen_console_command.feature +34 -0
  13. data/features/kitchen_diagnose_command.feature +64 -0
  14. data/features/kitchen_init_command.feature +29 -17
  15. data/features/kitchen_list_command.feature +2 -2
  16. data/features/kitchen_login_command.feature +56 -0
  17. data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
  18. data/features/kitchen_test_command.feature +88 -0
  19. data/features/step_definitions/gem_steps.rb +8 -6
  20. data/features/step_definitions/git_steps.rb +4 -2
  21. data/features/step_definitions/output_steps.rb +5 -0
  22. data/features/support/env.rb +12 -9
  23. data/lib/kitchen.rb +60 -38
  24. data/lib/kitchen/base64_stream.rb +55 -0
  25. data/lib/kitchen/busser.rb +124 -58
  26. data/lib/kitchen/cli.rb +121 -38
  27. data/lib/kitchen/collection.rb +3 -3
  28. data/lib/kitchen/color.rb +4 -4
  29. data/lib/kitchen/command.rb +78 -11
  30. data/lib/kitchen/command/action.rb +3 -2
  31. data/lib/kitchen/command/console.rb +12 -5
  32. data/lib/kitchen/command/diagnose.rb +17 -3
  33. data/lib/kitchen/command/driver_discover.rb +26 -7
  34. data/lib/kitchen/command/exec.rb +41 -0
  35. data/lib/kitchen/command/list.rb +44 -14
  36. data/lib/kitchen/command/login.rb +2 -1
  37. data/lib/kitchen/command/sink.rb +2 -1
  38. data/lib/kitchen/command/test.rb +5 -4
  39. data/lib/kitchen/config.rb +146 -14
  40. data/lib/kitchen/configurable.rb +314 -0
  41. data/lib/kitchen/data_munger.rb +522 -18
  42. data/lib/kitchen/diagnostic.rb +43 -4
  43. data/lib/kitchen/driver.rb +4 -4
  44. data/lib/kitchen/driver/base.rb +80 -115
  45. data/lib/kitchen/driver/dummy.rb +34 -6
  46. data/lib/kitchen/driver/proxy.rb +14 -3
  47. data/lib/kitchen/driver/ssh_base.rb +61 -7
  48. data/lib/kitchen/errors.rb +109 -9
  49. data/lib/kitchen/generator/driver_create.rb +39 -5
  50. data/lib/kitchen/generator/init.rb +130 -45
  51. data/lib/kitchen/instance.rb +162 -28
  52. data/lib/kitchen/lazy_hash.rb +79 -7
  53. data/lib/kitchen/loader/yaml.rb +159 -27
  54. data/lib/kitchen/logger.rb +267 -21
  55. data/lib/kitchen/logging.rb +30 -3
  56. data/lib/kitchen/login_command.rb +11 -2
  57. data/lib/kitchen/metadata_chopper.rb +2 -2
  58. data/lib/kitchen/provisioner.rb +4 -4
  59. data/lib/kitchen/provisioner/base.rb +107 -103
  60. data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
  61. data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
  62. data/lib/kitchen/provisioner/chef_base.rb +206 -167
  63. data/lib/kitchen/provisioner/chef_solo.rb +25 -7
  64. data/lib/kitchen/provisioner/chef_zero.rb +105 -29
  65. data/lib/kitchen/provisioner/dummy.rb +1 -1
  66. data/lib/kitchen/provisioner/shell.rb +21 -6
  67. data/lib/kitchen/rake_tasks.rb +8 -3
  68. data/lib/kitchen/shell_out.rb +15 -18
  69. data/lib/kitchen/ssh.rb +122 -27
  70. data/lib/kitchen/state_file.rb +24 -7
  71. data/lib/kitchen/thor_tasks.rb +9 -4
  72. data/lib/kitchen/util.rb +43 -118
  73. data/lib/kitchen/version.rb +1 -1
  74. data/lib/vendor/hash_recursive_merge.rb +10 -2
  75. data/spec/kitchen/base64_stream_spec.rb +77 -0
  76. data/spec/kitchen/busser_spec.rb +490 -0
  77. data/spec/kitchen/collection_spec.rb +10 -10
  78. data/spec/kitchen/color_spec.rb +2 -2
  79. data/spec/kitchen/config_spec.rb +234 -62
  80. data/spec/kitchen/configurable_spec.rb +490 -0
  81. data/spec/kitchen/data_munger_spec.rb +1070 -862
  82. data/spec/kitchen/diagnostic_spec.rb +79 -0
  83. data/spec/kitchen/driver/base_spec.rb +80 -85
  84. data/spec/kitchen/driver/dummy_spec.rb +43 -14
  85. data/spec/kitchen/driver/proxy_spec.rb +134 -0
  86. data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
  87. data/spec/kitchen/driver_spec.rb +15 -15
  88. data/spec/kitchen/errors_spec.rb +309 -0
  89. data/spec/kitchen/instance_spec.rb +143 -46
  90. data/spec/kitchen/lazy_hash_spec.rb +36 -9
  91. data/spec/kitchen/loader/yaml_spec.rb +237 -226
  92. data/spec/kitchen/logger_spec.rb +419 -0
  93. data/spec/kitchen/logging_spec.rb +59 -0
  94. data/spec/kitchen/login_command_spec.rb +49 -0
  95. data/spec/kitchen/metadata_chopper_spec.rb +82 -0
  96. data/spec/kitchen/platform_spec.rb +4 -4
  97. data/spec/kitchen/provisioner/base_spec.rb +65 -125
  98. data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
  99. data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
  100. data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
  101. data/spec/kitchen/provisioner/shell_spec.rb +269 -0
  102. data/spec/kitchen/provisioner_spec.rb +6 -6
  103. data/spec/kitchen/shell_out_spec.rb +143 -0
  104. data/spec/kitchen/ssh_spec.rb +683 -0
  105. data/spec/kitchen/state_file_spec.rb +28 -21
  106. data/spec/kitchen/suite_spec.rb +7 -7
  107. data/spec/kitchen/util_spec.rb +68 -10
  108. data/spec/kitchen_spec.rb +107 -0
  109. data/spec/spec_helper.rb +18 -13
  110. data/support/chef-client-zero.rb +10 -9
  111. data/support/chef_helpers.sh +16 -0
  112. data/support/download_helpers.sh +109 -0
  113. data/test-kitchen.gemspec +42 -33
  114. metadata +107 -33
@@ -18,5 +18,5 @@
18
18
 
19
19
  module Kitchen
20
20
 
21
- VERSION = "1.2.1"
21
+ VERSION = "1.3.0"
22
22
  end
@@ -1,3 +1,4 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  #
2
3
  # = Hash Recursive Merge
3
4
  #
@@ -24,16 +25,20 @@ module HashRecursiveMerge
24
25
  # When both +hsh+ and +other_hash+ contains an entry with the same key,
25
26
  # it merges and returns the values from both arrays.
26
27
  #
28
+ # @example
29
+ #
27
30
  # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
28
31
  # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
29
32
  # h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
30
33
  #
31
34
  # Simply using Hash#merge! would return
32
35
  #
36
+ # @example
37
+ #
33
38
  # h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
34
39
  #
35
40
  def rmerge!(other_hash)
36
- merge!(other_hash) do |key, oldval, newval|
41
+ merge!(other_hash) do |_key, oldval, newval|
37
42
  oldval.class == self.class ? oldval.rmerge!(newval) : newval
38
43
  end
39
44
  end
@@ -51,12 +56,16 @@ module HashRecursiveMerge
51
56
  # includes the same key, the value is merged instead replaced with
52
57
  # +other_hash+ value.
53
58
  #
59
+ # @example
60
+ #
54
61
  # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
55
62
  # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
56
63
  # h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
57
64
  #
58
65
  # Simply using Hash#merge would return
59
66
  #
67
+ # @example
68
+ #
60
69
  # h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
61
70
  #
62
71
  def rmerge(other_hash)
@@ -68,7 +77,6 @@ module HashRecursiveMerge
68
77
 
69
78
  end
70
79
 
71
-
72
80
  class Hash
73
81
  include HashRecursiveMerge
74
82
  end
@@ -0,0 +1,77 @@
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
+ require "base64"
21
+ require "stringio"
22
+ require "securerandom"
23
+
24
+ require "kitchen/base64_stream"
25
+
26
+ describe Kitchen::Base64Stream do
27
+
28
+ SHORT_BODIES = %w[you test wakkawakkawakka]
29
+
30
+ describe ".strict_encode" do
31
+
32
+ SHORT_BODIES.each do |body|
33
+ it "encodes short payload ('#{body}') from input IO to output IO" do
34
+ output = StringIO.new("", "wb")
35
+ StringIO.open(body) do |input|
36
+ Kitchen::Base64Stream.strict_encode(input, output)
37
+ end
38
+
39
+ output.string.must_equal Base64.strict_encode64(body)
40
+ end
41
+ end
42
+
43
+ it "encodes a large payload from input IO to output IO" do
44
+ body = SecureRandom.random_bytes(1048576 * 8)
45
+ output = StringIO.new("", "wb")
46
+ StringIO.open(body) do |input|
47
+ Kitchen::Base64Stream.strict_encode(input, output)
48
+ end
49
+
50
+ output.string.must_equal Base64.strict_encode64(body)
51
+ end
52
+ end
53
+
54
+ describe ".strict_decode" do
55
+
56
+ SHORT_BODIES.map { |b| Base64.strict_encode64(b) }.each do |body|
57
+ it "decodes short payload ('#{body}') from input IO to output IO" do
58
+ output = StringIO.new("", "wb")
59
+ StringIO.open(body) do |input|
60
+ Kitchen::Base64Stream.strict_decode(input, output)
61
+ end
62
+
63
+ output.string.must_equal Base64.strict_decode64(body)
64
+ end
65
+ end
66
+
67
+ it "decodes a large payload from input IO to output IO" do
68
+ body = Base64.strict_encode64(SecureRandom.hex(1048576 * 8))
69
+ output = StringIO.new("", "wb")
70
+ StringIO.open(body) do |input|
71
+ Kitchen::Base64Stream.strict_decode(input, output)
72
+ end
73
+
74
+ output.string.must_equal Base64.strict_decode64(body)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,490 @@
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/busser"
22
+ # @TODO: this can be remove once Kitchen::DEFAULT_TEST_DIR is removed
23
+ require "kitchen"
24
+
25
+ describe Kitchen::Busser do
26
+
27
+ let(:suite_name) { "germany" }
28
+ let(:config) { Hash.new }
29
+
30
+ let(:busser) do
31
+ Kitchen::Busser.new(suite_name, config)
32
+ end
33
+
34
+ describe ".new" do
35
+
36
+ it "raises a ClientError if a suite name is not provided" do
37
+ proc {
38
+ Kitchen::Busser.new(nil, config)
39
+ }.must_raise Kitchen::ClientError
40
+ end
41
+
42
+ it "raises a UserError if the suite name is 'helper'" do
43
+ proc {
44
+ Kitchen::Busser.new("helper", config)
45
+ }.must_raise Kitchen::UserError
46
+ end
47
+ end
48
+
49
+ it "#name returns the name of the suite" do
50
+ busser.name.must_equal "germany"
51
+ end
52
+
53
+ it "#config_keys returns an array of config key names" do
54
+ busser.config_keys.sort.must_equal [
55
+ :busser_bin, :kitchen_root, :root_path, :ruby_bindir, :sudo,
56
+ :suite_name, :test_base_path, :version
57
+ ]
58
+ end
59
+
60
+ describe "configuration" do
61
+
62
+ it ":kitchen_root defaults to current directory" do
63
+ busser[:kitchen_root].must_equal Dir.pwd
64
+ end
65
+
66
+ it ":test_base_path defaults to an expanded path" do
67
+ busser[:test_base_path].must_equal File.join(Dir.pwd, "test/integration")
68
+ end
69
+
70
+ it ":suite_name defaults to the passed in suite name" do
71
+ busser[:suite_name].must_equal "germany"
72
+ end
73
+
74
+ it ":sudo defaults to true" do
75
+ busser[:sudo].must_equal true
76
+ end
77
+
78
+ it ":ruby_bindir defaults the an Omnibus Chef installation" do
79
+ busser[:ruby_bindir].must_equal "/opt/chef/embedded/bin"
80
+ end
81
+
82
+ it ":root_path defaults to '/tmp/busser'" do
83
+ busser[:root_path].must_equal "/tmp/busser"
84
+ end
85
+
86
+ it ":version defaults to 'busser'" do
87
+ busser[:version].must_equal "busser"
88
+ end
89
+
90
+ it ":busser_bin defaults to a binstub under :root_path" do
91
+ config[:root_path] = "/beep"
92
+
93
+ busser[:busser_bin].must_equal "/beep/bin/busser"
94
+ end
95
+ end
96
+
97
+ describe "#diagnose" do
98
+
99
+ it "returns a hash with sorted keys" do
100
+ busser.diagnose.keys.must_equal [
101
+ :busser_bin, :kitchen_root, :root_path, :ruby_bindir, :sudo,
102
+ :suite_name, :test_base_path, :version
103
+ ]
104
+ end
105
+ end
106
+
107
+ describe "#setup_cmd" do
108
+
109
+ before do
110
+ @root = Dir.mktmpdir
111
+ config[:test_base_path] = @root
112
+ end
113
+
114
+ after do
115
+ FileUtils.remove_entry(@root)
116
+ end
117
+
118
+ let(:cmd) { busser.setup_cmd }
119
+
120
+ describe "with no suite test files" do
121
+
122
+ it "returns nil" do
123
+ cmd.must_equal nil
124
+ end
125
+ end
126
+
127
+ describe "with suite test files" do
128
+
129
+ before do
130
+ base = "#{config[:test_base_path]}/germany"
131
+
132
+ FileUtils.mkdir_p "#{base}/mondospec"
133
+ File.open("#{base}/mondospec/charlie", "wb") { |f| f.write("charlie") }
134
+ FileUtils.mkdir_p "#{base}/minispec"
135
+ File.open("#{base}/minispec/beta", "wb") { |f| f.write("beta") }
136
+ FileUtils.mkdir_p "#{base}/abba"
137
+ File.open("#{base}/abba/alpha", "wb") { |f| f.write("alpha") }
138
+
139
+ config[:ruby_bindir] = "/r"
140
+ end
141
+
142
+ it "uses bourne shell" do
143
+ cmd.must_match(/\Ash -c '$/)
144
+ cmd.must_match(/'\Z/)
145
+ end
146
+
147
+ it "sets the BUSSER_ROOT environment variable" do
148
+ config[:root_path] = "/r"
149
+
150
+ cmd.must_match regexify(%{BUSSER_ROOT="/r"}, :partial_line)
151
+ end
152
+
153
+ it "sets the GEM_HOME environment variable" do
154
+ config[:root_path] = "/r"
155
+
156
+ cmd.must_match regexify(%{GEM_HOME="/r/gems" }, :partial_line)
157
+ end
158
+
159
+ it "sets the GEM_PATH environment variable" do
160
+ config[:root_path] = "/r"
161
+
162
+ cmd.must_match regexify(%{GEM_PATH="/r/gems" }, :partial_line)
163
+ end
164
+
165
+ it "sets the GEM_CACHE environment variable" do
166
+ config[:root_path] = "/r"
167
+
168
+ cmd.must_match regexify(%{GEM_CACHE="/r/gems/cache" }, :partial_line)
169
+ end
170
+
171
+ it "exports all the environment variables" do
172
+ cmd.must_match regexify(
173
+ "export BUSSER_ROOT GEM_HOME GEM_PATH GEM_CACHE", :partial_line)
174
+ end
175
+
176
+ it "checks if busser is installed" do
177
+ cmd.must_match regexify(
178
+ %{if ! sudo -E /r/gem list busser -i >/dev/null;}, :partial_line)
179
+ end
180
+
181
+ describe "installing busser" do
182
+
183
+ it "installs the latest busser gem by default" do
184
+ cmd.must_match regexify(
185
+ %{sudo -E /r/gem install busser --no-rdoc --no-ri}, :partial_line)
186
+ end
187
+
188
+ it "installs a specific busser version gem" do
189
+ config[:version] = "4.0.7"
190
+
191
+ cmd.must_match regexify(
192
+ %{sudo -E /r/gem install busser --version 4.0.7 --no-rdoc --no-ri},
193
+ :partial_line)
194
+ end
195
+
196
+ it "installs a specific busser version gem with @ syntax" do
197
+ config[:version] = "busser@1.2.3"
198
+
199
+ cmd.must_match regexify(
200
+ %{sudo -E /r/gem install busser --version 1.2.3 --no-rdoc --no-ri},
201
+ :partial_line)
202
+ end
203
+
204
+ it "installs an arbitrary gem and version with @ syntax" do
205
+ config[:version] = "foo@9.0.1"
206
+
207
+ cmd.must_match regexify(
208
+ %{sudo -E /r/gem install foo --version 9.0.1 --no-rdoc --no-ri},
209
+ :partial_line)
210
+ end
211
+ end
212
+
213
+ it "calculates RubyGem's bindir" do
214
+ cmd.must_match regexify(
215
+ %{gem_bindir=`/r/ruby -rrubygems -e "puts Gem.bindir"`},
216
+ :partial_line)
217
+ end
218
+
219
+ it "runs busser setup from the installed gem_bindir binstub" do
220
+ cmd.must_match regexify(
221
+ %{sudo -E ${gem_bindir}/busser setup}, :partial_line)
222
+ end
223
+
224
+ it "runs busser plugin install with the :busser_bindir command" do
225
+ config[:busser_bin] = "/b/b"
226
+
227
+ cmd.must_match regexify(
228
+ %{sudo -E /b/b plugin install } +
229
+ %{busser-abba busser-minispec busser-mondospec},
230
+ :partial_line)
231
+ end
232
+ end
233
+ end
234
+
235
+ describe "#sync_cmd" do
236
+
237
+ before do
238
+ @root = Dir.mktmpdir
239
+ config[:test_base_path] = @root
240
+ end
241
+
242
+ after do
243
+ FileUtils.remove_entry(@root)
244
+ end
245
+
246
+ let(:cmd) { busser.sync_cmd }
247
+
248
+ describe "with no suite test files" do
249
+
250
+ it "returns nil" do
251
+ cmd.must_equal nil
252
+ end
253
+ end
254
+
255
+ describe "with suite test files" do
256
+
257
+ before do
258
+ base = "#{config[:test_base_path]}/germany"
259
+ hbase = "#{config[:test_base_path]}/helpers"
260
+
261
+ files.map { |f, md| [File.join(base, f), md] }.each do |f, md|
262
+ create_file(f, md[:content], md[:perms])
263
+ end
264
+ helper_files.map { |f, md| [File.join(hbase, f), md] }.each do |f, md|
265
+ create_file(f, md[:content], md[:perms])
266
+ end
267
+
268
+ config[:ruby_bindir] = "/r"
269
+ end
270
+
271
+ let(:files) do
272
+ {
273
+ "mondospec/charlie" => {
274
+ :content => "charlie",
275
+ :perms => "0764",
276
+ :base64 => "Y2hhcmxpZQ==",
277
+ :md5 => "bf779e0933a882808585d19455cd7937"
278
+ },
279
+ "minispec/beta" => {
280
+ :content => "beta",
281
+ :perms => "0644",
282
+ :base64 => "YmV0YQ==",
283
+ :md5 => "987bcab01b929eb2c07877b224215c92"
284
+ },
285
+ "abba/alpha" => {
286
+ :content => "alpha",
287
+ :perms => "0440",
288
+ :base64 => "YWxwaGE=",
289
+ :md5 => "2c1743a391305fbf367df8e4f069f9f9"
290
+ }
291
+ }
292
+ end
293
+
294
+ let(:helper_files) do
295
+ {
296
+ "minispec/spec_helper" => {
297
+ :content => "helping",
298
+ :perms => "0644",
299
+ :base64 => "aGVscGluZw==",
300
+ :md5 => "111c081293c11cb7c2ac6fbf841805cb"
301
+ },
302
+ "abba/common" => {
303
+ :content => "yeppers",
304
+ :perms => "0664",
305
+ :base64 => "eWVwcGVycw==",
306
+ :md5 => "7c3157de4890b1abcb7a6a3695eb6dd2"
307
+ }
308
+ }
309
+ end
310
+
311
+ it "uses bourne shell" do
312
+ cmd.must_match(/\Ash -c '$/)
313
+ cmd.must_match(/'\Z/)
314
+ end
315
+
316
+ it "sets the BUSSER_ROOT environment variable" do
317
+ config[:root_path] = "/r"
318
+
319
+ cmd.must_match regexify(%{BUSSER_ROOT="/r"}, :partial_line)
320
+ end
321
+
322
+ it "sets the GEM_HOME environment variable" do
323
+ config[:root_path] = "/r"
324
+
325
+ cmd.must_match regexify(%{GEM_HOME="/r/gems" }, :partial_line)
326
+ end
327
+
328
+ it "sets the GEM_PATH environment variable" do
329
+ config[:root_path] = "/r"
330
+
331
+ cmd.must_match regexify(%{GEM_PATH="/r/gems" }, :partial_line)
332
+ end
333
+
334
+ it "sets the GEM_CACHE environment variable" do
335
+ config[:root_path] = "/r"
336
+
337
+ cmd.must_match regexify(%{GEM_CACHE="/r/gems/cache" }, :partial_line)
338
+ end
339
+
340
+ it "exports all the environment variables" do
341
+ cmd.must_match regexify(
342
+ "export BUSSER_ROOT GEM_HOME GEM_PATH GEM_CACHE", :partial_line)
343
+ end
344
+
345
+ it "logs a message for each file" do
346
+ config[:busser_bin] = "/b/busser"
347
+
348
+ files.each do |f, md|
349
+ cmd.must_match regexify([
350
+ %{echo "Uploading `sudo -E /b/busser suite path`/#{f}},
351
+ %{(mode=#{md[:perms]})"}
352
+ ].join(" "))
353
+ end
354
+ end
355
+
356
+ it "logs a message for each helper file" do
357
+ config[:busser_bin] = "/b/busser"
358
+
359
+ helper_files.each do |f, md|
360
+ cmd.must_match regexify([
361
+ %{echo "Uploading `sudo -E /b/busser suite path`/#{f}},
362
+ %{(mode=#{md[:perms]})"}
363
+ ].join(" "))
364
+ end
365
+ end
366
+
367
+ it "base64 encodes each file for deserializing with busser" do
368
+ config[:busser_bin] = "/b/busser"
369
+
370
+ files.each do |f, md|
371
+ cmd.must_match regexify([
372
+ %{echo "#{md[:base64]}" | sudo -E /b/busser deserialize},
373
+ %{--destination=`sudo -E /b/busser suite path`/#{f}},
374
+ %{--md5sum=#{md[:md5]} --perms=#{md[:perms]}}
375
+ ].join(" "))
376
+ end
377
+ end
378
+
379
+ it "base64 encodes each helper file for deserializing with busser" do
380
+ config[:busser_bin] = "/b/busser"
381
+
382
+ helper_files.each do |f, md|
383
+ cmd.must_match regexify([
384
+ %{echo "#{md[:base64]}" | sudo -E /b/busser deserialize},
385
+ %{--destination=`sudo -E /b/busser suite path`/#{f}},
386
+ %{--md5sum=#{md[:md5]} --perms=#{md[:perms]}}
387
+ ].join(" "))
388
+ end
389
+ end
390
+
391
+ def create_file(file, content, perms)
392
+ FileUtils.mkdir_p(File.dirname(file))
393
+ File.open(file, "wb") { |f| f.write(content) }
394
+ FileUtils.chmod(perms.to_i(8), file)
395
+ end
396
+ end
397
+ end
398
+
399
+ describe "#run_cmd" do
400
+
401
+ before do
402
+ @root = Dir.mktmpdir
403
+ config[:test_base_path] = @root
404
+ end
405
+
406
+ after do
407
+ FileUtils.remove_entry(@root)
408
+ end
409
+
410
+ let(:cmd) { busser.run_cmd }
411
+
412
+ describe "with no suite test files" do
413
+
414
+ it "returns nil" do
415
+ cmd.must_equal nil
416
+ end
417
+ end
418
+
419
+ describe "with suite test files" do
420
+
421
+ before do
422
+ base = "#{config[:test_base_path]}/germany"
423
+
424
+ FileUtils.mkdir_p "#{base}/mondospec"
425
+ File.open("#{base}/mondospec/charlie", "wb") { |f| f.write("charlie") }
426
+ FileUtils.mkdir_p "#{base}/minispec"
427
+ File.open("#{base}/minispec/beta", "wb") { |f| f.write("beta") }
428
+ FileUtils.mkdir_p "#{base}/abba"
429
+ File.open("#{base}/abba/alpha", "wb") { |f| f.write("alpha") }
430
+
431
+ config[:ruby_bindir] = "/r"
432
+ end
433
+
434
+ it "uses bourne shell" do
435
+ cmd.must_match(/\Ash -c '$/)
436
+ cmd.must_match(/'\Z/)
437
+ end
438
+
439
+ it "sets the BUSSER_ROOT environment variable" do
440
+ config[:root_path] = "/r"
441
+
442
+ cmd.must_match regexify(%{BUSSER_ROOT="/r"}, :partial_line)
443
+ end
444
+
445
+ it "sets the GEM_HOME environment variable" do
446
+ config[:root_path] = "/r"
447
+
448
+ cmd.must_match regexify(%{GEM_HOME="/r/gems" }, :partial_line)
449
+ end
450
+
451
+ it "sets the GEM_PATH environment variable" do
452
+ config[:root_path] = "/r"
453
+
454
+ cmd.must_match regexify(%{GEM_PATH="/r/gems" }, :partial_line)
455
+ end
456
+
457
+ it "sets the GEM_CACHE environment variable" do
458
+ config[:root_path] = "/r"
459
+
460
+ cmd.must_match regexify(%{GEM_CACHE="/r/gems/cache" }, :partial_line)
461
+ end
462
+
463
+ it "exports all the environment variables" do
464
+ cmd.must_match regexify(
465
+ "export BUSSER_ROOT GEM_HOME GEM_PATH GEM_CACHE", :partial_line)
466
+ end
467
+
468
+ it "uses sudo for busser test when configured" do
469
+ config[:sudo] = true
470
+ config[:busser_bin] = "/p/b"
471
+
472
+ cmd.must_match regexify("sudo -E /p/b test", :partial_line)
473
+ end
474
+
475
+ it "does not use sudo for busser test when configured" do
476
+ config[:sudo] = false
477
+ config[:busser_bin] = "/p/b"
478
+
479
+ cmd.must_match regexify("/p/b test", :partial_line)
480
+ cmd.wont_match regexify("sudo -E /p/b test", :partial_line)
481
+ end
482
+ end
483
+ end
484
+
485
+ def regexify(str, line = :whole_line)
486
+ r = Regexp.escape(str)
487
+ r = "^\s*#{r}$" if line == :whole_line
488
+ Regexp.new(r)
489
+ end
490
+ end