| module ResolverSpecs |
| def self.included(base) |
| base.module_eval do |
| let(:resolver) { nil } |
| let(:result) { @result } |
| |
| before :each do |
| # See the comment in the first before :each block in safe_yaml_spec.rb. |
| require "safe_yaml" |
| end |
| |
| def parse(yaml) |
| tree = YAML.parse(yaml.unindent) |
| @result = resolver.resolve_node(tree) |
| end |
| |
| # Isn't this how I should've been doing it all along? |
| def parse_and_test(yaml) |
| safe_result = parse(yaml) |
| |
| exception_thrown = nil |
| |
| unsafe_result = begin |
| YAML.unsafe_load(yaml) |
| rescue Exception => e |
| exception_thrown = e |
| end |
| |
| if exception_thrown |
| # If the underlying YAML parser (e.g. Psych) threw an exception, I'm |
| # honestly not sure what the right thing to do is. For now I'll just |
| # print a warning. Should SafeYAML fail when Psych fails? |
| Kernel.warn "\n" |
| Kernel.warn "Discrepancy between SafeYAML and #{SafeYAML::YAML_ENGINE} on input:\n" |
| Kernel.warn "#{yaml.unindent}\n" |
| Kernel.warn "SafeYAML result:" |
| Kernel.warn "#{safe_result.inspect}\n" |
| Kernel.warn "#{SafeYAML::YAML_ENGINE} result:" |
| Kernel.warn "#{exception_thrown.inspect}\n" |
| |
| else |
| expect(safe_result).to eq(unsafe_result) |
| end |
| end |
| |
| context "by default" do |
| it "translates maps to hashes" do |
| parse <<-YAML |
| potayto: potahto |
| tomayto: tomahto |
| YAML |
| |
| expect(result).to eq({ |
| "potayto" => "potahto", |
| "tomayto" => "tomahto" |
| }) |
| end |
| |
| it "translates sequences to arrays" do |
| parse <<-YAML |
| - foo |
| - bar |
| - baz |
| YAML |
| |
| expect(result).to eq(["foo", "bar", "baz"]) |
| end |
| |
| it "translates most values to strings" do |
| parse "string: value" |
| expect(result).to eq({ "string" => "value" }) |
| end |
| |
| it "does not deserialize symbols" do |
| parse ":symbol: value" |
| expect(result).to eq({ ":symbol" => "value" }) |
| end |
| |
| it "translates valid integral numbers to integers" do |
| parse "integer: 1" |
| expect(result).to eq({ "integer" => 1 }) |
| end |
| |
| it "translates valid decimal numbers to floats" do |
| parse "float: 3.14" |
| expect(result).to eq({ "float" => 3.14 }) |
| end |
| |
| it "translates valid dates" do |
| parse "date: 2013-01-24" |
| expect(result).to eq({ "date" => Date.parse("2013-01-24") }) |
| end |
| |
| it "translates valid true/false values to booleans" do |
| parse <<-YAML |
| - yes |
| - true |
| - no |
| - false |
| YAML |
| |
| expect(result).to eq([true, true, false, false]) |
| end |
| |
| it "translates valid nulls to nil" do |
| parse <<-YAML |
| - |
| - ~ |
| - null |
| YAML |
| |
| expect(result).to eq([nil] * 3) |
| end |
| |
| it "matches the behavior of the underlying YAML engine w/ respect to capitalization of boolean values" do |
| parse_and_test <<-YAML |
| - true |
| - True |
| - TRUE |
| - tRue |
| - TRue |
| - False |
| - FALSE |
| - fAlse |
| - FALse |
| YAML |
| |
| # using Syck: [true, true, true, "tRue", "TRue", false, false, "fAlse", "FALse"] |
| # using Psych: all booleans |
| end |
| |
| it "matches the behavior of the underlying YAML engine w/ respect to capitalization of nil values" do |
| parse_and_test <<-YAML |
| - Null |
| - NULL |
| - nUll |
| - NUll |
| YAML |
| |
| # using Syck: [nil, nil, "nUll", "NUll"] |
| # using Psych: all nils |
| end |
| |
| it "translates quoted empty strings to strings (not nil)" do |
| parse "foo: ''" |
| expect(result).to eq({ "foo" => "" }) |
| end |
| |
| it "correctly reverse-translates strings encoded via #to_yaml" do |
| parse "5.10".to_yaml |
| expect(result).to eq("5.10") |
| end |
| |
| it "does not specially parse any double-quoted strings" do |
| parse <<-YAML |
| - "1" |
| - "3.14" |
| - "true" |
| - "false" |
| - "2013-02-03" |
| - "2013-02-03 16:27:00 -0600" |
| YAML |
| |
| expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"]) |
| end |
| |
| it "does not specially parse any single-quoted strings" do |
| parse <<-YAML |
| - '1' |
| - '3.14' |
| - 'true' |
| - 'false' |
| - '2013-02-03' |
| - '2013-02-03 16:27:00 -0600' |
| YAML |
| |
| expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"]) |
| end |
| |
| it "deals just fine with nested maps" do |
| parse <<-YAML |
| foo: |
| bar: |
| marco: polo |
| YAML |
| |
| expect(result).to eq({ "foo" => { "bar" => { "marco" => "polo" } } }) |
| end |
| |
| it "deals just fine with nested sequences" do |
| parse <<-YAML |
| - foo |
| - |
| - bar1 |
| - bar2 |
| - |
| - baz1 |
| - baz2 |
| YAML |
| |
| expect(result).to eq(["foo", ["bar1", "bar2", ["baz1", "baz2"]]]) |
| end |
| |
| it "applies the same transformations to keys as to values" do |
| parse <<-YAML |
| foo: string |
| :bar: symbol |
| 1: integer |
| 3.14: float |
| 2013-01-24: date |
| YAML |
| |
| expect(result).to eq({ |
| "foo" => "string", |
| ":bar" => "symbol", |
| 1 => "integer", |
| 3.14 => "float", |
| Date.parse("2013-01-24") => "date", |
| }) |
| end |
| |
| it "applies the same transformations to elements in sequences as to all values" do |
| parse <<-YAML |
| - foo |
| - :bar |
| - 1 |
| - 3.14 |
| - 2013-01-24 |
| YAML |
| |
| expect(result).to eq(["foo", ":bar", 1, 3.14, Date.parse("2013-01-24")]) |
| end |
| end |
| |
| context "for Ruby version #{RUBY_VERSION}" do |
| it "translates valid time values" do |
| parse "time: 2013-01-29 05:58:00 -0800" |
| expect(result).to eq({ "time" => Time.utc(2013, 1, 29, 13, 58, 0) }) |
| end |
| |
| it "applies the same transformation to elements in sequences" do |
| parse "- 2013-01-29 05:58:00 -0800" |
| expect(result).to eq([Time.utc(2013, 1, 29, 13, 58, 0)]) |
| end |
| |
| it "applies the same transformation to keys" do |
| parse "2013-01-29 05:58:00 -0800: time" |
| expect(result).to eq({ Time.utc(2013, 1, 29, 13, 58, 0) => "time" }) |
| end |
| end |
| |
| context "with symbol deserialization enabled" do |
| before :each do |
| SafeYAML::OPTIONS[:deserialize_symbols] = true |
| end |
| |
| after :each do |
| SafeYAML.restore_defaults! |
| end |
| |
| it "translates values starting with ':' to symbols" do |
| parse "symbol: :value" |
| expect(result).to eq({ "symbol" => :value }) |
| end |
| |
| it "applies the same transformation to keys" do |
| parse ":bar: symbol" |
| expect(result).to eq({ :bar => "symbol" }) |
| end |
| |
| it "applies the same transformation to elements in sequences" do |
| parse "- :bar" |
| expect(result).to eq([:bar]) |
| end |
| end |
| end |
| end |
| end |