microwave 1.0.4 → 11.400.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. data/CONTRIBUTING.md +155 -0
  2. data/README.md +89 -0
  3. data/Rakefile +2 -2
  4. data/bin/chef-apply +25 -0
  5. data/bin/chef-shell +34 -0
  6. data/bin/chef-solo +0 -2
  7. data/bin/shef +6 -5
  8. data/lib/chef.rb +2 -4
  9. data/spec/data/big_json.json +2 -1
  10. data/spec/data/big_json_plus_one.json +2 -1
  11. data/spec/data/cookbooks/chefignore +2 -0
  12. data/spec/data/cookbooks/openldap/attributes/default.rb +10 -9
  13. data/spec/data/cookbooks/openldap/attributes/smokey.rb +1 -1
  14. data/spec/data/git_bundles/sinatra-test-app-with-callback-files.gitbundle +0 -0
  15. data/spec/data/git_bundles/sinatra-test-app-with-symlinks.gitbundle +0 -0
  16. data/spec/data/git_bundles/sinatra-test-app.gitbundle +0 -0
  17. data/spec/data/lwrp/providers/inline_compiler.rb +26 -0
  18. data/spec/data/nodes/default.rb +3 -3
  19. data/spec/data/nodes/test.example.com.rb +3 -3
  20. data/spec/data/nodes/test.rb +3 -3
  21. data/spec/data/partial_one.erb +1 -0
  22. data/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb +4 -0
  23. data/spec/data/run_context/cookbooks/circular-dep1/definitions/circular_dep1_res.rb +1 -0
  24. data/spec/data/run_context/cookbooks/circular-dep1/libraries/lib.rb +2 -0
  25. data/spec/data/run_context/cookbooks/circular-dep1/metadata.rb +2 -0
  26. data/spec/data/run_context/cookbooks/circular-dep1/providers/provider.rb +1 -0
  27. data/spec/data/run_context/cookbooks/circular-dep1/recipes/default.rb +0 -0
  28. data/spec/data/run_context/cookbooks/circular-dep1/resources/resource.rb +1 -0
  29. data/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb +3 -0
  30. data/spec/data/run_context/cookbooks/circular-dep2/definitions/circular_dep2_res.rb +1 -0
  31. data/spec/data/run_context/cookbooks/circular-dep2/libraries/lib.rb +2 -0
  32. data/spec/data/run_context/cookbooks/circular-dep2/metadata.rb +2 -0
  33. data/spec/data/run_context/cookbooks/circular-dep2/providers/provider.rb +1 -0
  34. data/spec/data/run_context/cookbooks/circular-dep2/recipes/default.rb +0 -0
  35. data/spec/data/run_context/cookbooks/circular-dep2/resources/resource.rb +1 -0
  36. data/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb +2 -0
  37. data/spec/data/run_context/cookbooks/dependency1/attributes/default.rb +2 -0
  38. data/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb +3 -0
  39. data/spec/data/run_context/cookbooks/dependency1/definitions/dependency1_res.rb +1 -0
  40. data/spec/data/run_context/cookbooks/dependency1/libraries/lib.rb +2 -0
  41. data/spec/data/run_context/cookbooks/dependency1/providers/provider.rb +1 -0
  42. data/spec/data/run_context/cookbooks/dependency1/recipes/default.rb +0 -0
  43. data/spec/data/run_context/cookbooks/dependency1/resources/resource.rb +1 -0
  44. data/spec/data/run_context/cookbooks/dependency2/attributes/default.rb +3 -0
  45. data/spec/data/run_context/cookbooks/dependency2/definitions/dependency2_res.rb +1 -0
  46. data/spec/data/run_context/cookbooks/dependency2/libraries/lib.rb +2 -0
  47. data/spec/data/run_context/cookbooks/dependency2/providers/provider.rb +1 -0
  48. data/spec/data/run_context/cookbooks/dependency2/recipes/default.rb +0 -0
  49. data/spec/data/run_context/cookbooks/dependency2/resources/resource.rb +1 -0
  50. data/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb +3 -0
  51. data/spec/data/run_context/cookbooks/no-default-attr/definitions/no_default-attr_res.rb +1 -0
  52. data/spec/data/run_context/cookbooks/no-default-attr/providers/provider.rb +1 -0
  53. data/spec/data/run_context/cookbooks/no-default-attr/recipes/default.rb +0 -0
  54. data/spec/data/run_context/cookbooks/no-default-attr/resources/resource.rb +1 -0
  55. data/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb +3 -0
  56. data/spec/data/run_context/cookbooks/test-with-circular-deps/definitions/test_with-circular-deps_res.rb +1 -0
  57. data/spec/data/run_context/cookbooks/test-with-circular-deps/libraries/lib.rb +2 -0
  58. data/spec/data/run_context/cookbooks/test-with-circular-deps/metadata.rb +2 -0
  59. data/spec/data/run_context/cookbooks/test-with-circular-deps/providers/provider.rb +1 -0
  60. data/spec/data/run_context/cookbooks/test-with-circular-deps/recipes/default.rb +0 -0
  61. data/spec/data/run_context/cookbooks/test-with-circular-deps/resources/resource.rb +1 -0
  62. data/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb +3 -0
  63. data/spec/data/run_context/cookbooks/test-with-deps/definitions/test_with-deps_res.rb +1 -0
  64. data/spec/data/run_context/cookbooks/test-with-deps/libraries/lib.rb +1 -0
  65. data/spec/data/run_context/cookbooks/test-with-deps/metadata.rb +3 -0
  66. data/spec/data/run_context/cookbooks/test-with-deps/providers/provider.rb +1 -0
  67. data/spec/data/run_context/cookbooks/test-with-deps/recipes/default.rb +0 -0
  68. data/spec/data/run_context/cookbooks/test-with-deps/recipes/server.rb +0 -0
  69. data/spec/data/run_context/cookbooks/test-with-deps/resources/resource.rb +1 -0
  70. data/spec/data/run_context/cookbooks/test/attributes/default.rb +0 -0
  71. data/spec/data/run_context/cookbooks/test/attributes/george.rb +1 -1
  72. data/spec/data/run_context/cookbooks/test/definitions/test_res.rb +1 -0
  73. data/spec/data/run_context/cookbooks/test/providers/provider.rb +1 -0
  74. data/spec/data/run_context/cookbooks/test/resources/resource.rb +1 -0
  75. data/spec/data/shef-config.rb +10 -0
  76. data/spec/functional/dsl/registry_helper_spec.rb +63 -0
  77. data/spec/functional/knife/cookbook_delete_spec.rb +0 -2
  78. data/spec/functional/knife/exec_spec.rb +4 -6
  79. data/spec/functional/knife/smoke_test.rb +34 -0
  80. data/spec/functional/knife/ssh_spec.rb +64 -3
  81. data/spec/functional/resource/cookbook_file_spec.rb +33 -2
  82. data/spec/functional/resource/deploy_revision_spec.rb +515 -0
  83. data/spec/functional/resource/directory_spec.rb +4 -0
  84. data/spec/functional/resource/file_spec.rb +56 -22
  85. data/spec/functional/resource/link_spec.rb +12 -10
  86. data/spec/functional/resource/registry_spec.rb +572 -0
  87. data/spec/functional/resource/remote_directory_spec.rb +142 -36
  88. data/spec/functional/resource/remote_file_spec.rb +28 -3
  89. data/spec/functional/resource/template_spec.rb +23 -2
  90. data/spec/functional/run_lock_spec.rb +238 -0
  91. data/spec/functional/shell_spec.rb +101 -0
  92. data/spec/functional/tiny_server_spec.rb +5 -4
  93. data/spec/functional/win32/registry_helper_spec.rb +632 -0
  94. data/spec/functional/win32/security_spec.rb +37 -0
  95. data/spec/spec_helper.rb +15 -3
  96. data/spec/stress/win32/security_spec.rb +5 -5
  97. data/spec/support/chef_helpers.rb +14 -3
  98. data/spec/support/lib/chef/resource/cat.rb +3 -5
  99. data/spec/support/lib/chef/resource/one_two_three_four.rb +8 -10
  100. data/spec/support/lib/chef/resource/zen_master.rb +8 -10
  101. data/spec/support/matchers/leak.rb +1 -1
  102. data/spec/support/platform_helpers.rb +18 -0
  103. data/spec/support/shared/functional/directory_resource.rb +85 -23
  104. data/spec/support/shared/functional/file_resource.rb +198 -53
  105. data/spec/support/shared/functional/securable_resource.rb +140 -105
  106. data/spec/support/shared/functional/securable_resource_with_reporting.rb +375 -0
  107. data/spec/support/shared/unit/file_system_support.rb +110 -0
  108. data/spec/support/shared/unit/platform_introspector.rb +162 -0
  109. data/spec/tiny_server.rb +29 -10
  110. data/spec/unit/api_client/registration_spec.rb +172 -0
  111. data/spec/unit/api_client_spec.rb +156 -103
  112. data/spec/unit/application/apply.rb +84 -0
  113. data/spec/unit/application/knife_spec.rb +5 -0
  114. data/spec/unit/application_spec.rb +57 -2
  115. data/spec/unit/chef_fs/diff_spec.rb +329 -0
  116. data/spec/unit/chef_fs/file_pattern_spec.rb +526 -0
  117. data/spec/unit/chef_fs/file_system/chef_server_root_dir_spec.rb +237 -0
  118. data/spec/unit/chef_fs/file_system/cookbooks_dir_spec.rb +568 -0
  119. data/spec/unit/chef_fs/file_system/data_bags_dir_spec.rb +220 -0
  120. data/spec/unit/chef_fs/file_system_spec.rb +136 -0
  121. data/spec/unit/client_spec.rb +188 -16
  122. data/spec/unit/config_spec.rb +54 -4
  123. data/spec/unit/cookbook/chefignore_spec.rb +2 -1
  124. data/spec/unit/cookbook/syntax_check_spec.rb +48 -109
  125. data/spec/unit/cookbook_loader_spec.rb +153 -91
  126. data/spec/unit/cookbook_manifest_spec.rb +81 -81
  127. data/spec/unit/cookbook_spec.rb +3 -20
  128. data/spec/unit/cookbook_version_spec.rb +23 -122
  129. data/spec/unit/digester_spec.rb +50 -0
  130. data/spec/unit/dsl/data_query_spec.rb +66 -0
  131. data/spec/unit/dsl/platform_introspection_spec.rb +130 -0
  132. data/spec/unit/dsl/regsitry_helper_spec.rb +55 -0
  133. data/spec/unit/encrypted_data_bag_item_spec.rb +126 -10
  134. data/spec/unit/environment_spec.rb +0 -130
  135. data/spec/unit/exceptions_spec.rb +2 -3
  136. data/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb +23 -3
  137. data/spec/unit/json_compat_spec.rb +69 -0
  138. data/spec/unit/knife/bootstrap_spec.rb +81 -28
  139. data/spec/unit/knife/client_reregister_spec.rb +23 -22
  140. data/spec/unit/knife/configure_spec.rb +29 -26
  141. data/spec/unit/knife/cookbook_metadata_spec.rb +11 -4
  142. data/spec/unit/knife/cookbook_site_install_spec.rb +12 -2
  143. data/spec/unit/knife/cookbook_test_spec.rb +1 -0
  144. data/spec/unit/knife/cookbook_upload_spec.rb +41 -2
  145. data/spec/unit/knife/core/bootstrap_context_spec.rb +8 -1
  146. data/spec/unit/knife/core/ui_spec.rb +156 -7
  147. data/spec/unit/knife/data_bag_create_spec.rb +14 -0
  148. data/spec/unit/knife/data_bag_edit_spec.rb +14 -4
  149. data/spec/unit/knife/data_bag_from_file_spec.rb +17 -5
  150. data/spec/unit/knife/data_bag_show_spec.rb +11 -4
  151. data/spec/unit/knife/index_rebuild_spec.rb +96 -33
  152. data/spec/unit/knife/knife_help.rb +7 -7
  153. data/spec/unit/knife/node_run_list_remove_spec.rb +2 -1
  154. data/spec/unit/knife/ssh_spec.rb +121 -15
  155. data/spec/unit/knife/status_spec.rb +2 -2
  156. data/spec/unit/knife/user_create_spec.rb +86 -0
  157. data/spec/unit/knife/user_delete_spec.rb +39 -0
  158. data/spec/unit/knife/user_edit_spec.rb +42 -0
  159. data/spec/unit/knife/user_list_spec.rb +32 -0
  160. data/spec/unit/knife/user_reregister_spec.rb +53 -0
  161. data/spec/unit/knife/user_show_spec.rb +41 -0
  162. data/spec/unit/knife_spec.rb +53 -0
  163. data/spec/unit/lwrp_spec.rb +59 -17
  164. data/spec/unit/mixin/checksum_spec.rb +2 -2
  165. data/spec/unit/mixin/deep_merge_spec.rb +56 -491
  166. data/spec/unit/mixin/deprecation_spec.rb +23 -0
  167. data/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb +6 -1
  168. data/spec/unit/mixin/params_validate_spec.rb +4 -2
  169. data/spec/unit/mixin/securable_spec.rb +5 -3
  170. data/spec/unit/mixin/template_spec.rb +119 -0
  171. data/spec/unit/node/attribute_spec.rb +272 -137
  172. data/spec/unit/node/immutable_collections_spec.rb +139 -0
  173. data/spec/unit/node_spec.rb +411 -339
  174. data/spec/unit/platform_spec.rb +8 -8
  175. data/spec/unit/provider/breakpoint_spec.rb +8 -8
  176. data/spec/unit/provider/cookbook_file_spec.rb +4 -8
  177. data/spec/unit/provider/deploy/revision_spec.rb +2 -8
  178. data/spec/unit/provider/deploy_spec.rb +6 -40
  179. data/spec/unit/provider/directory_spec.rb +103 -68
  180. data/spec/unit/provider/erl_call_spec.rb +0 -2
  181. data/spec/unit/provider/file_spec.rb +69 -59
  182. data/spec/unit/provider/git_spec.rb +0 -10
  183. data/spec/unit/provider/group/groupadd_spec.rb +1 -1
  184. data/spec/unit/provider/group/usermod_spec.rb +2 -2
  185. data/spec/unit/provider/http_request_spec.rb +28 -69
  186. data/spec/unit/provider/ifconfig_spec.rb +2 -2
  187. data/spec/unit/provider/link_spec.rb +1 -1
  188. data/spec/unit/provider/ohai_spec.rb +4 -4
  189. data/spec/unit/provider/package/apt_spec.rb +0 -1
  190. data/spec/unit/provider/package/ips_spec.rb +0 -1
  191. data/spec/unit/provider/package/rubygems_spec.rb +0 -18
  192. data/spec/unit/provider/package/yum_spec.rb +79 -15
  193. data/spec/unit/provider/package_spec.rb +7 -5
  194. data/spec/unit/provider/registry_key_spec.rb +269 -0
  195. data/spec/unit/provider/remote_directory_spec.rb +24 -7
  196. data/spec/unit/provider/remote_file_spec.rb +36 -0
  197. data/spec/unit/provider/route_spec.rb +3 -6
  198. data/spec/unit/provider/ruby_block_spec.rb +8 -0
  199. data/spec/unit/provider/service/arch_service_spec.rb +4 -4
  200. data/spec/unit/provider/service/debian_service_spec.rb +1 -1
  201. data/spec/unit/provider/service/freebsd_service_spec.rb +4 -4
  202. data/spec/unit/provider/service/init_service_spec.rb +26 -3
  203. data/spec/unit/provider/service/insserv_service_spec.rb +1 -1
  204. data/spec/unit/provider/service/invokercd_service_spec.rb +3 -3
  205. data/spec/unit/provider/service/redhat_spec.rb +1 -1
  206. data/spec/unit/provider/service/simple_service_spec.rb +3 -3
  207. data/spec/unit/provider/service/upstart_service_spec.rb +7 -7
  208. data/spec/unit/provider/service_spec.rb +2 -2
  209. data/spec/unit/provider/subversion_spec.rb +1 -1
  210. data/spec/unit/provider/template_spec.rb +35 -11
  211. data/spec/unit/provider/user/dscl_spec.rb +57 -31
  212. data/spec/unit/provider/user_spec.rb +7 -16
  213. data/spec/unit/provider_spec.rb +4 -3
  214. data/spec/unit/recipe_spec.rb +10 -8
  215. data/spec/unit/registry_helper_spec.rb +376 -0
  216. data/spec/unit/resource/log_spec.rb +9 -0
  217. data/spec/unit/resource/registry_key_spec.rb +171 -0
  218. data/spec/unit/resource/remote_file_spec.rb +21 -23
  219. data/spec/unit/resource/ruby_block_spec.rb +7 -3
  220. data/spec/unit/resource/service_spec.rb +11 -0
  221. data/spec/unit/resource_spec.rb +27 -4
  222. data/spec/unit/rest/auth_credentials_spec.rb +2 -14
  223. data/spec/unit/rest_spec.rb +122 -187
  224. data/spec/unit/run_context/cookbook_compiler_spec.rb +181 -0
  225. data/spec/unit/run_context_spec.rb +18 -4
  226. data/spec/unit/run_list_spec.rb +0 -209
  227. data/spec/unit/run_lock_spec.rb +37 -0
  228. data/spec/unit/runner_spec.rb +101 -2
  229. data/spec/unit/scan_access_control_spec.rb +4 -4
  230. data/spec/unit/{shef → shell}/model_wrapper_spec.rb +5 -5
  231. data/spec/unit/{shef/shef_ext_spec.rb → shell/shell_ext_spec.rb} +21 -21
  232. data/spec/unit/{shef/shef_session_spec.rb → shell/shell_session_spec.rb} +12 -12
  233. data/spec/unit/shell_out_spec.rb +18 -0
  234. data/spec/unit/{shef_spec.rb → shell_spec.rb} +20 -20
  235. data/spec/unit/user_spec.rb +255 -0
  236. metadata +162 -157
  237. data/README.rdoc +0 -177
  238. data/spec/unit/certificate_spec.rb +0 -76
  239. data/spec/unit/checksum_cache_spec.rb +0 -209
  240. data/spec/unit/checksum_spec.rb +0 -94
  241. data/spec/unit/couchdb_spec.rb +0 -274
  242. data/spec/unit/index_queue_spec.rb +0 -391
  243. data/spec/unit/json_compat_spect.rb +0 -53
  244. data/spec/unit/mixin/language_spec.rb +0 -305
  245. data/spec/unit/openid_registration_spec.rb +0 -153
  246. data/spec/unit/solr_query/query_transform_spec.rb +0 -454
  247. data/spec/unit/solr_query/solr_http_request_spec.rb +0 -244
  248. data/spec/unit/solr_query_spec.rb +0 -203
  249. data/spec/unit/webui_user_spec.rb +0 -238
