diff options
39 files changed, 153 insertions, 73 deletions
diff --git a/chef.gemspec b/chef.gemspec index 481b120fe6..9049e1a874 100644 --- a/chef.gemspec +++ b/chef.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |s| s.add_dependency "mixlib-shellout", ">= 2.0.0.rc.0", "< 3.0" s.add_dependency "ohai", ">= 7.6.0.rc.0" - s.add_dependency "ffi-yajl", "~> 1.0", ">= 1.0.2" + s.add_dependency "ffi-yajl", "~> 1.1" s.add_dependency "net-ssh", "~> 2.6" s.add_dependency "net-ssh-multi", "~> 1.1" # CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not. diff --git a/kitchen-tests/.kitchen.yml b/kitchen-tests/.kitchen.yml index 651a606502..d13a558c97 100644 --- a/kitchen-tests/.kitchen.yml +++ b/kitchen-tests/.kitchen.yml @@ -2,7 +2,7 @@ provisioner: name: chef_solo github: "opscode/chef" - branch: <%= %x(git rev-parse HEAD) %> + branch: "tball/yajl-replace-json" # TODO replace this when going to master require_chef_omnibus: true data_path: test/fixtures diff --git a/kitchen-tests/test/fixtures/serverspec_helper.rb b/kitchen-tests/test/fixtures/serverspec_helper.rb index 6e6d71e79b..04e99156d6 100644 --- a/kitchen-tests/test/fixtures/serverspec_helper.rb +++ b/kitchen-tests/test/fixtures/serverspec_helper.rb @@ -4,6 +4,7 @@ require 'serverspec' require 'json' +require 'ffi_yajl' set :backend, :exec @@ -21,7 +22,7 @@ def load_nodestub platform = 'centos' platform_version = os[:release].to_i end - JSON.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{platform}/#{platform_version}.json"), :symbolize_names => true) + FFI_Yajl::Encoder.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{platform}/#{platform_version}.json"), :symbolize_names => true) end # centos-59 doesn't have /sbin in the default path, diff --git a/lib/chef/chef_fs/file_system/organization_invites_entry.rb b/lib/chef/chef_fs/file_system/organization_invites_entry.rb index cb26326050..5df37085cb 100644 --- a/lib/chef/chef_fs/file_system/organization_invites_entry.rb +++ b/lib/chef/chef_fs/file_system/organization_invites_entry.rb @@ -1,5 +1,6 @@ require 'chef/chef_fs/file_system/rest_list_entry' require 'chef/chef_fs/data_handler/organization_invites_data_handler' +require 'chef/json_compat' class Chef module ChefFS @@ -34,7 +35,7 @@ class Chef end def write(contents) - desired_invites = minimize_value(JSON.parse(contents, :create_additions => false)) + desired_invites = minimize_value(Chef::JSONCompat.parse(contents, :create_additions => false)) actual_invites = _read_json.inject({}) { |h,val| h[val['username']] = val['id']; h } invites = actual_invites.keys (desired_invites - invites).each do |invite| diff --git a/lib/chef/chef_fs/file_system/organization_members_entry.rb b/lib/chef/chef_fs/file_system/organization_members_entry.rb index eb524d5ea2..94393b341f 100644 --- a/lib/chef/chef_fs/file_system/organization_members_entry.rb +++ b/lib/chef/chef_fs/file_system/organization_members_entry.rb @@ -1,5 +1,6 @@ require 'chef/chef_fs/file_system/rest_list_entry' require 'chef/chef_fs/data_handler/organization_members_data_handler' +require 'chef/json_compat' class Chef module ChefFS @@ -34,7 +35,7 @@ class Chef end def write(contents) - desired_members = minimize_value(JSON.parse(contents, :create_additions => false)) + desired_members = minimize_value(Chef::JSONCompat.parse(contents, :create_additions => false)) members = minimize_value(_read_json) (desired_members - members).each do |member| begin diff --git a/lib/chef/chef_fs/file_system/rest_list_entry.rb b/lib/chef/chef_fs/file_system/rest_list_entry.rb index ac47ff4f25..f68794cb0d 100644 --- a/lib/chef/chef_fs/file_system/rest_list_entry.rb +++ b/lib/chef/chef_fs/file_system/rest_list_entry.rb @@ -21,6 +21,7 @@ require 'chef/chef_fs/file_system/not_found_error' require 'chef/chef_fs/file_system/operation_failed_error' require 'chef/role' require 'chef/node' +require 'chef/json_compat' class Chef module ChefFS @@ -172,7 +173,7 @@ class Chef def api_error_text(response) begin - JSON.parse(response.body)['error'].join("\n") + Chef::JSONCompat.parse(response.body)['error'].join("\n") rescue response.body end diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 40aaaf1191..95af94bdf7 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -479,7 +479,7 @@ class Chef cookbook_version.manifest = o # We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>) - cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(cookbook_version.metadata.to_json) + cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(cookbook_version.metadata)) cookbook_version.freeze_version if o["frozen?"] cookbook_version diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb index e92d5c36ae..6f7ec4653e 100644 --- a/lib/chef/json_compat.rb +++ b/lib/chef/json_compat.rb @@ -18,7 +18,7 @@ # Wrapper class for interacting with JSON. require 'ffi_yajl' -require 'json' +#require 'json' require 'ffi_yajl/json_gem' # XXX: parts of chef require JSON gem's Hash#to_json monkeypatch require 'chef/exceptions' diff --git a/lib/chef/util/powershell/cmdlet_result.rb b/lib/chef/util/powershell/cmdlet_result.rb index af7b3607cd..246701a7bc 100644 --- a/lib/chef/util/powershell/cmdlet_result.rb +++ b/lib/chef/util/powershell/cmdlet_result.rb @@ -16,7 +16,7 @@ # limitations under the License. # -require 'json' +require 'chef/json_compat' class Chef::Util::Powershell class CmdletResult @@ -33,7 +33,7 @@ class Chef::Util::Powershell def return_value if output_format == :object - JSON.parse(@status.stdout) + Chef::JSONCompat.parse(@status.stdout) else @status.stdout end diff --git a/spec/functional/knife/cookbook_delete_spec.rb b/spec/functional/knife/cookbook_delete_spec.rb index ee620bf165..4773fd2185 100644 --- a/spec/functional/knife/cookbook_delete_spec.rb +++ b/spec/functional/knife/cookbook_delete_spec.rb @@ -47,7 +47,7 @@ describe Chef::Knife::CookbookDelete do Chef::Log.level = :debug @knife.name_args = %w{no-such-cookbook} - @api.get("/cookbooks/no-such-cookbook", 404, {'error'=>'dear Tim, no. -Sent from my iPad'}.to_json) + @api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({'error'=>'dear Tim, no. -Sent from my iPad'})) end it "logs an error and exits" do @@ -62,7 +62,7 @@ describe Chef::Knife::CookbookDelete do before do @knife.name_args = %w{obsolete-cookbook} @cookbook_list = {'obsolete-cookbook' => { 'versions' => ['version' => '1.0.0']} } - @api.get("/cookbooks/obsolete-cookbook", 200, @cookbook_list.to_json) + @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "asks for confirmation, then deletes the cookbook" do @@ -105,7 +105,7 @@ describe Chef::Knife::CookbookDelete do versions = ['1.0.0', '1.1.0', '1.2.0'] with_version = lambda { |version| { 'version' => version } } @cookbook_list = {'obsolete-cookbook' => { 'versions' => versions.map(&with_version) } } - @api.get("/cookbooks/obsolete-cookbook", 200, @cookbook_list.to_json) + @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "deletes all versions of a cookbook when given the '-a' flag" do diff --git a/spec/functional/knife/exec_spec.rb b/spec/functional/knife/exec_spec.rb index 455160fd5c..7eb52d01df 100644 --- a/spec/functional/knife/exec_spec.rb +++ b/spec/functional/knife/exec_spec.rb @@ -47,7 +47,7 @@ describe Chef::Knife::Exec do @node = Chef::Node.new @node.name("ohai-world") response = {"rows" => [@node],"start" => 0,"total" => 1} - @api.get(%r{^/search/node}, 200, response.to_json) + @api.get(%r{^/search/node}, 200, Chef::JSONCompat.to_json(response)) code = "$output.puts nodes.all" @knife.config[:exec] = code @knife.run diff --git a/spec/functional/util/powershell/cmdlet_spec.rb b/spec/functional/util/powershell/cmdlet_spec.rb index 63d1ac09b5..b240a5ec12 100644 --- a/spec/functional/util/powershell/cmdlet_spec.rb +++ b/spec/functional/util/powershell/cmdlet_spec.rb @@ -16,7 +16,7 @@ # limitations under the License. # -require 'json' +require 'chef/json_compat' require File.expand_path('../../../../spec_helper', __FILE__) describe Chef::Util::Powershell::Cmdlet, :windows_only do @@ -91,7 +91,7 @@ describe Chef::Util::Powershell::Cmdlet, :windows_only do it "returns json format data", :windows_powershell_dsc_only do result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls') expect(result.succeeded?).to eq(true) - expect(lambda{JSON.parse(result.return_value)}).not_to raise_error + expect(lambda{Chef::JSONCompat.parse(result.return_value)}).not_to raise_error end end diff --git a/spec/integration/knife/chef_repo_path_spec.rb b/spec/integration/knife/chef_repo_path_spec.rb index 90455ed374..9f6a27f006 100644 --- a/spec/integration/knife/chef_repo_path_spec.rb +++ b/spec/integration/knife/chef_repo_path_spec.rb @@ -291,7 +291,6 @@ EOM knife('show --local /clients/blah.json').should_succeed <<EOM /clients/blah.json: { - } EOM end @@ -391,7 +390,6 @@ EOM knife('show --local /environments/blah.json').should_succeed <<EOM /environments/blah.json: { - } EOM end @@ -406,7 +404,6 @@ EOM knife('show --local /nodes/blah.json').should_succeed <<EOM /nodes/blah.json: { - } EOM end @@ -421,7 +418,6 @@ EOM knife('show --local /roles/blah.json').should_succeed <<EOM /roles/blah.json: { - } EOM end @@ -436,7 +432,6 @@ EOM knife('show --local /users/blah.json').should_succeed <<EOM /users/blah.json: { - } EOM end diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb index 05d33d1a17..380711bf4f 100644 --- a/spec/integration/knife/upload_spec.rb +++ b/spec/integration/knife/upload_spec.rb @@ -19,6 +19,7 @@ require 'support/shared/integration/integration_helper' require 'chef/knife/upload' require 'chef/knife/diff' require 'chef/knife/raw' +require 'chef/json_compat' describe 'knife upload' do include IntegrationSupport @@ -261,7 +262,7 @@ Created /data_bags/x/y.json EOM knife('diff --name-status /data_bags').should_succeed <<EOM EOM - JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ] + Chef::JSONCompat.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ] end it 'knife upload /data_bags/x /data_bags/x/y.json uploads x once' do @@ -284,7 +285,7 @@ Created /data_bags/x Created /data_bags/x/y.json EOM knife('diff --name-status /data_bags').should_succeed '' - result = JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false) + result = Chef::JSONCompat.parse(knife('raw /data/x/y').stdout, :create_additions => false) result.keys.sort.should == [ 'chef_type', 'data_bag', 'id' ] result['chef_type'].should == 'aaa' result['data_bag'].should == 'bbb' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ed0a8f89f6..9d629da226 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -185,3 +185,13 @@ module WEBrick end end end + +# We are no longer using the 'json' gem - deny all access to it! +orig_require = Kernel.send(:instance_method, :require) +Kernel.send(:remove_method, :require) +Kernel.send(:define_method, :require) { |path| + raise LoadError, 'JSON gem is no longer allowed - use Chef::JSONCompat.to_json' if path == 'json' + orig_require.bind(Kernel).call(path) +} +# Enough stuff needs json serialization that I'm just adding it here for equality asserts +require 'chef/json_compat' diff --git a/spec/support/shared/shared_examples.rb b/spec/support/shared/shared_examples.rb new file mode 100644 index 0000000000..ccdd8cf316 --- /dev/null +++ b/spec/support/shared/shared_examples.rb @@ -0,0 +1,10 @@ +# For storing any examples shared between multiple tests + +# Any object which defines a .to_json should import this test +shared_examples "to_json equalivent to Chef::JSONCompat.to_json" do + + it "should allow consumers to call #to_json or Chef::JSONCompat.to_json" do + expect(subject.to_json).to eq(Chef::JSONCompat.to_json(subject)) + end + +end diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb index 7e6ef3a809..a2cfe168d5 100644 --- a/spec/tiny_server.rb +++ b/spec/tiny_server.rb @@ -22,7 +22,6 @@ require 'webrick/https' require 'rack' #require 'thin' require 'singleton' -require 'chef/json_compat' require 'open-uri' require 'chef/config' @@ -152,7 +151,7 @@ module TinyServer :available_routes => @routes, :request => env} # Uncomment me for glorious debugging # pp :not_found => debug_info - [404, {'Content-Type' => 'application/json'}, [ debug_info.to_json ]] + [404, {'Content-Type' => 'application/json'}, [ Chef::JSONCompat.to_json(debug_info) ]] end end diff --git a/spec/unit/api_client_spec.rb b/spec/unit/api_client_spec.rb index 76fc4afb5c..7fb2b310f9 100644 --- a/spec/unit/api_client_spec.rb +++ b/spec/unit/api_client_spec.rb @@ -123,6 +123,10 @@ describe Chef::ApiClient do it "does not include the private key if not present" do @json.should_not include("private_key") end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @client } + end end describe "when deserializing from JSON" do @@ -135,7 +139,7 @@ describe Chef::ApiClient do "validator" => true, "json_class" => "Chef::ApiClient" } - @client = Chef::JSONCompat.from_json(client.to_json) + @client = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(client)) end it "should deserialize to a Chef::ApiClient object" do diff --git a/spec/unit/config_fetcher_spec.rb b/spec/unit/config_fetcher_spec.rb index f6d5436a11..31787a0909 100644 --- a/spec/unit/config_fetcher_spec.rb +++ b/spec/unit/config_fetcher_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' require 'chef/config_fetcher' + describe Chef::ConfigFetcher do - let(:valid_json) { {:a=>"b"}.to_json } + let(:valid_json) { Chef::JSONCompat.to_json({:a=>"b"}) } let(:invalid_json) { %q[{"syntax-error": "missing quote}] } let(:http) { double("Chef::HTTP::Simple") } diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index e61c85b42b..86be0d2390 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -623,9 +623,13 @@ describe Chef::Cookbook::Metadata do metadata.version "1.2.3" end + it "should produce the same output from to_json and Chef::JSONCompat" do + expect(metadata.to_json).to eq(Chef::JSONCompat.to_json(metadata)) + end + describe "serialize" do - let(:deserialized_metadata) { Chef::JSONCompat.from_json(metadata.to_json) } + let(:deserialized_metadata) { Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(metadata)) } it "should serialize to a json hash" do deserialized_metadata.should be_a_kind_of(Hash) @@ -657,7 +661,7 @@ describe Chef::Cookbook::Metadata do describe "deserialize" do - let(:deserialized_metadata) { Chef::Cookbook::Metadata.from_json(metadata.to_json) } + let(:deserialized_metadata) { Chef::Cookbook::Metadata.from_json(Chef::JSONCompat.to_json(metadata)) } it "should deserialize to a Chef::Cookbook::Metadata object" do diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb index f40bbd5696..deaf393d7a 100644 --- a/spec/unit/cookbook_loader_spec.rb +++ b/spec/unit/cookbook_loader_spec.rb @@ -210,7 +210,7 @@ describe Chef::CookbookLoader do aa.to_hash["metadata"].recipes.keys.should include("openldap") expected_desc = "Main Open LDAP configuration" aa.to_hash["metadata"].recipes["openldap"].should == expected_desc - raw = aa.to_hash["metadata"].recipes.to_json + raw = Chef::JSONCompat.to_json(aa.to_hash["metadata"].recipes) search_str = "\"openldap\":\"" key_idx = raw.index(search_str) key_idx.should be > 0 diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb index f20bc3766a..18fb709e71 100644 --- a/spec/unit/cookbook_version_spec.rb +++ b/spec/unit/cookbook_version_spec.rb @@ -422,4 +422,8 @@ describe Chef::CookbookVersion do end + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { Chef::CookbookVersion.new("tatft", '/tmp/blah') } + end + end diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb index ead0dadfa2..f28450ef72 100644 --- a/spec/unit/data_bag_item_spec.rb +++ b/spec/unit/data_bag_item_spec.rb @@ -166,7 +166,7 @@ describe Chef::DataBagItem do before(:each) do @data_bag_item.data_bag('mars_volta') @data_bag_item.raw_data = { "id" => "octahedron", "snooze" => { "finally" => :world_will }} - @deserial = Chef::JSONCompat.from_json(@data_bag_item.to_json) + @deserial = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data_bag_item)) end it "should deserialize to a Chef::DataBagItem object" do @@ -184,6 +184,10 @@ describe Chef::DataBagItem do it "should have a matching 'snooze' key" do @deserial["snooze"].should == { "finally" => "world_will" } end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @data_bag_item } + end end describe "when converting to a string" do diff --git a/spec/unit/data_bag_spec.rb b/spec/unit/data_bag_spec.rb index c905277b7c..55d2a30324 100644 --- a/spec/unit/data_bag_spec.rb +++ b/spec/unit/data_bag_spec.rb @@ -59,7 +59,7 @@ describe Chef::DataBag do describe "deserialize" do before(:each) do @data_bag.name('mars_volta') - @deserial = Chef::JSONCompat.from_json(@data_bag.to_json) + @deserial = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data_bag)) end it "should deserialize to a Chef::DataBag object" do @@ -72,6 +72,10 @@ describe Chef::DataBag do it "should match '#{t}'" do @deserial.send(t.to_sym).should == @data_bag.send(t.to_sym) end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @data_bag } + end end end diff --git a/spec/unit/encrypted_data_bag_item_spec.rb b/spec/unit/encrypted_data_bag_item_spec.rb index 5ee245b9bc..9335889ef3 100644 --- a/spec/unit/encrypted_data_bag_item_spec.rb +++ b/spec/unit/encrypted_data_bag_item_spec.rb @@ -168,6 +168,17 @@ describe Chef::EncryptedDataBagItem::Decryptor do let(:plaintext_data) { {"foo" => "bar"} } let(:encryption_key) { "passwd" } let(:decryption_key) { encryption_key } + let(:json_wrapped_data) { Chef::JSONCompat.to_json({"json_wrapper" => plaintext_data}) } + + shared_examples "decryption examples" do + it "decrypts the encrypted value" do + decryptor.decrypted_data.should eq(json_wrapped_data) + end + + it "unwraps the encrypted data and returns it" do + decryptor.for_decrypted_item.should eq plaintext_data + end + end context "when decrypting a version 3 (JSON+aes-256-gcm+random iv+auth tag) encrypted value" do @@ -179,13 +190,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do let(:bogus_auth_tag) { "bogus_auth_tag" } - it "decrypts the encrypted value" do - decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json) - end - - it "unwraps the encrypted data and returns it" do - decryptor.for_decrypted_item.should eq plaintext_data - end + include_examples "decryption examples" it "rejects the data if the authentication tag is wrong" do encrypted_value["auth_tag"] = bogus_auth_tag @@ -240,13 +245,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do Base64.encode64(raw_hmac) end - it "decrypts the encrypted value" do - decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json) - end - - it "unwraps the encrypted data and returns it" do - decryptor.for_decrypted_item.should eq plaintext_data - end + include_examples "decryption examples" it "rejects the data if the hmac is wrong" do encrypted_value["hmac"] = bogus_hmac @@ -270,13 +269,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do decryptor.should be_a_instance_of Chef::EncryptedDataBagItem::Decryptor::Version1Decryptor end - it "decrypts the encrypted value" do - decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json) - end - - it "unwraps the encrypted data and returns it" do - decryptor.for_decrypted_item.should eq plaintext_data - end + include_examples "decryption examples" describe "and the decryption step returns invalid data" do it "raises a decryption failure error" do diff --git a/spec/unit/environment_spec.rb b/spec/unit/environment_spec.rb index 5a2c400d3c..bb4ece0a47 100644 --- a/spec/unit/environment_spec.rb +++ b/spec/unit/environment_spec.rb @@ -196,7 +196,7 @@ describe Chef::Environment do %w{name description cookbook_versions}.each do |t| it "should include '#{t}'" do - @json.should =~ /"#{t}":#{Regexp.escape(@environment.send(t.to_sym).to_json)}/ + @json.should =~ /"#{t}":#{Regexp.escape(Chef::JSONCompat.to_json(@environment.send(t.to_sym)))}/ end end @@ -207,6 +207,10 @@ describe Chef::Environment do it "should include 'chef_type'" do @json.should =~ /"chef_type":"environment"/ end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @environment } + end end describe "from_json" do @@ -222,7 +226,7 @@ describe Chef::Environment do "json_class" => "Chef::Environment", "chef_type" => "environment" } - @environment = Chef::JSONCompat.from_json(@data.to_json) + @environment = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data)) end it "should return a Chef::Environment" do diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb index 3e7b1ba93f..c7bfc63e6b 100644 --- a/spec/unit/exceptions_spec.rb +++ b/spec/unit/exceptions_spec.rb @@ -74,5 +74,11 @@ describe Chef::Exceptions do it "should have an exception class of #{exception} which inherits from #{expected_super_class}" do lambda{ raise exception }.should raise_error(expected_super_class) end + + if exception.methods.include?(:to_json) + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { exception } + end + end end end diff --git a/spec/unit/json_compat_spec.rb b/spec/unit/json_compat_spec.rb index e355a47faa..5951f0cc47 100644 --- a/spec/unit/json_compat_spec.rb +++ b/spec/unit/json_compat_spec.rb @@ -58,13 +58,17 @@ describe Chef::JSONCompat do describe "when pretty printing an object that defines #to_json" do class Foo def to_json(*a) - {'foo' => 1234}.to_json(*a) + Chef::JSONCompat.to_json({'foo' => 1234, 'bar' => {'baz' => 5678}}, *a) end end it "should work" do f = Foo.new - expect(Chef::JSONCompat.to_json_pretty(f)).to eql("{\n \"foo\": 1234\n}\n") + expect(Chef::JSONCompat.to_json_pretty(f)).to eql("{\n \"foo\": 1234,\n \"bar\": {\n \"baz\": 5678\n }\n}\n") + end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { Foo.new } end end @@ -97,4 +101,9 @@ describe Chef::JSONCompat do end end end + + it "should not allow the json gem to be required because of the spec_helper" do + # We want to prevent ourselves from writing code that requires 'json' + expect { require 'json' }.to raise_error(LoadError) + end end diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb index 902e5f6115..ad3f32fecc 100644 --- a/spec/unit/knife/cookbook_site_share_spec.rb +++ b/spec/unit/knife/cookbook_site_share_spec.rb @@ -109,7 +109,7 @@ describe Chef::Knife::CookbookSiteShare do end it 'should post the cookbook to "https://supermarket.getchef.com"' do - response_text = {:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'}.to_json + response_text = Chef::JSONCompat.to_json({:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'}) @upload_response.stub(:body).and_return(response_text) @upload_response.stub(:code).and_return(201) Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/supermarket\.getchef\.com/, anything(), anything(), anything()) @@ -117,7 +117,7 @@ describe Chef::Knife::CookbookSiteShare do end it 'should alert the user when a version already exists' do - response_text = {:error_messages => ['Version already exists']}.to_json + response_text = Chef::JSONCompat.to_json({:error_messages => ['Version already exists']}) @upload_response.stub(:body).and_return(response_text) @upload_response.stub(:code).and_return(409) lambda { @knife.run }.should raise_error(SystemExit) @@ -125,7 +125,7 @@ describe Chef::Knife::CookbookSiteShare do end it 'should pass any errors on to the user' do - response_text = {:error_messages => ["You're holding it wrong"]}.to_json + response_text = Chef::JSONCompat.to_json({:error_messages => ["You're holding it wrong"]}) @upload_response.stub(:body).and_return(response_text) @upload_response.stub(:code).and_return(403) lambda { @knife.run }.should raise_error(SystemExit) @@ -133,7 +133,7 @@ describe Chef::Knife::CookbookSiteShare do end it 'should print the body if no errors are exposed on failure' do - response_text = {:system_error => "Your call was dropped", :reason => "There's a map for that"}.to_json + response_text = Chef::JSONCompat.to_json({:system_error => "Your call was dropped", :reason => "There's a map for that"}) @upload_response.stub(:body).and_return(response_text) @upload_response.stub(:code).and_return(500) @knife.ui.should_receive(:error).with(/#{Regexp.escape(response_text)}/)#.ordered diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb index 266991a7dd..3d9bf69769 100644 --- a/spec/unit/knife/core/bootstrap_context_spec.rb +++ b/spec/unit/knife/core/bootstrap_context_spec.rb @@ -95,13 +95,13 @@ EXPECTED describe "when JSON attributes are given" do let(:config) { {:first_boot_attributes => {:baz => :quux}} } it "adds the attributes to first_boot" do - bootstrap_context.first_boot.to_json.should eq({:baz => :quux, :run_list => run_list}.to_json) + bootstrap_context.first_boot.to_json.should eq(Chef::JSONCompat.to_json({:baz => :quux, :run_list => run_list})) end end describe "when JSON attributes are NOT given" do it "sets first_boot equal to run_list" do - bootstrap_context.first_boot.to_json.should eq({:run_list => run_list}.to_json) + bootstrap_context.first_boot.to_json.should eq(Chef::JSONCompat.to_json({:run_list => run_list})) end end diff --git a/spec/unit/knife/data_bag_from_file_spec.rb b/spec/unit/knife/data_bag_from_file_spec.rb index dba5cc282b..8de046e7a4 100644 --- a/spec/unit/knife/data_bag_from_file_spec.rb +++ b/spec/unit/knife/data_bag_from_file_spec.rb @@ -29,7 +29,7 @@ describe Chef::Knife::DataBagFromFile do Chef::Platform.stub(:windows?) { false } Chef::Config[:node_name] = "webmonkey.example.com" FileUtils.mkdir_p([db_folder, db_folder2]) - db_file.write(plain_data.to_json) + db_file.write(Chef::JSONCompat.to_json(plain_data)) db_file.flush allow(knife).to receive(:config).and_return(config) allow(Chef::Knife::Core::ObjectLoader).to receive(:new).and_return(loader) diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 21a978a9c9..ccecfca2f0 100644 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -762,6 +762,10 @@ describe Chef::Node do end serialized_node.run_list.should == node.run_list end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { node.from_file(File.expand_path("nodes/test.example.com.rb", CHEF_SPEC_DATA)) } + end end describe "to_s" do diff --git a/spec/unit/provider/remote_file/cache_control_data_spec.rb b/spec/unit/provider/remote_file/cache_control_data_spec.rb index 8e396b1b40..8a849d9d7d 100644 --- a/spec/unit/provider/remote_file/cache_control_data_spec.rb +++ b/spec/unit/provider/remote_file/cache_control_data_spec.rb @@ -85,7 +85,7 @@ describe Chef::Provider::RemoteFile::CacheControlData do cache["etag"] = etag cache["mtime"] = mtime cache["checksum"] = last_fetched_checksum - cache.to_json + Chef::JSONCompat.to_json(cache) end before do diff --git a/spec/unit/resource_collection_spec.rb b/spec/unit/resource_collection_spec.rb index eddd92e098..30c7630ba1 100644 --- a/spec/unit/resource_collection_spec.rb +++ b/spec/unit/resource_collection_spec.rb @@ -278,12 +278,20 @@ describe Chef::ResourceCollection do json.should =~ /json_class/ json.should =~ /instance_vars/ end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @rc } + end end describe "self.from_json" do - it "should deserialize itself from json" do + it "should not respond to this method" do + expect(@rc.respond_to?(:from_json)).to eq(false) + end + + it "should convert from json using the CHEF::JSONCompat library" do @rc << @resource - json = @rc.to_json + json = Chef::JSONCompat.to_json(@rc) s_rc = Chef::JSONCompat.from_json(json) s_rc.should be_a_kind_of(Chef::ResourceCollection) s_rc[0].name.should eql(@resource.name) diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb index fe6a895b5a..1a89cbdce1 100644 --- a/spec/unit/resource_reporter_spec.rb +++ b/spec/unit/resource_reporter_spec.rb @@ -421,7 +421,7 @@ describe Chef::ResourceReporter do it "includes the run_list" do @report.should have_key("run_list") - @report["run_list"].should == @run_status.node.run_list.to_json + @report["run_list"].should == Chef::JSONCompat.to_json(@run_status.node.run_list) end it "includes the end_time" do @@ -484,7 +484,7 @@ describe Chef::ResourceReporter do it "includes the exception trace in the event data" do @report["data"]["exception"].should have_key("backtrace") - @report["data"]["exception"]["backtrace"].should == @backtrace.to_json + @report["data"]["exception"]["backtrace"].should == Chef::JSONCompat.to_json(@backtrace) end it "includes the error inspector output in the event data" do @@ -701,7 +701,7 @@ describe Chef::ResourceReporter do }) data_stream = Zlib::GzipReader.new(StringIO.new(data)) data = data_stream.read - data.should eq(@expected_data.to_json) + data.should eq(Chef::JSONCompat.to_json(@expected_data)) response end diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index e85633eaab..50136a673d 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -336,6 +336,10 @@ describe Chef::Resource do json.should =~ /json_class/ json.should =~ /instance_vars/ end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @resource } + end end describe "to_hash" do @@ -354,7 +358,7 @@ describe Chef::Resource do describe "self.json_create" do it "should deserialize itself from json" do - json = @resource.to_json + json = Chef::JSONCompat.to_json(@resource) serialized_node = Chef::JSONCompat.from_json(json) serialized_node.should be_a_kind_of(Chef::Resource) serialized_node.name.should eql(@resource.name) diff --git a/spec/unit/role_spec.rb b/spec/unit/role_spec.rb index f3fa7e1868..36f32eb87f 100644 --- a/spec/unit/role_spec.rb +++ b/spec/unit/role_spec.rb @@ -216,6 +216,10 @@ describe Chef::Role do end end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @role } + end end describe "when created from JSON", :json => true do diff --git a/spec/unit/run_list_spec.rb b/spec/unit/run_list_spec.rb index 220e4ea4a6..d2f0e01811 100644 --- a/spec/unit/run_list_spec.rb +++ b/spec/unit/run_list_spec.rb @@ -304,7 +304,11 @@ describe Chef::RunList do end it "converts to json by converting its array form" do - @run_list.to_json.should == ["recipe[nagios::client]", "role[production]", "recipe[apache2]"].to_json + Chef::JSONCompat.to_json(@run_list).should == Chef::JSONCompat.to_json(["recipe[nagios::client]", "role[production]", "recipe[apache2]"]) + end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @run_list } end end diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb index 08bde33d7b..055512444b 100644 --- a/spec/unit/user_spec.rb +++ b/spec/unit/user_spec.rb @@ -154,6 +154,10 @@ describe Chef::User do it "does not include the password if not present" do @json.should_not include("password") end + + include_examples "to_json equalivent to Chef::JSONCompat.to_json" do + let(:subject) { @user } + end end describe "when deserializing from JSON" do @@ -163,7 +167,7 @@ describe Chef::User do "private_key" => "pandas", "password" => "password", "admin" => true } - @user = Chef::User.from_json(user.to_json) + @user = Chef::User.from_json(Chef::JSONCompat.to_json(user)) end it "should deserialize to a Chef::User object" do |