microwave 1.0.4 → 11.400.2

Sign up to get free protection for your applications and to get access to all the features.
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
+