@@ -19,6 +19,29 @@
19
19
  require 'spec_helper'
20
20
  require 'chef/mixin/deprecation'
21
21
 
22
+ describe Chef::Mixin do
23
+ describe "deprecating constants (Class/Module)" do
24
+ before do
25
+ Chef::Mixin.deprecate_constant(:DeprecatedClass, Chef::Node, "This is a test deprecation")
26
+ @log_io = StringIO.new
27
+ Chef::Log.init(@log_io)
28
+ end
29
+
30
+ it "has a list of deprecated constants" do
31
+ Chef::Mixin.deprecated_constants.should have_key(:DeprecatedClass)
32
+ end
33
+
34
+ it "returns the replacement when accessing the deprecated constant" do
35
+ Chef::Mixin::DeprecatedClass.should == Chef::Node
36
+ end
37
+
38
+ it "warns when accessing the deprecated constant" do
39
+ Chef::Mixin::DeprecatedClass
40
+ @log_io.string.should include("This is a test deprecation")
41
+ end
42
+ end
43
+ end
44
+
22
45
  describe Chef::Mixin::Deprecation::DeprecatedInstanceVariable do
23
46
  before do
24
47
  Chef::Log.logger = Logger.new(StringIO.new)
@@ -27,13 +27,18 @@ describe Chef::Mixin::EnforceOwnershipAndPermissions do
27
27
  @node.name "make_believe"
