test-kitchen 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
@@ -1,117 +1,117 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, 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/lazy_hash"
22
-
23
- describe Kitchen::LazyHash do
24
-
25
- let(:context) do
26
- stub(:color => "blue", :metal => "heavy")
27
- end
28
-
29
- let(:hash_obj) do
30
- {
31
- :shed_color => ->(c) { c.color },
32
- :barn => "locked",
33
- :genre => proc { |c| "#{c.metal} metal" }
34
- }
35
- end
36
-
37
- describe "#[]" do
38
-
39
- it "returns regular values for keys" do
40
- Kitchen::LazyHash.new(hash_obj, context)[:barn].must_equal "locked"
41
- end
42
-
43
- it "invokes call on values that are lambdas" do
44
- Kitchen::LazyHash.new(hash_obj, context)[:shed_color].must_equal "blue"
45
- end
46
-
47
- it "invokes call on values that are Procs" do
48
- Kitchen::LazyHash.new(hash_obj, context)[:genre].must_equal "heavy metal"
49
- end
50
- end
51
-
52
- describe "#fetch" do
53
-
54
- it "returns regular hash values for keys" do
55
- Kitchen::LazyHash.new(hash_obj, context).fetch(:barn).must_equal "locked"
56
- end
57
-
58
- it "invokes call on values that are lambdas" do
59
- Kitchen::LazyHash.new(hash_obj, context).
60
- fetch(:shed_color).must_equal "blue"
61
- end
62
-
63
- it "invokes call on values that are Procs" do
64
- Kitchen::LazyHash.new(hash_obj, context).
65
- fetch(:genre).must_equal "heavy metal"
66
- end
67
-
68
- it "uses a default value for unset values" do
69
- Kitchen::LazyHash.new(hash_obj, context).
70
- fetch(:nope, "candy").must_equal "candy"
71
- end
72
-
73
- it "uses a block for unset values" do
74
- Kitchen::LazyHash.new(hash_obj, context).
75
- fetch(:nope) { |key| "#{key} is costly" }.must_equal "nope is costly"
76
- end
77
- end
78
-
79
- describe "#to_hash" do
80
-
81
- it "invokes any callable values and returns a Hash object" do
82
- converted = Kitchen::LazyHash.new(hash_obj, context).to_hash
83
-
84
- converted.must_be_instance_of Hash
85
- converted.fetch(:shed_color).must_equal "blue"
86
- converted.fetch(:barn).must_equal "locked"
87
- converted.fetch(:genre).must_equal "heavy metal"
88
- end
89
- end
90
-
91
- describe "select" do
92
- it "calls Procs when appropriate" do
93
- Kitchen::LazyHash.new(hash_obj, context).select { |_, _| true }.
94
- must_equal :shed_color => "blue", :barn => "locked", :genre => "heavy metal"
95
- end
96
- end
97
-
98
- describe "enumerable" do
99
- it "is an Enumerable" do
100
- assert Kitchen::LazyHash.new(hash_obj, context).is_a? Enumerable
101
- end
102
-
103
- it "returns an Enumerator from each() if no block given" do
104
- e = Kitchen::LazyHash.new(hash_obj, context).each
105
- e.is_a? Enumerator
106
- e.next.must_equal [:shed_color, "blue"]
107
- e.next.must_equal [:barn, "locked"]
108
- e.next.must_equal [:genre, "heavy metal"]
109
- end
110
-
111
- it "yields each item to the block if a block is given to each()" do
112
- items = []
113
- Kitchen::LazyHash.new(hash_obj, context).each { |i| items << i }
114
- items.must_equal [[:shed_color, "blue"], [:barn, "locked"], [:genre, "heavy metal"]]
115
- end
116
- end
117
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, 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/lazy_hash"
22
+
23
+ describe Kitchen::LazyHash do
24
+
25
+ let(:context) do
26
+ stub(:color => "blue", :metal => "heavy")
27
+ end
28
+
29
+ let(:hash_obj) do
30
+ {
31
+ :shed_color => ->(c) { c.color },
32
+ :barn => "locked",
33
+ :genre => proc { |c| "#{c.metal} metal" }
34
+ }
35
+ end
36
+
37
+ describe "#[]" do
38
+
39
+ it "returns regular values for keys" do
40
+ Kitchen::LazyHash.new(hash_obj, context)[:barn].must_equal "locked"
41
+ end
42
+
43
+ it "invokes call on values that are lambdas" do
44
+ Kitchen::LazyHash.new(hash_obj, context)[:shed_color].must_equal "blue"
45
+ end
46
+
47
+ it "invokes call on values that are Procs" do
48
+ Kitchen::LazyHash.new(hash_obj, context)[:genre].must_equal "heavy metal"
49
+ end
50
+ end
51
+
52
+ describe "#fetch" do
53
+
54
+ it "returns regular hash values for keys" do
55
+ Kitchen::LazyHash.new(hash_obj, context).fetch(:barn).must_equal "locked"
56
+ end
57
+
58
+ it "invokes call on values that are lambdas" do
59
+ Kitchen::LazyHash.new(hash_obj, context).
60
+ fetch(:shed_color).must_equal "blue"
61
+ end
62
+
63
+ it "invokes call on values that are Procs" do
64
+ Kitchen::LazyHash.new(hash_obj, context).
65
+ fetch(:genre).must_equal "heavy metal"
66
+ end
67
+
68
+ it "uses a default value for unset values" do
69
+ Kitchen::LazyHash.new(hash_obj, context).
70
+ fetch(:nope, "candy").must_equal "candy"
71
+ end
72
+
73
+ it "uses a block for unset values" do
74
+ Kitchen::LazyHash.new(hash_obj, context).
75
+ fetch(:nope) { |key| "#{key} is costly" }.must_equal "nope is costly"
76
+ end
77
+ end
78
+
79
+ describe "#to_hash" do
80
+
81
+ it "invokes any callable values and returns a Hash object" do
82
+ converted = Kitchen::LazyHash.new(hash_obj, context).to_hash
83
+
84
+ converted.must_be_instance_of Hash
85
+ converted.fetch(:shed_color).must_equal "blue"
86
+ converted.fetch(:barn).must_equal "locked"
87
+ converted.fetch(:genre).must_equal "heavy metal"
88
+ end
89
+ end
90
+
91
+ describe "select" do
92
+ it "calls Procs when appropriate" do
93
+ Kitchen::LazyHash.new(hash_obj, context).select { |_, _| true }.
94
+ must_equal :shed_color => "blue", :barn => "locked", :genre => "heavy metal"
95
+ end
96
+ end
97
+
98
+ describe "enumerable" do
99
+ it "is an Enumerable" do
100
+ assert Kitchen::LazyHash.new(hash_obj, context).is_a? Enumerable
101
+ end
102
+
103
+ it "returns an Enumerator from each() if no block given" do
104
+ e = Kitchen::LazyHash.new(hash_obj, context).each
105
+ e.is_a? Enumerator
106
+ e.next.must_equal [:shed_color, "blue"]
107
+ e.next.must_equal [:barn, "locked"]
108
+ e.next.must_equal [:genre, "heavy metal"]
109
+ end
110
+
111
+ it "yields each item to the block if a block is given to each()" do
112
+ items = []
113
+ Kitchen::LazyHash.new(hash_obj, context).each { |i| items << i }
114
+ items.must_equal [[:shed_color, "blue"], [:barn, "locked"], [:genre, "heavy metal"]]
115
+ end
116
+ end
117
+ end
@@ -1,774 +1,774 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, 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/errors"
22
- require "kitchen/util"
23
- require "kitchen/loader/yaml"
24
-
25
- class Yamled
26
- attr_accessor :foo
27
- end
28
-
29
- describe Kitchen::Loader::YAML do
30
-
31
- let(:loader) do
32
- Kitchen::Loader::YAML.new(:project_config => "/tmp/.kitchen.yml")
33
- end
34
-
35
- before do
36
- FakeFS.activate!
37
- FileUtils.mkdir_p("/tmp")
38
- end
39
-
40
- after do
41
- FakeFS.deactivate!
42
- FakeFS::FileSystem.clear
43
- end
44
-
45
- describe ".initialize" do
46
-
47
- it "sets project_config based on Dir.pwd by default" do
48
- stub_file(File.join(Dir.pwd, ".kitchen.yml"), Hash.new)
49
- loader = Kitchen::Loader::YAML.new
50
-
51
- loader.diagnose[:project_config][:filename].
52
- must_equal File.expand_path(File.join(Dir.pwd, ".kitchen.yml"))
53
- end
54
-
55
- it "sets project_config from parameter, if given" do
56
- stub_file("/tmp/crazyfunkytown.file", Hash.new)
57
- loader = Kitchen::Loader::YAML.new(
58
- :project_config => "/tmp/crazyfunkytown.file")
59
-
60
- loader.diagnose[:project_config][:filename].
61
- must_match %r{/tmp/crazyfunkytown.file$}
62
- end
63
-
64
- it "sets local_config based on Dir.pwd by default" do
65
- stub_file(File.join(Dir.pwd, ".kitchen.local.yml"), Hash.new)
66
- loader = Kitchen::Loader::YAML.new
67
-
68
- loader.diagnose[:local_config][:filename].
69
- must_equal File.expand_path(File.join(Dir.pwd, ".kitchen.local.yml"))
70
- end
71
-
72
- it "sets local_config based on location of project_config by default" do
73
- stub_file("/tmp/.kitchen.local.yml", Hash.new)
74
- loader = Kitchen::Loader::YAML.new(
75
- :project_config => "/tmp/.kitchen.yml")
76
-
77
- loader.diagnose[:local_config][:filename].
78
- must_match %r{/tmp/.kitchen.local.yml$}
79
- end
80
-
81
- it "sets local_config from parameter, if given" do
82
- stub_file("/tmp/crazyfunkytown.file", Hash.new)
83
- loader = Kitchen::Loader::YAML.new(
84
- :local_config => "/tmp/crazyfunkytown.file")
85
-
86
- loader.diagnose[:local_config][:filename].
87
- must_match %r{/tmp/crazyfunkytown.file$}
88
- end
89
-
90
- it "sets global_config based on ENV['HOME'] by default" do
91
- stub_file(File.join(ENV["HOME"], ".kitchen/config.yml"), Hash.new)
92
- loader = Kitchen::Loader::YAML.new
93
-
94
- loader.diagnose[:global_config][:filename].must_equal File.expand_path(
95
- File.join(ENV["HOME"], ".kitchen/config.yml"))
96
- end
97
-
98
- it "sets global_config from parameter, if given" do
99
- stub_file("/tmp/crazyfunkytown.file", Hash.new)
100
- loader = Kitchen::Loader::YAML.new(
101
- :global_config => "/tmp/crazyfunkytown.file")
102
-
103
- loader.diagnose[:global_config][:filename].
104
- must_match %r{/tmp/crazyfunkytown.file$}
105
- end
106
- end
107
-
108
- describe "#read" do
109
-
110
- it "returns a hash of kitchen.yml with symbolized keys" do
111
- stub_yaml!(
112
- "foo" => "bar"
113
- )
114
-
115
- loader.read.must_equal(:foo => "bar")
116
- end
117
-
118
- it "deep merges in kitchen.local.yml configuration with kitchen.yml" do
119
- stub_yaml!(".kitchen.yml",
120
- "common" => { "xx" => 1 },
121
- "a" => "b"
122
- )
123
- stub_yaml!(".kitchen.local.yml",
124
- "common" => { "yy" => 2 },
125
- "c" => "d"
126
- )
127
-
128
- loader.read.must_equal(
129
- :a => "b",
130
- :c => "d",
131
- :common => { :xx => 1, :yy => 2 }
132
- )
133
- end
134
-
135
- it "deep merges in a global config file with all other configs" do
136
- stub_yaml!(".kitchen.yml",
137
- "common" => { "xx" => 1 },
138
- "a" => "b"
139
- )
140
- stub_yaml!(".kitchen.local.yml",
141
- "common" => { "yy" => 2 },
142
- "c" => "d"
143
- )
144
- stub_global!(
145
- "common" => { "zz" => 3 },
146
- "e" => "f"
147
- )
148
-
149
- loader.read.must_equal(
150
- :a => "b",
151
- :c => "d",
152
- :e => "f",
153
- :common => { :xx => 1, :yy => 2, :zz => 3 }
154
- )
155
- end
156
-
157
- it "merges kitchen.yml over configuration in global config" do
158
- stub_global!(
159
- "common" => { "thekey" => "nope" }
160
- )
161
- stub_yaml!(".kitchen.yml",
162
- "common" => { "thekey" => "yep" }
163
- )
164
-
165
- loader.read.must_equal(:common => { :thekey => "yep" })
166
- end
167
-
168
- it "merges kitchen.local.yml over configuration in kitchen.yml" do
169
- stub_yaml!(".kitchen.yml",
170
- "common" => { "thekey" => "nope" }
171
- )
172
- stub_yaml!(".kitchen.local.yml",
173
- "common" => { "thekey" => "yep" }
174
- )
175
-
176
- loader.read.must_equal(:common => { :thekey => "yep" })
177
- end
178
-
179
- it "merges kitchen.local.yml over both kitchen.yml and global config" do
180
- stub_yaml!(".kitchen.yml",
181
- "common" => { "thekey" => "nope" }
182
- )
183
- stub_yaml!(".kitchen.local.yml",
184
- "common" => { "thekey" => "yep" }
185
- )
186
- stub_global!(
187
- "common" => { "thekey" => "kinda" }
188
- )
189
-
190
- loader.read.must_equal(:common => { :thekey => "yep" })
191
- end
192
-
193
- NORMALIZED_KEYS = {
194
- "driver" => "name",
195
- "provisioner" => "name",
196
- "busser" => "version"
197
- }
198
-
199
- NORMALIZED_KEYS.each do |key, default_key|
200
-
201
- describe "normalizing #{key} config hashes" do
202
-
203
- it "merges local with #{key} string value over yaml with hash value" do
204
- stub_yaml!(".kitchen.yml",
205
- key => { "dakey" => "ya" }
206
- )
207
- stub_yaml!(".kitchen.local.yml",
208
- key => "namey"
209
- )
210
-
211
- loader.read.must_equal(
212
- key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
213
- )
214
- end
215
-
216
- it "merges local with #{key} hash value over yaml with string value" do
217
- stub_yaml!(".kitchen.yml",
218
- key => "namey"
219
- )
220
- stub_yaml!(".kitchen.local.yml",
221
- key => { "dakey" => "ya" }
222
- )
223
-
224
- loader.read.must_equal(
225
- key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
226
- )
227
- end
228
-
229
- it "merges local with #{key} nil value over yaml with hash value" do
230
- stub_yaml!(".kitchen.yml",
231
- key => { "dakey" => "ya" }
232
- )
233
- stub_yaml!(".kitchen.local.yml",
234
- key => nil
235
- )
236
-
237
- loader.read.must_equal(
238
- key.to_sym => { :dakey => "ya" }
239
- )
240
- end
241
-
242
- it "merges local with #{key} hash value over yaml with nil value" do
243
- stub_yaml!(".kitchen.yml",
244
- key => "namey"
245
- )
246
- stub_yaml!(".kitchen.local.yml",
247
- key => nil
248
- )
249
-
250
- loader.read.must_equal(
251
- key.to_sym => { default_key.to_sym => "namey" }
252
- )
253
- end
254
-
255
- it "merges global with #{key} string value over yaml with hash value" do
256
- stub_yaml!(".kitchen.yml",
257
- key => { "dakey" => "ya" }
258
- )
259
- stub_global!(
260
- key => "namey"
261
- )
262
-
263
- loader.read.must_equal(
264
- key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
265
- )
266
- end
267
-
268
- it "merges global with #{key} hash value over yaml with string value" do
269
- stub_yaml!(".kitchen.yml",
270
- key => "namey"
271
- )
272
- stub_global!(
273
- key => { "dakey" => "ya" }
274
- )
275
-
276
- loader.read.must_equal(
277
- key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
278
- )
279
- end
280
-
281
- it "merges global with #{key} nil value over yaml with hash value" do
282
- stub_yaml!(".kitchen.yml",
283
- key => { "dakey" => "ya" }
284
- )
285
- stub_global!(
286
- key => nil
287
- )
288
-
289
- loader.read.must_equal(
290
- key.to_sym => { :dakey => "ya" }
291
- )
292
- end
293
-
294
- it "merges global with #{key} hash value over yaml with nil value" do
295
- stub_yaml!(".kitchen.yml",
296
- key => nil
297
- )
298
- stub_global!(
299
- key => { "dakey" => "ya" }
300
- )
301
-
302
- loader.read.must_equal(
303
- key.to_sym => { :dakey => "ya" }
304
- )
305
- end
306
-
307
- it "merges global, local, over yaml with mixed hash, string, nil values" do
308
- stub_yaml!(".kitchen.yml",
309
- key => nil
310
- )
311
- stub_yaml!(".kitchen.local.yml",
312
- key => "namey"
313
- )
314
- stub_global!(
315
- key => { "dakey" => "ya" }
316
- )
317
-
318
- loader.read.must_equal(
319
- key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
320
- )
321
- end
322
- end
323
- end
324
-
325
- it "handles a kitchen.local.yml with no yaml elements" do
326
- stub_yaml!(".kitchen.yml",
327
- "a" => "b"
328
- )
329
- stub_yaml!(".kitchen.local.yml", Hash.new)
330
-
331
- loader.read.must_equal(:a => "b")
332
- end
333
-
334
- it "handles a kitchen.yml with no yaml elements" do
335
- stub_yaml!(".kitchen.yml", Hash.new)
336
- stub_yaml!(".kitchen.local.yml",
337
- "a" => "b"
338
- )
339
-
340
- loader.read.must_equal(:a => "b")
341
- end
342
-
343
- it "handles a kitchen.yml with yaml elements that parse as nil" do
344
- stub_yaml!(".kitchen.yml", nil)
345
- stub_yaml!(".kitchen.local.yml",
346
- "a" => "b"
347
- )
348
-
349
- loader.read.must_equal(:a => "b")
350
- end
351
-
352
- it "raises an UserError if the config_file does not exist" do
353
- proc { loader.read }.must_raise Kitchen::UserError
354
- end
355
-
356
- it "arbitrary objects aren't deserialized in kitchen.yml" do
357
- FileUtils.mkdir_p "/tmp"
358
- File.open("/tmp/.kitchen.yml", "wb") do |f|
359
- f.write <<-YAML.gsub(/^ {10}/, "")
360
- --- !ruby/object:Yamled
361
- foo: bar
362
- YAML
363
- end
364
-
365
- loader.read.class.wont_equal Yamled
366
- loader.read.class.must_equal Hash
367
- loader.read.must_equal(:foo => "bar")
368
- end
369
-
370
- it "arbitrary objects aren't deserialized in kitchen.local.yml" do
371
- FileUtils.mkdir_p "/tmp"
372
- File.open("/tmp/.kitchen.local.yml", "wb") do |f|
373
- f.write <<-YAML.gsub(/^ {10}/, "")
374
- --- !ruby/object:Yamled
375
- wakka: boop
376
- YAML
377
- end
378
- stub_yaml!(".kitchen.yml", Hash.new)
379
-
380
- loader.read.class.wont_equal Yamled
381
- loader.read.class.must_equal Hash
382
- loader.read.must_equal(:wakka => "boop")
383
- end
384
-
385
- it "raises a UserError if kitchen.yml cannot be parsed" do
386
- FileUtils.mkdir_p "/tmp"
387
- File.open("/tmp/.kitchen.yml", "wb") { |f| f.write "&*%^*" }
388
-
389
- err = proc { loader.read }.must_raise Kitchen::UserError
390
- err.message.must_match Regexp.new(
391
- "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
392
- end
393
-
394
- it "raises a UserError if kitchen.yml cannot be parsed" do
395
- FileUtils.mkdir_p "/tmp"
396
- File.open("/tmp/.kitchen.yml", "wb") { |f| f.write "uhoh" }
397
-
398
- err = proc { loader.read }.must_raise Kitchen::UserError
399
- err.message.must_match Regexp.new(
400
- "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
401
- end
402
-
403
- it "handles a kitchen.yml if it is a commented out YAML document" do
404
- FileUtils.mkdir_p "/tmp"
405
- File.open("/tmp/.kitchen.yml", "wb") { |f| f.write '#---\n' }
406
-
407
- loader.read.must_equal(Hash.new)
408
- end
409
-
410
- it "raises a UserError if kitchen.local.yml cannot be parsed" do
411
- FileUtils.mkdir_p "/tmp"
412
- File.open("/tmp/.kitchen.local.yml", "wb") { |f| f.write "&*%^*" }
413
- stub_yaml!(".kitchen.yml", Hash.new)
414
-
415
- proc { loader.read }.must_raise Kitchen::UserError
416
- end
417
-
418
- it "evaluates kitchen.yml through erb before loading by default" do
419
- FileUtils.mkdir_p "/tmp"
420
- File.open("/tmp/.kitchen.yml", "wb") do |f|
421
- f.write <<-'YAML'.gsub(/^ {10}/, "")
422
- ---
423
- name: <%= "AHH".downcase + "choo" %>
424
- YAML
425
- end
426
-
427
- loader.read.must_equal(:name => "ahhchoo")
428
- end
429
-
430
- it "raises a UserError if there is an ERB processing error" do
431
- FileUtils.mkdir_p "/tmp"
432
- File.open("/tmp/.kitchen.yml", "wb") do |f|
433
- f.write <<-'YAML'.gsub(/^ {10}/, "")
434
- ---
435
- <%= poop %>: yep
436
- YAML
437
- end
438
-
439
- err = proc { loader.read }.must_raise Kitchen::UserError
440
- err.message.must_match Regexp.new(
441
- "Error parsing ERB content in ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
442
- end
443
-
444
- it "evaluates kitchen.local.yml through erb before loading by default" do
445
- FileUtils.mkdir_p "/tmp"
446
- File.open("/tmp/.kitchen.local.yml", "wb") do |f|
447
- f.write <<-'YAML'.gsub(/^ {10}/, "")
448
- ---
449
- <% %w{noodle mushroom}.each do |kind| %>
450
- <%= kind %>: soup
451
- <% end %>
452
- YAML
453
- end
454
- stub_yaml!(".kitchen.yml", "spinach" => "salad")
455
-
456
- loader.read.must_equal(
457
- :spinach => "salad",
458
- :noodle => "soup",
459
- :mushroom => "soup"
460
- )
461
- end
462
-
463
- it "skips evaluating kitchen.yml through erb if disabled" do
464
- loader = Kitchen::Loader::YAML.new(
465
- :project_config => "/tmp/.kitchen.yml", :process_erb => false)
466
- FileUtils.mkdir_p "/tmp"
467
- File.open("/tmp/.kitchen.yml", "wb") do |f|
468
- f.write <<-'YAML'.gsub(/^ {10}/, "")
469
- ---
470
- name: <%= "AHH".downcase %>
471
- YAML
472
- end
473
-
474
- loader.read.must_equal(:name => '<%= "AHH".downcase %>')
475
- end
476
-
477
- it "skips evaluating kitchen.local.yml through erb if disabled" do
478
- loader = Kitchen::Loader::YAML.new(
479
- :project_config => "/tmp/.kitchen.yml", :process_erb => false)
480
- FileUtils.mkdir_p "/tmp"
481
- File.open("/tmp/.kitchen.local.yml", "wb") do |f|
482
- f.write <<-'YAML'.gsub(/^ {10}/, "")
483
- ---
484
- name: <%= "AHH".downcase %>
485
- YAML
486
- end
487
- stub_yaml!(".kitchen.yml", Hash.new)
488
-
489
- loader.read.must_equal(:name => '<%= "AHH".downcase %>')
490
- end
491
-
492
- it "skips kitchen.local.yml if disabled" do
493
- loader = Kitchen::Loader::YAML.new(
494
- :project_config => "/tmp/.kitchen.yml", :process_local => false)
495
- stub_yaml!(".kitchen.yml",
496
- "a" => "b"
497
- )
498
- stub_yaml!(".kitchen.local.yml",
499
- "superawesomesauceadditions" => "enabled, yo"
500
- )
501
-
502
- loader.read.must_equal(:a => "b")
503
- end
504
-
505
- it "skips the global config if disabled" do
506
- loader = Kitchen::Loader::YAML.new(
507
- :project_config => "/tmp/.kitchen.yml", :process_global => false)
508
- stub_yaml!(".kitchen.yml",
509
- "a" => "b"
510
- )
511
- stub_global!(
512
- "superawesomesauceadditions" => "enabled, yo"
513
- )
514
-
515
- loader.read.must_equal(:a => "b")
516
- end
517
- end
518
-
519
- describe "#diagnose" do
520
-
521
- it "returns a Hash" do
522
- stub_yaml!(Hash.new)
523
-
524
- loader.diagnose.must_be_kind_of(Hash)
525
- end
526
-
527
- it "contains erb processing information when true" do
528
- stub_yaml!(Hash.new)
529
-
530
- loader.diagnose[:process_erb].must_equal true
531
- end
532
-
533
- it "contains erb processing information when false" do
534
- stub_yaml!(Hash.new)
535
- loader = Kitchen::Loader::YAML.new(
536
- :project_config => "/tmp/.kitchen.yml", :process_erb => false)
537
-
538
- loader.diagnose[:process_erb].must_equal false
539
- end
540
-
541
- it "contains local processing information when true" do
542
- stub_yaml!(Hash.new)
543
-
544
- loader.diagnose[:process_local].must_equal true
545
- end
546
-
547
- it "contains local processing information when false" do
548
- stub_yaml!(Hash.new)
549
- loader = Kitchen::Loader::YAML.new(
550
- :project_config => "/tmp/.kitchen.yml", :process_local => false)
551
-
552
- loader.diagnose[:process_local].must_equal false
553
- end
554
-
555
- it "contains global processing information when true" do
556
- stub_yaml!(Hash.new)
557
-
558
- loader.diagnose[:process_global].must_equal true
559
- end
560
-
561
- it "contains global processing information when false" do
562
- stub_yaml!(Hash.new)
563
- loader = Kitchen::Loader::YAML.new(
564
- :project_config => "/tmp/.kitchen.yml", :process_global => false)
565
-
566
- loader.diagnose[:process_global].must_equal false
567
- end
568
-
569
- describe "for yaml files" do
570
-
571
- before do
572
- stub_yaml!(".kitchen.yml",
573
- "from_project" => "project",
574
- "common" => { "p" => "pretty" }
575
- )
576
- stub_yaml!(".kitchen.local.yml",
577
- "from_local" => "local",
578
- "common" => { "l" => "looky" }
579
- )
580
- stub_global!(
581
- "from_global" => "global",
582
- "common" => { "g" => "goody" }
583
- )
584
- end
585
-
586
- it "global config contains a filename" do
587
- loader.diagnose[:global_config][:filename].
588
- must_equal File.join(ENV["HOME"].gsub('\\', "/"), ".kitchen/config.yml")
589
- end
590
-
591
- it "global config contains raw data" do
592
- loader.diagnose[:global_config][:raw_data].must_equal(
593
- "from_global" => "global",
594
- "common" => { "g" => "goody" }
595
- )
596
- end
597
-
598
- it "project config contains a filename" do
599
- loader.diagnose[:project_config][:filename].
600
- must_match %r{/tmp/.kitchen.yml$}
601
- end
602
-
603
- it "project config contains raw data" do
604
- loader.diagnose[:project_config][:raw_data].must_equal(
605
- "from_project" => "project",
606
- "common" => { "p" => "pretty" }
607
- )
608
- end
609
-
610
- it "local config contains a filename" do
611
- loader.diagnose[:local_config][:filename].
612
- must_match %r{/tmp/.kitchen.local.yml$}
613
- end
614
-
615
- it "local config contains raw data" do
616
- loader.diagnose[:local_config][:raw_data].must_equal(
617
- "from_local" => "local",
618
- "common" => { "l" => "looky" }
619
- )
620
- end
621
-
622
- it "combined config contains a nil filename" do
623
- loader.diagnose[:combined_config][:filename].
624
- must_equal nil
625
- end
626
-
627
- it "combined config contains raw data" do
628
- loader.diagnose[:combined_config][:raw_data].must_equal(
629
- "from_global" => "global",
630
- "from_project" => "project",
631
- "from_local" => "local",
632
- "common" => {
633
- "g" => "goody",
634
- "p" => "pretty",
635
- "l" => "looky"
636
- }
637
- )
638
- end
639
-
640
- describe "for global on error" do
641
-
642
- before do
643
- FileUtils.mkdir_p(File.join(ENV["HOME"], ".kitchen"))
644
- File.open(File.join(ENV["HOME"], ".kitchen/config.yml"), "wb") do |f|
645
- f.write "&*%^*"
646
- end
647
- end
648
-
649
- it "uses an error hash with the raw file contents" do
650
- loader.diagnose[:global_config][:raw_data][:error][:raw_file].
651
- must_equal "&*%^*"
652
- end
653
-
654
- it "uses an error hash with the exception" do
655
- loader.diagnose[:global_config][:raw_data][:error][:exception].
656
- must_match %r{Kitchen::UserError}
657
- end
658
-
659
- it "uses an error hash with the exception message" do
660
- loader.diagnose[:global_config][:raw_data][:error][:message].
661
- must_match %r{Error parsing}
662
- end
663
-
664
- it "uses an error hash with the exception backtrace" do
665
- loader.diagnose[:global_config][:raw_data][:error][:backtrace].
666
- must_be_kind_of Array
667
- end
668
- end
669
-
670
- describe "for project on error" do
671
-
672
- before do
673
- File.open("/tmp/.kitchen.yml", "wb") do |f|
674
- f.write "&*%^*"
675
- end
676
- end
677
-
678
- it "uses an error hash with the raw file contents" do
679
- loader.diagnose[:project_config][:raw_data][:error][:raw_file].
680
- must_equal "&*%^*"
681
- end
682
-
683
- it "uses an error hash with the exception" do
684
- loader.diagnose[:project_config][:raw_data][:error][:exception].
685
- must_match %r{Kitchen::UserError}
686
- end
687
-
688
- it "uses an error hash with the exception message" do
689
- loader.diagnose[:project_config][:raw_data][:error][:message].
690
- must_match %r{Error parsing}
691
- end
692
-
693
- it "uses an error hash with the exception backtrace" do
694
- loader.diagnose[:project_config][:raw_data][:error][:backtrace].
695
- must_be_kind_of Array
696
- end
697
- end
698
-
699
- describe "for local on error" do
700
-
701
- before do
702
- File.open("/tmp/.kitchen.local.yml", "wb") do |f|
703
- f.write "&*%^*"
704
- end
705
- end
706
-
707
- it "uses an error hash with the raw file contents" do
708
- loader.diagnose[:local_config][:raw_data][:error][:raw_file].
709
- must_equal "&*%^*"
710
- end
711
-
712
- it "uses an error hash with the exception" do
713
- loader.diagnose[:local_config][:raw_data][:error][:exception].
714
- must_match %r{Kitchen::UserError}
715
- end
716
-
717
- it "uses an error hash with the exception message" do
718
- loader.diagnose[:local_config][:raw_data][:error][:message].
719
- must_match %r{Error parsing}
720
- end
721
-
722
- it "uses an error hash with the exception backtrace" do
723
- loader.diagnose[:local_config][:raw_data][:error][:backtrace].
724
- must_be_kind_of Array
725
- end
726
- end
727
-
728
- describe "for combined on error" do
729
-
730
- before do
731
- File.open("/tmp/.kitchen.yml", "wb") do |f|
732
- f.write "&*%^*"
733
- end
734
- end
735
-
736
- it "uses an error hash with nil raw file contents" do
737
- loader.diagnose[:combined_config][:raw_data][:error][:raw_file].
738
- must_equal nil
739
- end
740
-
741
- it "uses an error hash with the exception" do
742
- loader.diagnose[:combined_config][:raw_data][:error][:exception].
743
- must_match %r{Kitchen::UserError}
744
- end
745
-
746
- it "uses an error hash with the exception message" do
747
- loader.diagnose[:combined_config][:raw_data][:error][:message].
748
- must_match %r{Error parsing}
749
- end
750
-
751
- it "uses an error hash with the exception backtrace" do
752
- loader.diagnose[:combined_config][:raw_data][:error][:backtrace].
753
- must_be_kind_of Array
754
- end
755
- end
756
- end
757
- end
758
-
759
- private
760
-
761
- def stub_file(path, hash)
762
- FileUtils.mkdir_p(File.dirname(path))
763
- File.open(path, "wb") { |f| f.write(hash.to_yaml) }
764
- end
765
-
766
- def stub_yaml!(name = ".kitchen.yml", hash)
767
- stub_file(File.join("/tmp", name), hash)
768
- end
769
-
770
- def stub_global!(hash)
771
- stub_file(File.join(File.expand_path(ENV["HOME"]),
772
- ".kitchen", "config.yml"), hash)
773
- end
774
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, 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/errors"
22
+ require "kitchen/util"
23
+ require "kitchen/loader/yaml"
24
+
25
+ class Yamled
26
+ attr_accessor :foo
27
+ end
28
+
29
+ describe Kitchen::Loader::YAML do
30
+
31
+ let(:loader) do
32
+ Kitchen::Loader::YAML.new(:project_config => "/tmp/.kitchen.yml")
33
+ end
34
+
35
+ before do
36
+ FakeFS.activate!
37
+ FileUtils.mkdir_p("/tmp")
38
+ end
39
+
40
+ after do
41
+ FakeFS.deactivate!
42
+ FakeFS::FileSystem.clear
43
+ end
44
+
45
+ describe ".initialize" do
46
+
47
+ it "sets project_config based on Dir.pwd by default" do
48
+ stub_file(File.join(Dir.pwd, ".kitchen.yml"), Hash.new)
49
+ loader = Kitchen::Loader::YAML.new
50
+
51
+ loader.diagnose[:project_config][:filename].
52
+ must_equal File.expand_path(File.join(Dir.pwd, ".kitchen.yml"))
53
+ end
54
+
55
+ it "sets project_config from parameter, if given" do
56
+ stub_file("/tmp/crazyfunkytown.file", Hash.new)
57
+ loader = Kitchen::Loader::YAML.new(
58
+ :project_config => "/tmp/crazyfunkytown.file")
59
+
60
+ loader.diagnose[:project_config][:filename].
61
+ must_match %r{/tmp/crazyfunkytown.file$}
62
+ end
63
+
64
+ it "sets local_config based on Dir.pwd by default" do
65
+ stub_file(File.join(Dir.pwd, ".kitchen.local.yml"), Hash.new)
66
+ loader = Kitchen::Loader::YAML.new
67
+
68
+ loader.diagnose[:local_config][:filename].
69
+ must_equal File.expand_path(File.join(Dir.pwd, ".kitchen.local.yml"))
70
+ end
71
+
72
+ it "sets local_config based on location of project_config by default" do
73
+ stub_file("/tmp/.kitchen.local.yml", Hash.new)
74
+ loader = Kitchen::Loader::YAML.new(
75
+ :project_config => "/tmp/.kitchen.yml")
76
+
77
+ loader.diagnose[:local_config][:filename].
78
+ must_match %r{/tmp/.kitchen.local.yml$}
79
+ end
80
+
81
+ it "sets local_config from parameter, if given" do
82
+ stub_file("/tmp/crazyfunkytown.file", Hash.new)
83
+ loader = Kitchen::Loader::YAML.new(
84
+ :local_config => "/tmp/crazyfunkytown.file")
85
+
86
+ loader.diagnose[:local_config][:filename].
87
+ must_match %r{/tmp/crazyfunkytown.file$}
88
+ end
89
+
90
+ it "sets global_config based on ENV['HOME'] by default" do
91
+ stub_file(File.join(ENV["HOME"], ".kitchen/config.yml"), Hash.new)
92
+ loader = Kitchen::Loader::YAML.new
93
+
94
+ loader.diagnose[:global_config][:filename].must_equal File.expand_path(
95
+ File.join(ENV["HOME"], ".kitchen/config.yml"))
96
+ end
97
+
98
+ it "sets global_config from parameter, if given" do
99
+ stub_file("/tmp/crazyfunkytown.file", Hash.new)
100
+ loader = Kitchen::Loader::YAML.new(
101
+ :global_config => "/tmp/crazyfunkytown.file")
102
+
103
+ loader.diagnose[:global_config][:filename].
104
+ must_match %r{/tmp/crazyfunkytown.file$}
105
+ end
106
+ end
107
+
108
+ describe "#read" do
109
+
110
+ it "returns a hash of kitchen.yml with symbolized keys" do
111
+ stub_yaml!(
112
+ "foo" => "bar"
113
+ )
114
+
115
+ loader.read.must_equal(:foo => "bar")
116
+ end
117
+
118
+ it "deep merges in kitchen.local.yml configuration with kitchen.yml" do
119
+ stub_yaml!(".kitchen.yml",
120
+ "common" => { "xx" => 1 },
121
+ "a" => "b"
122
+ )
123
+ stub_yaml!(".kitchen.local.yml",
124
+ "common" => { "yy" => 2 },
125
+ "c" => "d"
126
+ )
127
+
128
+ loader.read.must_equal(
129
+ :a => "b",
130
+ :c => "d",
131
+ :common => { :xx => 1, :yy => 2 }
132
+ )
133
+ end
134
+
135
+ it "deep merges in a global config file with all other configs" do
136
+ stub_yaml!(".kitchen.yml",
137
+ "common" => { "xx" => 1 },
138
+ "a" => "b"
139
+ )
140
+ stub_yaml!(".kitchen.local.yml",
141
+ "common" => { "yy" => 2 },
142
+ "c" => "d"
143
+ )
144
+ stub_global!(
145
+ "common" => { "zz" => 3 },
146
+ "e" => "f"
147
+ )
148
+
149
+ loader.read.must_equal(
150
+ :a => "b",
151
+ :c => "d",
152
+ :e => "f",
153
+ :common => { :xx => 1, :yy => 2, :zz => 3 }
154
+ )
155
+ end
156
+
157
+ it "merges kitchen.yml over configuration in global config" do
158
+ stub_global!(
159
+ "common" => { "thekey" => "nope" }
160
+ )
161
+ stub_yaml!(".kitchen.yml",
162
+ "common" => { "thekey" => "yep" }
163
+ )
164
+
165
+ loader.read.must_equal(:common => { :thekey => "yep" })
166
+ end
167
+
168
+ it "merges kitchen.local.yml over configuration in kitchen.yml" do
169
+ stub_yaml!(".kitchen.yml",
170
+ "common" => { "thekey" => "nope" }
171
+ )
172
+ stub_yaml!(".kitchen.local.yml",
173
+ "common" => { "thekey" => "yep" }
174
+ )
175
+
176
+ loader.read.must_equal(:common => { :thekey => "yep" })
177
+ end
178
+
179
+ it "merges kitchen.local.yml over both kitchen.yml and global config" do
180
+ stub_yaml!(".kitchen.yml",
181
+ "common" => { "thekey" => "nope" }
182
+ )
183
+ stub_yaml!(".kitchen.local.yml",
184
+ "common" => { "thekey" => "yep" }
185
+ )
186
+ stub_global!(
187
+ "common" => { "thekey" => "kinda" }
188
+ )
189
+
190
+ loader.read.must_equal(:common => { :thekey => "yep" })
191
+ end
192
+
193
+ NORMALIZED_KEYS = {
194
+ "driver" => "name",
195
+ "provisioner" => "name",
196
+ "busser" => "version"
197
+ }
198
+
199
+ NORMALIZED_KEYS.each do |key, default_key|
200
+
201
+ describe "normalizing #{key} config hashes" do
202
+
203
+ it "merges local with #{key} string value over yaml with hash value" do
204
+ stub_yaml!(".kitchen.yml",
205
+ key => { "dakey" => "ya" }
206
+ )
207
+ stub_yaml!(".kitchen.local.yml",
208
+ key => "namey"
209
+ )
210
+
211
+ loader.read.must_equal(
212
+ key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
213
+ )
214
+ end
215
+
216
+ it "merges local with #{key} hash value over yaml with string value" do
217
+ stub_yaml!(".kitchen.yml",
218
+ key => "namey"
219
+ )
220
+ stub_yaml!(".kitchen.local.yml",
221
+ key => { "dakey" => "ya" }
222
+ )
223
+
224
+ loader.read.must_equal(
225
+ key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
226
+ )
227
+ end
228
+
229
+ it "merges local with #{key} nil value over yaml with hash value" do
230
+ stub_yaml!(".kitchen.yml",
231
+ key => { "dakey" => "ya" }
232
+ )
233
+ stub_yaml!(".kitchen.local.yml",
234
+ key => nil
235
+ )
236
+
237
+ loader.read.must_equal(
238
+ key.to_sym => { :dakey => "ya" }
239
+ )
240
+ end
241
+
242
+ it "merges local with #{key} hash value over yaml with nil value" do
243
+ stub_yaml!(".kitchen.yml",
244
+ key => "namey"
245
+ )
246
+ stub_yaml!(".kitchen.local.yml",
247
+ key => nil
248
+ )
249
+
250
+ loader.read.must_equal(
251
+ key.to_sym => { default_key.to_sym => "namey" }
252
+ )
253
+ end
254
+
255
+ it "merges global with #{key} string value over yaml with hash value" do
256
+ stub_yaml!(".kitchen.yml",
257
+ key => { "dakey" => "ya" }
258
+ )
259
+ stub_global!(
260
+ key => "namey"
261
+ )
262
+
263
+ loader.read.must_equal(
264
+ key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
265
+ )
266
+ end
267
+
268
+ it "merges global with #{key} hash value over yaml with string value" do
269
+ stub_yaml!(".kitchen.yml",
270
+ key => "namey"
271
+ )
272
+ stub_global!(
273
+ key => { "dakey" => "ya" }
274
+ )
275
+
276
+ loader.read.must_equal(
277
+ key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
278
+ )
279
+ end
280
+
281
+ it "merges global with #{key} nil value over yaml with hash value" do
282
+ stub_yaml!(".kitchen.yml",
283
+ key => { "dakey" => "ya" }
284
+ )
285
+ stub_global!(
286
+ key => nil
287
+ )
288
+
289
+ loader.read.must_equal(
290
+ key.to_sym => { :dakey => "ya" }
291
+ )
292
+ end
293
+
294
+ it "merges global with #{key} hash value over yaml with nil value" do
295
+ stub_yaml!(".kitchen.yml",
296
+ key => nil
297
+ )
298
+ stub_global!(
299
+ key => { "dakey" => "ya" }
300
+ )
301
+
302
+ loader.read.must_equal(
303
+ key.to_sym => { :dakey => "ya" }
304
+ )
305
+ end
306
+
307
+ it "merges global, local, over yaml with mixed hash, string, nil values" do
308
+ stub_yaml!(".kitchen.yml",
309
+ key => nil
310
+ )
311
+ stub_yaml!(".kitchen.local.yml",
312
+ key => "namey"
313
+ )
314
+ stub_global!(
315
+ key => { "dakey" => "ya" }
316
+ )
317
+
318
+ loader.read.must_equal(
319
+ key.to_sym => { default_key.to_sym => "namey", :dakey => "ya" }
320
+ )
321
+ end
322
+ end
323
+ end
324
+
325
+ it "handles a kitchen.local.yml with no yaml elements" do
326
+ stub_yaml!(".kitchen.yml",
327
+ "a" => "b"
328
+ )
329
+ stub_yaml!(".kitchen.local.yml", Hash.new)
330
+
331
+ loader.read.must_equal(:a => "b")
332
+ end
333
+
334
+ it "handles a kitchen.yml with no yaml elements" do
335
+ stub_yaml!(".kitchen.yml", Hash.new)
336
+ stub_yaml!(".kitchen.local.yml",
337
+ "a" => "b"
338
+ )
339
+
340
+ loader.read.must_equal(:a => "b")
341
+ end
342
+
343
+ it "handles a kitchen.yml with yaml elements that parse as nil" do
344
+ stub_yaml!(".kitchen.yml", nil)
345
+ stub_yaml!(".kitchen.local.yml",
346
+ "a" => "b"
347
+ )
348
+
349
+ loader.read.must_equal(:a => "b")
350
+ end
351
+
352
+ it "raises an UserError if the config_file does not exist" do
353
+ proc { loader.read }.must_raise Kitchen::UserError
354
+ end
355
+
356
+ it "arbitrary objects aren't deserialized in kitchen.yml" do
357
+ FileUtils.mkdir_p "/tmp"
358
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
359
+ f.write <<-YAML.gsub(/^ {10}/, "")
360
+ --- !ruby/object:Yamled
361
+ foo: bar
362
+ YAML
363
+ end
364
+
365
+ loader.read.class.wont_equal Yamled
366
+ loader.read.class.must_equal Hash
367
+ loader.read.must_equal(:foo => "bar")
368
+ end
369
+
370
+ it "arbitrary objects aren't deserialized in kitchen.local.yml" do
371
+ FileUtils.mkdir_p "/tmp"
372
+ File.open("/tmp/.kitchen.local.yml", "wb") do |f|
373
+ f.write <<-YAML.gsub(/^ {10}/, "")
374
+ --- !ruby/object:Yamled
375
+ wakka: boop
376
+ YAML
377
+ end
378
+ stub_yaml!(".kitchen.yml", Hash.new)
379
+
380
+ loader.read.class.wont_equal Yamled
381
+ loader.read.class.must_equal Hash
382
+ loader.read.must_equal(:wakka => "boop")
383
+ end
384
+
385
+ it "raises a UserError if kitchen.yml cannot be parsed" do
386
+ FileUtils.mkdir_p "/tmp"
387
+ File.open("/tmp/.kitchen.yml", "wb") { |f| f.write "&*%^*" }
388
+
389
+ err = proc { loader.read }.must_raise Kitchen::UserError
390
+ err.message.must_match Regexp.new(
391
+ "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
392
+ end
393
+
394
+ it "raises a UserError if kitchen.yml cannot be parsed" do
395
+ FileUtils.mkdir_p "/tmp"
396
+ File.open("/tmp/.kitchen.yml", "wb") { |f| f.write "uhoh" }
397
+
398
+ err = proc { loader.read }.must_raise Kitchen::UserError
399
+ err.message.must_match Regexp.new(
400
+ "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
401
+ end
402
+
403
+ it "handles a kitchen.yml if it is a commented out YAML document" do
404
+ FileUtils.mkdir_p "/tmp"
405
+ File.open("/tmp/.kitchen.yml", "wb") { |f| f.write '#---\n' }
406
+
407
+ loader.read.must_equal(Hash.new)
408
+ end
409
+
410
+ it "raises a UserError if kitchen.local.yml cannot be parsed" do
411
+ FileUtils.mkdir_p "/tmp"
412
+ File.open("/tmp/.kitchen.local.yml", "wb") { |f| f.write "&*%^*" }
413
+ stub_yaml!(".kitchen.yml", Hash.new)
414
+
415
+ proc { loader.read }.must_raise Kitchen::UserError
416
+ end
417
+
418
+ it "evaluates kitchen.yml through erb before loading by default" do
419
+ FileUtils.mkdir_p "/tmp"
420
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
421
+ f.write <<-'YAML'.gsub(/^ {10}/, "")
422
+ ---
423
+ name: <%= "AHH".downcase + "choo" %>
424
+ YAML
425
+ end
426
+
427
+ loader.read.must_equal(:name => "ahhchoo")
428
+ end
429
+
430
+ it "raises a UserError if there is an ERB processing error" do
431
+ FileUtils.mkdir_p "/tmp"
432
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
433
+ f.write <<-'YAML'.gsub(/^ {10}/, "")
434
+ ---
435
+ <%= poop %>: yep
436
+ YAML
437
+ end
438
+
439
+ err = proc { loader.read }.must_raise Kitchen::UserError
440
+ err.message.must_match Regexp.new(
441
+ "Error parsing ERB content in ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
442
+ end
443
+
444
+ it "evaluates kitchen.local.yml through erb before loading by default" do
445
+ FileUtils.mkdir_p "/tmp"
446
+ File.open("/tmp/.kitchen.local.yml", "wb") do |f|
447
+ f.write <<-'YAML'.gsub(/^ {10}/, "")
448
+ ---
449
+ <% %w{noodle mushroom}.each do |kind| %>
450
+ <%= kind %>: soup
451
+ <% end %>
452
+ YAML
453
+ end
454
+ stub_yaml!(".kitchen.yml", "spinach" => "salad")
455
+
456
+ loader.read.must_equal(
457
+ :spinach => "salad",
458
+ :noodle => "soup",
459
+ :mushroom => "soup"
460
+ )
461
+ end
462
+
463
+ it "skips evaluating kitchen.yml through erb if disabled" do
464
+ loader = Kitchen::Loader::YAML.new(
465
+ :project_config => "/tmp/.kitchen.yml", :process_erb => false)
466
+ FileUtils.mkdir_p "/tmp"
467
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
468
+ f.write <<-'YAML'.gsub(/^ {10}/, "")
469
+ ---
470
+ name: <%= "AHH".downcase %>
471
+ YAML
472
+ end
473
+
474
+ loader.read.must_equal(:name => '<%= "AHH".downcase %>')
475
+ end
476
+
477
+ it "skips evaluating kitchen.local.yml through erb if disabled" do
478
+ loader = Kitchen::Loader::YAML.new(
479
+ :project_config => "/tmp/.kitchen.yml", :process_erb => false)
480
+ FileUtils.mkdir_p "/tmp"
481
+ File.open("/tmp/.kitchen.local.yml", "wb") do |f|
482
+ f.write <<-'YAML'.gsub(/^ {10}/, "")
483
+ ---
484
+ name: <%= "AHH".downcase %>
485
+ YAML
486
+ end
487
+ stub_yaml!(".kitchen.yml", Hash.new)
488
+
489
+ loader.read.must_equal(:name => '<%= "AHH".downcase %>')
490
+ end
491
+
492
+ it "skips kitchen.local.yml if disabled" do
493
+ loader = Kitchen::Loader::YAML.new(
494
+ :project_config => "/tmp/.kitchen.yml", :process_local => false)
495
+ stub_yaml!(".kitchen.yml",
496
+ "a" => "b"
497
+ )
498
+ stub_yaml!(".kitchen.local.yml",
499
+ "superawesomesauceadditions" => "enabled, yo"
500
+ )
501
+
502
+ loader.read.must_equal(:a => "b")
503
+ end
504
+
505
+ it "skips the global config if disabled" do
506
+ loader = Kitchen::Loader::YAML.new(
507
+ :project_config => "/tmp/.kitchen.yml", :process_global => false)
508
+ stub_yaml!(".kitchen.yml",
509
+ "a" => "b"
510
+ )
511
+ stub_global!(
512
+ "superawesomesauceadditions" => "enabled, yo"
513
+ )
514
+
515
+ loader.read.must_equal(:a => "b")
516
+ end
517
+ end
518
+
519
+ describe "#diagnose" do
520
+
521
+ it "returns a Hash" do
522
+ stub_yaml!(Hash.new)
523
+
524
+ loader.diagnose.must_be_kind_of(Hash)
525
+ end
526
+
527
+ it "contains erb processing information when true" do
528
+ stub_yaml!(Hash.new)
529
+
530
+ loader.diagnose[:process_erb].must_equal true
531
+ end
532
+
533
+ it "contains erb processing information when false" do
534
+ stub_yaml!(Hash.new)
535
+ loader = Kitchen::Loader::YAML.new(
536
+ :project_config => "/tmp/.kitchen.yml", :process_erb => false)
537
+
538
+ loader.diagnose[:process_erb].must_equal false
539
+ end
540
+
541
+ it "contains local processing information when true" do
542
+ stub_yaml!(Hash.new)
543
+
544
+ loader.diagnose[:process_local].must_equal true
545
+ end
546
+
547
+ it "contains local processing information when false" do
548
+ stub_yaml!(Hash.new)
549
+ loader = Kitchen::Loader::YAML.new(
550
+ :project_config => "/tmp/.kitchen.yml", :process_local => false)
551
+
552
+ loader.diagnose[:process_local].must_equal false
553
+ end
554
+
555
+ it "contains global processing information when true" do
556
+ stub_yaml!(Hash.new)
557
+
558
+ loader.diagnose[:process_global].must_equal true
559
+ end
560
+
561
+ it "contains global processing information when false" do
562
+ stub_yaml!(Hash.new)
563
+ loader = Kitchen::Loader::YAML.new(
564
+ :project_config => "/tmp/.kitchen.yml", :process_global => false)
565
+
566
+ loader.diagnose[:process_global].must_equal false
567
+ end
568
+
569
+ describe "for yaml files" do
570
+
571
+ before do
572
+ stub_yaml!(".kitchen.yml",
573
+ "from_project" => "project",
574
+ "common" => { "p" => "pretty" }
575
+ )
576
+ stub_yaml!(".kitchen.local.yml",
577
+ "from_local" => "local",
578
+ "common" => { "l" => "looky" }
579
+ )
580
+ stub_global!(
581
+ "from_global" => "global",
582
+ "common" => { "g" => "goody" }
583
+ )
584
+ end
585
+
586
+ it "global config contains a filename" do
587
+ loader.diagnose[:global_config][:filename].
588
+ must_equal File.join(ENV["HOME"].gsub('\\', "/"), ".kitchen/config.yml")
589
+ end
590
+
591
+ it "global config contains raw data" do
592
+ loader.diagnose[:global_config][:raw_data].must_equal(
593
+ "from_global" => "global",
594
+ "common" => { "g" => "goody" }
595
+ )
596
+ end
597
+
598
+ it "project config contains a filename" do
599
+ loader.diagnose[:project_config][:filename].
600
+ must_match %r{/tmp/.kitchen.yml$}
601
+ end
602
+
603
+ it "project config contains raw data" do
604
+ loader.diagnose[:project_config][:raw_data].must_equal(
605
+ "from_project" => "project",
606
+ "common" => { "p" => "pretty" }
607
+ )
608
+ end
609
+
610
+ it "local config contains a filename" do
611
+ loader.diagnose[:local_config][:filename].
612
+ must_match %r{/tmp/.kitchen.local.yml$}
613
+ end
614
+
615
+ it "local config contains raw data" do
616
+ loader.diagnose[:local_config][:raw_data].must_equal(
617
+ "from_local" => "local",
618
+ "common" => { "l" => "looky" }
619
+ )
620
+ end
621
+
622
+ it "combined config contains a nil filename" do
623
+ loader.diagnose[:combined_config][:filename].
624
+ must_equal nil
625
+ end
626
+
627
+ it "combined config contains raw data" do
628
+ loader.diagnose[:combined_config][:raw_data].must_equal(
629
+ "from_global" => "global",
630
+ "from_project" => "project",
631
+ "from_local" => "local",
632
+ "common" => {
633
+ "g" => "goody",
634
+ "p" => "pretty",
635
+ "l" => "looky"
636
+ }
637
+ )
638
+ end
639
+
640
+ describe "for global on error" do
641
+
642
+ before do
643
+ FileUtils.mkdir_p(File.join(ENV["HOME"], ".kitchen"))
644
+ File.open(File.join(ENV["HOME"], ".kitchen/config.yml"), "wb") do |f|
645
+ f.write "&*%^*"
646
+ end
647
+ end
648
+
649
+ it "uses an error hash with the raw file contents" do
650
+ loader.diagnose[:global_config][:raw_data][:error][:raw_file].
651
+ must_equal "&*%^*"
652
+ end
653
+
654
+ it "uses an error hash with the exception" do
655
+ loader.diagnose[:global_config][:raw_data][:error][:exception].
656
+ must_match %r{Kitchen::UserError}
657
+ end
658
+
659
+ it "uses an error hash with the exception message" do
660
+ loader.diagnose[:global_config][:raw_data][:error][:message].
661
+ must_match %r{Error parsing}
662
+ end
663
+
664
+ it "uses an error hash with the exception backtrace" do
665
+ loader.diagnose[:global_config][:raw_data][:error][:backtrace].
666
+ must_be_kind_of Array
667
+ end
668
+ end
669
+
670
+ describe "for project on error" do
671
+
672
+ before do
673
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
674
+ f.write "&*%^*"
675
+ end
676
+ end
677
+
678
+ it "uses an error hash with the raw file contents" do
679
+ loader.diagnose[:project_config][:raw_data][:error][:raw_file].
680
+ must_equal "&*%^*"
681
+ end
682
+
683
+ it "uses an error hash with the exception" do
684
+ loader.diagnose[:project_config][:raw_data][:error][:exception].
685
+ must_match %r{Kitchen::UserError}
686
+ end
687
+
688
+ it "uses an error hash with the exception message" do
689
+ loader.diagnose[:project_config][:raw_data][:error][:message].
690
+ must_match %r{Error parsing}
691
+ end
692
+
693
+ it "uses an error hash with the exception backtrace" do
694
+ loader.diagnose[:project_config][:raw_data][:error][:backtrace].
695
+ must_be_kind_of Array
696
+ end
697
+ end
698
+
699
+ describe "for local on error" do
700
+
701
+ before do
702
+ File.open("/tmp/.kitchen.local.yml", "wb") do |f|
703
+ f.write "&*%^*"
704
+ end
705
+ end
706
+
707
+ it "uses an error hash with the raw file contents" do
708
+ loader.diagnose[:local_config][:raw_data][:error][:raw_file].
709
+ must_equal "&*%^*"
710
+ end
711
+
712
+ it "uses an error hash with the exception" do
713
+ loader.diagnose[:local_config][:raw_data][:error][:exception].
714
+ must_match %r{Kitchen::UserError}
715
+ end
716
+
717
+ it "uses an error hash with the exception message" do
718
+ loader.diagnose[:local_config][:raw_data][:error][:message].
719
+ must_match %r{Error parsing}
720
+ end
721
+
722
+ it "uses an error hash with the exception backtrace" do
723
+ loader.diagnose[:local_config][:raw_data][:error][:backtrace].
724
+ must_be_kind_of Array
725
+ end
726
+ end
727
+
728
+ describe "for combined on error" do
729
+
730
+ before do
731
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
732
+ f.write "&*%^*"
733
+ end
734
+ end
735
+
736
+ it "uses an error hash with nil raw file contents" do
737
+ loader.diagnose[:combined_config][:raw_data][:error][:raw_file].
738
+ must_equal nil
739
+ end
740
+
741
+ it "uses an error hash with the exception" do
742
+ loader.diagnose[:combined_config][:raw_data][:error][:exception].
743
+ must_match %r{Kitchen::UserError}
744
+ end
745
+
746
+ it "uses an error hash with the exception message" do
747
+ loader.diagnose[:combined_config][:raw_data][:error][:message].
748
+ must_match %r{Error parsing}
749
+ end
750
+
751
+ it "uses an error hash with the exception backtrace" do
752
+ loader.diagnose[:combined_config][:raw_data][:error][:backtrace].
753
+ must_be_kind_of Array
754
+ end
755
+ end
756
+ end
757
+ end
758
+
759
+ private
760
+
761
+ def stub_file(path, hash)
762
+ FileUtils.mkdir_p(File.dirname(path))
763
+ File.open(path, "wb") { |f| f.write(hash.to_yaml) }
764
+ end
765
+
766
+ def stub_yaml!(name = ".kitchen.yml", hash)
767
+ stub_file(File.join("/tmp", name), hash)
768
+ end
769
+
770
+ def stub_global!(hash)
771
+ stub_file(File.join(File.expand_path(ENV["HOME"]),
772
+ ".kitchen", "config.yml"), hash)
773
+ end
774
+ end