28
28
  @events = Chef::EventDispatch::Dispatcher.new
29
29
  @run_context = Chef::RunContext.new(@node, {}, @events)
30
- @resource = Chef::Resource::File.new("#{Dir.mktmpdir}/madeup.txt")
30
+ @tmpdir = Dir.mktmpdir
31
+ @resource = Chef::Resource::File.new("#{@tmpdir}/madeup.txt")
31
32
  FileUtils.touch @resource.path
32
33
  @resource.owner "adam"
33
34
  @provider = Chef::Provider::File.new(@resource, @run_context)
34
35
  @provider.current_resource = @resource
35
36
  end
36
37
 
38
+ after(:each) do
39
+ FileUtils.rm_rf(@tmpdir)
40
+ end
41
+
37
42
  it "should call set_all on the file access control object" do
38
43
  Chef::FileAccessControl.any_instance.should_receive(:set_all)
39
44
  @provider.enforce_ownership_and_permissions
@@ -330,10 +330,12 @@ describe Chef::Mixin::ParamsValidate do
330
330
 
331
331
  it "asserts that a value returns false from a predicate method" do
332
332
  lambda do
333
- @vo.validate({:not_blank => "should pass"}, {:not_blank => {:cannot_be => :blank}})
333
+ @vo.validate({:not_blank => "should pass"},
334
+ {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}})
334
335
  end.should_not raise_error
335
336
  lambda do
336
- @vo.validate({:not_blank => ""}, {:not_blank => {:cannot_be => :blank}})
337
+ @vo.validate({:not_blank => ""},
338
+ {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}})
337
339
  end.should raise_error(Chef::Exceptions::ValidationFailed)
338
340
  end
339
341
 
@@ -112,9 +112,11 @@ describe Chef::Mixin::Securable do
112
112
  @original_config = Chef::Config.hash_dup
113
113
  load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "config.rb")
114
114
  load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "mixin", "securable.rb")
115
- @securable = Object.new
116
- @securable.send(:extend, Chef::Mixin::Securable)
117
- @securable.send(:extend, Chef::Mixin::ParamsValidate)
115
+ SECURABLE_CLASS = Class.new do
116
+ include Chef::Mixin::Securable
117
+ include Chef::Mixin::ParamsValidate
118
+ end
119
+ @securable = SECURABLE_CLASS.new
118
120
  end
119
121
  end
120
122
 
@@ -44,6 +44,125 @@ describe Chef::Mixin::Template, "render_template" do
44
44
  end
45
45
  end
46
46
 
47
+ describe "with a template resource" do
48
+ before :each do
49
+ @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
50
+ Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
51
+
52
+ @node = Chef::Node.new
53
+ cl = Chef::CookbookLoader.new(@cookbook_repo)
54
+ cl.load_cookbooks
55
+ @cookbook_collection = Chef::CookbookCollection.new(cl)
56
+ @events = Chef::EventDispatch::Dispatcher.new
57
+ @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
58
+
59
+ @rendered_file_location = Dir.tmpdir + '/openldap_stuff.conf'
60
+
61
+ @resource = Chef::Resource::Template.new(@rendered_file_location)
62
+ @resource.cookbook_name = 'openldap'
63
+
64
+ @provider = Chef::Provider::Template.new(@resource, @run_context)
65
+ @current_resource = @resource.dup
66
+ @provider.current_resource = @current_resource
67
+ @access_controls = mock("access controls")
68
+ @provider.stub!(:access_controls).and_return(@access_controls)
69
+
70
+ @template_context = {}
71
+ @template_context[:node] = @node
72
+ @template_context[:template_finder] = Chef::Provider::TemplateFinder.new(@run_context, @resource.cookbook_name, @node)
73
+ end
74
+
75
+ it "should provide a render method" do
76
+ @provider.render_template("before {<%= render 'test.erb' %>} after", @template_context) do |tmp|
77
+ tmp.open.read.should == "before {We could be diving for pearls!\n} after"
78
+ end
79
+ end
80
+
81
+ it "should render local files" do
82
+ begin
83
+ tf = Tempfile.new("partial")
84
+ tf.puts "test"
85
+ tf.rewind
86
+
87
+ @provider.render_template("before {<%= render '#{tf.path}', :local => true %>} after", @template_context) do |tmp|
88
+ tmp.open.read.should == "before {test\n} after"
89
+ end
90
+ ensure
91
+ tf.close
92
+ end
93
+ end
94
+
95
+ it "should render partials from a different cookbook" do
96
+ @template_context[:template_finder] = Chef::Provider::TemplateFinder.new(@run_context, 'apache2', @node)
97
+
98
+ @provider.render_template("before {<%= render 'test.erb', :cookbook => 'openldap' %>} after", @template_context) do |tmp|
99
+ tmp.open.read.should == "before {We could be diving for pearls!\n} after"
100
+ end
101
+ end
102
+
103
+ it "should render using the source argument if provided" do
104
+ begin
105
+ tf = Tempfile.new("partial")
106
+ tf.puts "test"
107
+ tf.rewind
108
+
109
+ @provider.render_template("before {<%= render 'something', :local => true, :source => '#{tf.path}' %>} after", @template_context) do |tmp|
110
+ tmp.open.read.should == "before {test\n} after"
111
+ end
112
+ ensure
113
+ tf.close
114
+ end
115
+ end
116
+
117
+ it "should pass the node to partials" do
118
+ @node.normal[:slappiness] = "happiness"
119
+
120
+ @provider.render_template("before {<%= render 'openldap_stuff.conf.erb' %>} after", @template_context) do |tmp|
121
+ tmp.open.read.should == "before {slappiness is happiness} after"
122
+ end
123
+ end
124
+
125
+ it "should pass the original variables to partials" do
126
+ @template_context[:secret] = 'candy'
127
+
128
+ @provider.render_template("before {<%= render 'openldap_variable_stuff.conf.erb' %>} after", @template_context) do |tmp|
129
+ tmp.open.read.should == "before {super secret is candy} after"
130
+ end
131
+ end
132
+
133
+ it "should pass variables to partials" do
134
+ @provider.render_template("before {<%= render 'openldap_variable_stuff.conf.erb', :variables => {:secret => 'whatever' } %>} after", @template_context) do |tmp|
135
+ tmp.open.read.should == "before {super secret is whatever} after"
136
+ end
137
+ end
138
+
139
+ it "should pass variables to partials even if they are named the same" do
140
+ @template_context[:secret] = 'one'
141
+
142
+ @provider.render_template("before {<%= render 'openldap_variable_stuff.conf.erb', :variables => {:secret => 'two' } %>} after <%= @secret %>", @template_context) do |tmp|
143
+ tmp.open.read.should == "before {super secret is two} after one"
144
+ end
145
+ end
146
+
147
+ it "should pass nil for missing variables in partials" do
148
+ @provider.render_template("before {<%= render 'openldap_variable_stuff.conf.erb', :variables => {} %>} after", @template_context) do |tmp|
149
+ tmp.open.read.should == "before {super secret is } after"
150
+ end
151
+
152
+ @provider.render_template("before {<%= render 'openldap_variable_stuff.conf.erb' %>} after", @template_context) do |tmp|
153
+ tmp.open.read.should == "before {super secret is } after"
154
+ end
155
+ end
156
+
157
+ it "should render nested partials" do
158
+ path = File.expand_path(File.join(CHEF_SPEC_DATA, "partial_one.erb"))
159
+
160
+ @provider.render_template("before {<%= render '#{path}', :local => true %>} after", @template_context) do |tmp|
161
+ tmp.open.read.should == "before {partial one We could be diving for pearls!\n calling home\n} after"
162
+ end
163
+ end
164
+ end
165
+
47
166
  describe "when an exception is raised in the template" do
48
167
  def do_raise
49
168
  @context = {:chef => "cool"}
@@ -225,30 +225,171 @@ describe Chef::Node::Attribute do
225
225
  [ :normal, :default, :override, :automatic ].each do |accessor|
226
226
  it "should set #{accessor}" do
227
227
  na = Chef::Node::Attribute.new({ :normal => true }, { :default => true }, { :override => true }, { :automatic => true })
228
- na.send(accessor).should == { accessor => true }
228
+ na.send(accessor).should == { accessor.to_s => true }
229
229
  end
230
230
  end
231
231
 
232
- it "should allow you to set the initial state" do
233
- attrs = {"first" => {"second" => {"third" => {"jackpot" => "jackpot!"}}}}
234
- na = Chef::Node::Attribute.new(attrs, {}, {}, {}, [ "first", "second", "third" ])
235
- na.should have_key("jackpot")
236
- end
237
-
238
232
  it "should be enumerable" do
239
233
  @attributes.should be_is_a(Enumerable)
240
234
  end
241
235
  end
242
236
 
243
- describe "hash_and_not_cna" do
244
- it "should return false if we pass it a Chef::Node::Attribute" do
245
- @attributes.hash_and_not_cna?(@attributes).should == false
237
+ describe "when printing attribute components" do
238
+
239
+ it "does not cause a type error" do
240
+ # See CHEF-3799; IO#puts implicitly calls #to_ary on its argument. This
241
+ # is expected to raise a NoMethodError or return an Array. `to_ary` is
242
+ # the "strict" conversion method that should only be implemented by
243
+ # things that are truly Array-like, so NoMethodError is the right choice.
244
+ # (cf. there is no Hash#to_ary).
245
+ lambda { @attributes.default.to_ary }.should raise_error(NoMethodError)
246
+ end
247
+
248
+ end
249
+
250
+ describe "when debugging attributes" do
251
+ before do
252
+ @attributes.default[:foo][:bar] = "default"
253
+ @attributes.env_default[:foo][:bar] = "env_default"
254
+ @attributes.role_default[:foo][:bar] = "role_default"
255
+ @attributes.force_default[:foo][:bar] = "force_default"
256
+ @attributes.normal[:foo][:bar] = "normal"
257
+ @attributes.override[:foo][:bar] = "override"
258
+ @attributes.role_override[:foo][:bar] = "role_override"
259
+ @attributes.env_override[:foo][:bar] = "env_override"
260
+ @attributes.force_override[:foo][:bar] = "force_override"
261
+ @attributes.automatic[:foo][:bar] = "automatic"
262
+ end
263
+
264
+ it "gives the value at each level of precedence for a path spec" do
265
+ expected = [["set_unless_enabled?", false],
266
+ ["default", "default"],
267
+ ["env_default", "env_default"],
268
+ ["role_default", "role_default"],
269
+ ["force_default", "force_default"],
270
+ ["normal", "normal"],
271
+ ["override", "override"],
272
+ ["role_override", "role_override"],
273
+ ["env_override", "env_override"],
274
+ ["force_override", "force_override"],
275
+ ["automatic", "automatic"]
276
+ ]
277
+ @attributes.debug_value(:foo, :bar).should == expected
278
+ end
279
+ end
280
+
281
+ describe "when fetching values based on precedence" do
282
+ before do
283
+ @attributes.default["default"] = "cookbook default"
284
+ @attributes.override["override"] = "cookbook override"
285
+ end
286
+
287
+ it "prefers 'forced default' over any other default" do
288
+ @attributes.default!["default"] = "force default"
289
+ @attributes.role_default["default"] = "role default"
290
+ @attributes.env_default["default"] = "environment default"
291
+ @attributes["default"].should == "force default"
292
+ end
293
+
294
+ it "prefers role_default over environment or cookbook default" do
295
+ @attributes.role_default["default"] = "role default"
296
+ @attributes.env_default["default"] = "environment default"
297
+ @attributes["default"].should == "role default"
298
+ end
299
+
300
+ it "prefers environment default over cookbook default" do
301
+ @attributes.env_default["default"] = "environment default"
302
+ @attributes["default"].should == "environment default"
303
+ end
304
+
305
+ it "returns the cookbook default when no other default values are present" do
306
+ @attributes["default"].should == "cookbook default"
307
+ end
308
+
309
+ it "prefers 'forced overrides' over role or cookbook overrides" do
310
+ @attributes.override!["override"] = "force override"
311
+ @attributes.env_override["override"] = "environment override"
312
+ @attributes.role_override["override"] = "role override"
313
+ @attributes["override"].should == "force override"
314
+ end
315
+
316
+ it "prefers environment overrides over role or cookbook overrides" do
317
+ @attributes.env_override["override"] = "environment override"
318
+ @attributes.role_override["override"] = "role override"
319
+ @attributes["override"].should == "environment override"
320
+ end
321
+
322
+ it "prefers role overrides over cookbook overrides" do
323
+ @attributes.role_override["override"] = "role override"
324
+ @attributes["override"].should == "role override"
325
+ end
326
+
327
+ it "returns cookbook overrides when no other overrides are present" do
328
+ @attributes["override"].should == "cookbook override"
329
+ end
330
+
331
+ it "merges arrays within the default precedence" do
332
+ @attributes.role_default["array"] = %w{role}
333
+ @attributes.env_default["array"] = %w{env}
334
+ @attributes["array"].should == %w{env role}
335
+ end
336
+
337
+ it "merges arrays within the override precedence" do
338
+ @attributes.role_override["array"] = %w{role}
339
+ @attributes.env_override["array"] = %w{env}
340
+ @attributes["array"].should == %w{role env}
341
+ end
342
+
343
+ it "does not merge arrays between default and normal" do
344
+ @attributes.role_default["array"] = %w{role}
345
+ @attributes.normal["array"] = %w{normal}
346
+ @attributes["array"].should == %w{normal}
347
+ end
348
+
349
+ it "does not merge arrays between normal and override" do
350
+ @attributes.normal["array"] = %w{normal}
351
+ @attributes.role_override["array"] = %w{role}
352
+ @attributes["array"].should == %w{role}
353
+ end
354
+
355
+ it "merges nested hashes between precedence levels" do
356
+ @attributes = Chef::Node::Attribute.new({}, {}, {}, {})
357
+ @attributes.env_default = {"a" => {"b" => {"default" => "default"}}}
358
+ @attributes.normal = {"a" => {"b" => {"normal" => "normal"}}}
359
+ @attributes.override = {"a" => {"override" => "role"}}
360
+ @attributes.automatic = {"a" => {"automatic" => "auto"}}
361
+ @attributes["a"].should == {"b"=>{"default"=>"default", "normal"=>"normal"},
362
+ "override"=>"role",
363
+ "automatic"=>"auto"}
364
+ end
365
+ end
366
+
367
+ describe "when reading combined default or override values" do
368
+ before do
369
+ @attributes.default["cd"] = "cookbook default"
370
+ @attributes.role_default["rd"] = "role default"
371
+ @attributes.env_default["ed"] = "env default"
372
+ @attributes.default!["fd"] = "force default"
373
+ @attributes.override["co"] = "cookbook override"
374
+ @attributes.role_override["ro"] = "role override"
375
+ @attributes.env_override["eo"] = "env override"
376
+ @attributes.override!["fo"] = "force override"
377
+ end
378
+
379
+ it "merges all types of overrides into a combined override" do
380
+ @attributes.combined_override["co"].should == "cookbook override"
381
+ @attributes.combined_override["ro"].should == "role override"
382
+ @attributes.combined_override["eo"].should == "env override"
383
+ @attributes.combined_override["fo"].should == "force override"
246
384
  end
247
385
 
248
- it "should return true if we pass it something that responds to has_key?" do
249
- hashy = mock("Hashlike", :has_key? => true)
250
- @attributes.hash_and_not_cna?(hashy).should == true
386
+ it "merges all types of defaults into a combined default" do
387
+ @attributes.combined_default["cd"].should == "cookbook default"
388
+ @attributes.combined_default["rd"].should == "role default"
389
+ @attributes.combined_default["ed"].should == "env default"
390
+ @attributes.combined_default["fd"].should == "force default"
251
391
  end
392
+
252
393
  end
253
394
 
254
395
  describe "[]" do
@@ -282,67 +423,31 @@ describe Chef::Node::Attribute do
282
423
 
283
424
  it "should return the merged hash if all three have values" do
284
425
  result = @attributes["music"]
285
- result["mars_volta"] = "cicatriz"
286
- result["jimmy_eat_world"] = "nice"
287
- result["mastodon"] = "rocks"
288
- end
289
- end
290
-
291
- describe "auto_vivifiy" do
292
- it "should set the hash key to a mash if it does not exist" do
293
- @attributes.auto_vivifiy({}, "one")["one"].should be_a_kind_of(Mash)
294
- end
295
-
296
- it "should raise an exception if the key does exist and does not respond to has_key?" do
297
- lambda { @attributes.auto_vivifiy({ "one" => "value" }) }.should raise_error(ArgumentError)
298
- end
299
-
300
- it "should not alter the value if the key exists and responds to has_key?" do
301
- @attributes.auto_vivifiy({ "one" => { "will" => true } }, "one")["one"].should have_key("will")
426
+ result["mars_volta"].should == "cicatriz"
427
+ result["jimmy_eat_world"].should == "nice"
428
+ result["mastodon"].should == "rocks"
302
429
  end
303
430
  end
304
431
 
305
- describe "set_value" do
306
- it "should set the value for a top level key" do
307
- to_check = {}
308
- @attributes.set_value(to_check, "one", "some value")
309
- to_check["one"].should == "some value"
310
- end
311
-
312
- it "should set the value for a second level key" do
313
- to_check = {}
314
- @attributes[ "one" ]
315
- @attributes.set_value(to_check, "two", "some value")
316
- to_check["one"]["two"].should == "some value"
432
+ describe "[]=" do
433
+ it "should error out when the type of attribute to set has not been specified" do
434
+ @attributes.normal["the_ghost"] = { }
435
+ lambda { @attributes["the_ghost"]["exterminate"] = false }.should raise_error(Chef::Exceptions::ImmutableAttributeModification)
317
436
  end
318
437
 
319
- it "should set the value for a very deep key" do
320
- to_check = {}
321
- attributes = Chef::Node::Attribute.new({}, {}, {}, {}, %w{one two three four five})
322
- attributes.set_value(to_check, "six", "some value")
323
- to_check["one"]["two"]["three"]["four"]["five"]["six"].should == "some value"
324
- end
325
- end
326
-
327
- describe "[]=" do
328
438
  it "should let you set an attribute value when another hash has an intermediate value" do
329
439
  @attributes.normal["the_ghost"] = { "exterminate" => "the future" }
330
- @attributes.set_type = :default
331
- @attributes.auto_vivifiy_on_read = true
332
- lambda { @attributes["the_ghost"]["exterminate"]["tomorrow"] = false }.should_not raise_error(NoMethodError)
440
+ lambda { @attributes.normal["the_ghost"]["exterminate"]["tomorrow"] = false }.should_not raise_error(NoMethodError)
333
441
  end
334
442
 
335
443
  it "should set the attribute value" do
336
- @attributes["longboard"] = "surfing"
337
- @attributes["longboard"].should == "surfing"
338
- @attributes.attribute["longboard"].should == "surfing"
444
+ @attributes.normal["longboard"] = "surfing"
445
+ @attributes.normal["longboard"].should == "surfing"
446
+ @attributes.normal["longboard"].should == "surfing"
339
447
  end
340
448
 
341
- it "should set deeply nested attribute value when auto_vivifiy_on_read is true" do
342
- @attributes.set_type = :normal
343
- @attributes.auto_vivifiy_on_read = true
344
- @attributes["deftones"]["hunters"]["nap"] = "surfing"
345
- @attributes.reset
449
+ it "should set deeply nested attribute values when a precedence level is specified" do
450
+ @attributes.normal["deftones"]["hunters"]["nap"] = "surfing"
346
451
  @attributes.normal["deftones"]["hunters"]["nap"].should == "surfing"
347
452
  end
348
453
 
@@ -351,45 +456,23 @@ describe Chef::Node::Attribute do
351
456
  end
352
457
 
353
458
  it "should let you set attributes manually without vivification" do
354
- @attributes["foo"] = Mash.new
355
- @attributes["foo"]["bar"] = :baz
356
- @attributes["foo"]["bar"].should == :baz
459
+ @attributes.normal["foo"] = Mash.new
460
+ @attributes.normal["foo"]["bar"] = :baz
461
+ @attributes.normal["foo"]["bar"].should == :baz
357
462
  end
358
463
 
359
464
  it "should optionally skip setting the value if one already exists" do
360
465
  @attributes.set_unless_value_present = true
361
- @attributes["hostname"] = "bar"
466
+ @attributes.normal["hostname"] = "bar"
362
467
  @attributes["hostname"].should == "latte"
363
468
  end
364
469
 
365
- it "should write to an attribute that has been read before properly" do
366
- @attributes["foo"] = Mash.new
367
- @attributes["foo"]["bar"] ||= "stop the world"
368
- @attributes["foo"]["bar"].should == "stop the world"
369
- end
370
- end
371
-
372
- describe "get_value" do
373
- it "should get a value from a top level key" do
374
- @attributes.get_value(@default_hash, "domain").should == "opscode.com"
375
- end
376
-
377
- it "should return nil for a top level key that does not exist" do
378
- @attributes.get_value(@default_hash, "domainz").should == nil
379
- end
380
-
381
- it "should get a value based on the state of the object" do
382
- @attributes.auto_vivifiy_on_read = true
383
- @attributes.set_type = :normal
384
- @attributes[:foo][:bar][:baz] = "snack"
385
- @attributes.get_value(@attribute_hash, :baz).should == "snack"
386
- end
387
-
388
- it "should return nil based on the state of the object if the key does not exist" do
389
- @attributes.auto_vivifiy_on_read = true
390
- @attributes.set_type = :normal
391
- @attributes[:foo][:bar][:baz] = "snack"
392
- @attributes.get_value(@attribute_hash, :baznatch).should == nil
470
+ it "does not support ||= when setting" do
471
+ # This is a limitation of auto-vivification.
472
+ # Users who need this behavior can use set_unless and friends
473
+ @attributes.normal["foo"] = Mash.new
474
+ @attributes.normal["foo"]["bar"] ||= "stop the world"
475
+ @attributes.normal["foo"]["bar"].should == {}
393
476
  end
394
477
  end
395
478
 
@@ -423,14 +506,8 @@ describe Chef::Node::Attribute do
423
506
  end
424
507
 
425
508
  it "should return true if an attribute exists but is set to false" do
426
- @attributes["music"]
427
- @attributes.has_key?("apophis").should == true
428
- end
429
-
430
- it "should find keys at the current nesting level" do
431
- @attributes["music"]
432
- @attributes.has_key?("mastodon").should == true
433
- @attributes.has_key?("whitesnake").should == false
509
+ @attributes.has_key?("music")
510
+ @attributes["music"].has_key?("apophis").should == true
434
511
  end
435
512
 
436
513
  it "does not find keys above the current nesting level" do
@@ -461,11 +538,6 @@ describe Chef::Node::Attribute do
461
538
  @attributes.attribute?("ninja").should == false
462
539
  end
463
540
 
464
- it "should be looking at the current position of the object" do
465
- @attributes["music"]
466
- @attributes.attribute?("mastodon").should == true
467
- @attributes.attribute?("whitesnake").should == false
468
- end
469
541
  end
470
542
 
471
543
  describe "method_missing" do
@@ -473,16 +545,10 @@ describe Chef::Node::Attribute do
473
545
  @attributes.music.mastodon.should == "rocks"
474
546
  end
475
547
 
476
- it "should behave like a []= lookup if the last method has an argument" do
477
- @attributes.music.mastodon(["dream", "still", "shining"])
478
- @attributes.reset
479
- @attributes.music.mastodon.should == ["dream", "still", "shining"]
480
- end
481
-
482
548
  it "should allow the last method to set a value if it has an = sign on the end" do
483
- @attributes.music.mastodon = [ "dream", "still", "shining" ]
549
+ @attributes.normal.music.mastodon = [ "dream", "still", "shining" ]
484
550
  @attributes.reset
485
- @attributes.music.mastodon.should == [ "dream", "still", "shining" ]
551
+ @attributes.normal.music.mastodon.should == [ "dream", "still", "shining" ]
486
552
  end
487
553
  end
488
554
 
@@ -923,8 +989,8 @@ describe Chef::Node::Attribute do
923
989
  end
924
990
  end
925
991
 
926
- it "should return an empty array for a block containing nil" do
927
- @attributes.select { nil }.should == []
992
+ it "should return an empty hash/array (ruby-version-dependent) for a block containing nil" do
993
+ @attributes.select { nil }.should == {}.select { nil }
928
994
  end
929
995
 
930
996
  # sorted for spec clarity
@@ -998,36 +1064,105 @@ describe Chef::Node::Attribute do
998
1064
 
999
1065
  describe "inspect" do
1000
1066
  it "should be readable" do
1001
- @attributes.inspect.should =~ /@automatic=\{\.\.\.\}/
1002
- @attributes.inspect.should =~ /@normal=\{\.\.\.\}/
1067
+ # NOTE: previous implementation hid the values, showing @automatic={...}
1068
+ # That is nice and compact, but hides a lot of info, which seems counter
1069
+ # to the point of calling #inspect...
1070
+ @attributes.inspect.should =~ /@automatic=\{.*\}/
1071
+ @attributes.inspect.should =~ /@normal=\{.*\}/
1003
1072
  end
1004
1073
  end
1005
1074
 
1006
- describe "when a value has been set at all four precedence levels" do
1007
- before do
1008
- @default_attrs = {"foo" => {"bar" => "default_value"}}
1009
- @normal_attrs = {"foo" => {"bar" => "normal_value"}}
1010
- @override_attrs = {"foo" => {"bar" => "override_value"}}
1011
- @automatic_attrs = {"foo" => {"bar" => "automatic_value"}}
1075
+ # For expedience, this test is implementation-heavy.
1076
+ describe "when a component attribute is mutated" do
1077
+ [
1078
+ :clear,
1079
+ :shift
1080
+ ].each do |mutator|
1081
+ it "resets the cache when the mutator #{mutator} is called" do
1082
+ @attributes.should_receive(:reset_cache)
1083
+ @attributes.default.send(mutator)
1084
+ end
1085
+ end
1012
1086
 
1013
- #(normal, default, override, automatic, state=[])
1014
- @attributes = Chef::Node::Attribute.new(@normal_attrs, @default_attrs, @override_attrs, @automatic_attrs)
1087
+ it "resets the cache when the mutator delete is called" do
1088
+ @attributes.should_receive(:reset_cache)
1089
+ @attributes.default.delete(:music)
1015
1090
  end
1016
1091
 
1017
- it "deletes a key from all precedence levels" do
1018
- @attributes["foo"].delete("bar")
1019
- @attributes.reset
1020
- @attributes["foo"].should_not have_key("bar")
1021
- @default_attrs["foo"].should_not have_key("bar")
1022
- @normal_attrs["foo"].should_not have_key("bar")
1023
- @override_attrs["foo"].should_not have_key("bar")
1024
- @automatic_attrs["foo"].should_not have_key("bar")
1092
+ [
1093
+ :merge!,
1094
+ :update,
1095
+ :replace
1096
+ ].each do |mutator|
1097
+ it "resets the cache when the mutator #{mutator} is called" do
1098
+ # Implementation of Mash means that this could get called many times. That's okay.
1099
+ @attributes.should_receive(:reset_cache).at_least(1).times
1100
+ @attributes.default.send(mutator, {:foo => :bar})
1101
+ end
1025
1102
  end
1026
1103
 
1027
- it "returns the automatic (highest precedence) value when deleting a key" do
1028
- @attributes["foo"].delete("bar").should == "automatic_value"
1104
+ [
1105
+ :delete_if,
1106
+ :keep_if,
1107
+ :reject!,
1108
+ :select!,
1109
+ ].each do |mutator|
1110
+ it "resets the cache when the mutator #{mutator} is called" do
1111
+ # Implementation of Mash means that this could get called many times. That's okay.
1112
+ @attributes.should_receive(:reset_cache).at_least(1).times
1113
+ block = lambda {|k,v| true }
1114
+ @attributes.default.send(mutator, &block)
1115
+ end
1116
+ end
1117
+ end
1118
+
1119
+ describe "when not mutated" do
1120
+
1121
+ it "does not reset the cache when dup'd [CHEF-3680]" do
1122
+ @attributes.default[:foo][:bar] = "set on original"
1123
+ subtree = @attributes[:foo]
1124
+ @attributes.default[:foo].dup[:bar] = "set on dup"
1125
+ subtree[:bar].should == "set on original"
1126
+ end
1127
+
1128
+ end
1129
+
1130
+ describe "when setting a component attribute to a new value" do
1131
+ it "converts the input in to a VividMash tree (default)" do
1132
+ @attributes.default = {}
1133
+ @attributes.default.foo = "bar"
1134
+ @attributes.merged_attributes[:foo].should == "bar"
1135
+ end
1136
+
1137
+ it "converts the input in to a VividMash tree (normal)" do
1138
+ @attributes.normal = {}
1139
+ @attributes.normal.foo = "bar"
1140
+ @attributes.merged_attributes[:foo].should == "bar"
1141
+ end
1142
+
1143
+ it "converts the input in to a VividMash tree (override)" do
1144
+ @attributes.override = {}
1145
+ @attributes.override.foo = "bar"
1146
+ @attributes.merged_attributes[:foo].should == "bar"
1147
+ end
1148
+
1149
+ it "converts the input in to a VividMash tree (automatic)" do
1150
+ @attributes.automatic = {}
1151
+ @attributes.automatic.foo = "bar"
1152
+ @attributes.merged_attributes[:foo].should == "bar"
1153
+ end
1154
+ end
1155
+
1156
+ describe "when attemping to write without specifying precedence" do
1157
+ it "raises an error when using []=" do
1158
+ lambda { @attributes[:new_key] = "new value" }.should raise_error(Chef::Exceptions::ImmutableAttributeModification)
1159
+ end
1160
+
1161
+ it "raises an error when using `attr=value`" do
1162
+ lambda { @attributes.new_key = "new value" }.should raise_error(Chef::Exceptions::ImmutableAttributeModification)
1029
1163
  end
1030
1164
 
1031
1165
  end
1032
1166
 
1033
1167
  end
1168
+