safe_yaml 0.2.2 → 0.3

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.
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ gemspec
4
4
 
5
5
  group :development do
6
6
  gem "heredoc_unindent"
7
+ gem "pry"
7
8
  gem "rake"
8
9
  gem "rspec"
9
10
  end
data/Gemfile.lock CHANGED
@@ -1,13 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- safe_yaml (0.1)
4
+ safe_yaml (0.2.2)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
+ coderay (1.0.8)
9
10
  diff-lcs (1.1.3)
10
11
  heredoc_unindent (1.1.2)
12
+ method_source (0.8.1)
13
+ pry (0.9.11.2)
14
+ coderay (~> 1.0.5)
15
+ method_source (~> 0.8)
16
+ slop (~> 3.4)
11
17
  rake (10.0.3)
12
18
  rspec (2.12.0)
13
19
  rspec-core (~> 2.12.0)
@@ -17,12 +23,14 @@ GEM
17
23
  rspec-expectations (2.12.1)
18
24
  diff-lcs (~> 1.1.3)
19
25
  rspec-mocks (2.12.1)
26
+ slop (3.4.3)
20
27
 
21
28
  PLATFORMS
22
29
  ruby
23
30
 
24
31
  DEPENDENCIES
25
32
  heredoc_unindent
33
+ pry
26
34
  rake
27
35
  rspec
28
36
  safe_yaml!
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  SafeYAML
2
2
  ========
3
3
 
4
- *Parse (simple) YAML safely, without that pesky arbitrary code execution vulnerability.*
4
+ *Parse YAML safely, without that pesky arbitrary code execution vulnerability.*
5
5
 
6
6
  ***
7
7
 
@@ -38,4 +38,4 @@ With `YAML.safe_load`, that attacker would be thwarted:
38
38
  > YAML.safe_load(yaml)
39
39
  => {"foo; end; puts %(I'm in yr system!); def bar"=>"baz"}
40
40
 
41
- SafeYAML requires Ruby 1.9.2 or newer. Maybe I'll get around to writing a Syck handler eventually, at which point it could support older versions as well.
41
+ SafeYAML requires Ruby 1.8.7 or newer and works with both [Syck](http://www.ruby-doc.org/stdlib-1.8.7/libdoc/yaml/rdoc/YAML.html) and [Psych](http://github.com/tenderlove/psych).
@@ -1,20 +1,7 @@
1
1
  require "psych"
2
- require "yaml"
3
2
 
4
3
  module SafeYAML
5
- class Handler < Psych::Handler
6
- PREDEFINED_VALUES = {
7
- "" => nil,
8
- "~" => nil,
9
- "null" => nil,
10
- "yes" => true,
11
- "on" => true,
12
- "true" => true,
13
- "no" => false,
14
- "off" => false,
15
- "false" => false
16
- }.freeze
17
-
4
+ class PsychHandler < Psych::Handler
18
5
  def initialize
19
6
  @anchors = {}
20
7
  @stack = []
@@ -25,7 +12,7 @@ module SafeYAML
25
12
  end
26
13
 
27
14
  def add_to_current_structure(value, anchor=nil)
28
- value = transform_value(value)
15
+ value = Transform.to_proper_type(value)
29
16
 
30
17
  @anchors[anchor] = value if anchor
31
18
 
@@ -58,25 +45,6 @@ module SafeYAML
58
45
  end
59
46
  end
60
47
 
61
- def transform_value(value)
62
- if value.is_a?(String)
63
- if PREDEFINED_VALUES.include?(value.downcase)
64
- return PREDEFINED_VALUES[value.downcase]
65
-
66
- elsif value.match(/^:\w+$/)
67
- return value[1..-1].to_sym
68
-
69
- elsif value.match(/^\d+$/)
70
- return value.to_i
71
-
72
- elsif value.match(/^\d+(?:\.\d*)?$/) || value.match(/^\.\d+$/)
73
- return value.to_f
74
- end
75
- end
76
-
77
- value
78
- end
79
-
80
48
  def end_current_structure
81
49
  @stack.pop
82
50
  @current_structure = @stack.last
@@ -0,0 +1,49 @@
1
+ module SafeYAML
2
+ class SyckResolver
3
+ def initialize
4
+ @anchors = {}
5
+ end
6
+
7
+ def resolve_tree(tree)
8
+ case tree.kind
9
+ when :map
10
+ return resolve_map(tree.value)
11
+ when :seq
12
+ return resolve_seq(tree.value)
13
+ else
14
+ raise "Don't know how to resolve a #{tree.kind} tree!"
15
+ end
16
+ end
17
+
18
+ def resolve_node(node)
19
+ case node.kind
20
+ when :map
21
+ return resolve_map(node.value)
22
+ when :seq
23
+ return resolve_seq(node.value)
24
+ when :scalar
25
+ return resolve_scalar(node.value)
26
+ end
27
+ end
28
+
29
+ def resolve_map(map)
30
+ hash = {}
31
+ map.each do |key_node, value_node|
32
+ if resolve_node(key_node) == "<<"
33
+ hash.merge!(resolve_node(value_node))
34
+ else
35
+ hash[resolve_node(key_node)] = resolve_node(value_node)
36
+ end
37
+ end
38
+ return hash
39
+ end
40
+
41
+ def resolve_seq(seq)
42
+ seq.map { |node| resolve_node(node) }
43
+ end
44
+
45
+ def resolve_scalar(scalar)
46
+ Transform.to_proper_type(scalar)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ module SafeYAML
2
+ class Transform
3
+ PREDEFINED_VALUES = {
4
+ "" => nil,
5
+ "~" => nil,
6
+ "null" => nil,
7
+ "yes" => true,
8
+ "on" => true,
9
+ "true" => true,
10
+ "no" => false,
11
+ "off" => false,
12
+ "false" => false
13
+ }.freeze
14
+
15
+ def self.to_proper_type(value)
16
+ if value.is_a?(String)
17
+ if PREDEFINED_VALUES.include?(value.downcase)
18
+ return PREDEFINED_VALUES[value.downcase]
19
+
20
+ elsif value.match(/^:\w+$/)
21
+ return value[1..-1].to_sym
22
+
23
+ elsif value.match(/^\d+$/)
24
+ return value.to_i
25
+
26
+ elsif value.match(/^\d+(?:\.\d*)?$/) || value.match(/^\.\d+$/)
27
+ return value.to_f
28
+ end
29
+ end
30
+
31
+ value
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module SafeYAML
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3"
3
3
  end
data/lib/safe_yaml.rb CHANGED
@@ -1,10 +1,22 @@
1
- require "safe_yaml/handler"
1
+ require "yaml"
2
+ require "safe_yaml/transform"
2
3
  require "safe_yaml/version"
3
4
 
4
5
  module YAML
5
- def self.safe_load(yaml)
6
- safe_handler = SafeYAML::Handler.new
7
- Psych::Parser.new(safe_handler).parse(yaml)
8
- return safe_handler.result
6
+ if RUBY_VERSION >= "1.9.2"
7
+ require "safe_yaml/psych_handler"
8
+ def self.safe_load(yaml)
9
+ safe_handler = SafeYAML::PsychHandler.new
10
+ Psych::Parser.new(safe_handler).parse(yaml)
11
+ return safe_handler.result
12
+ end
13
+
14
+ else
15
+ require "safe_yaml/syck_resolver"
16
+ def self.safe_load(yaml)
17
+ safe_resolver = SafeYAML::SyckResolver.new
18
+ tree = YAML.parse(yaml)
19
+ return safe_resolver.resolve_tree(tree)
20
+ end
9
21
  end
10
22
  end
data/safe_yaml.gemspec CHANGED
@@ -6,13 +6,13 @@ Gem::Specification.new do |gem|
6
6
  gem.version = SafeYAML::VERSION
7
7
  gem.authors = "Dan Tao"
8
8
  gem.email = "daniel.tao@gmail.com"
9
- gem.description = %q{Parse (simple) YAML safely, without that pesky arbitrary code execution vulnerability.}
9
+ gem.description = %q{Parse YAML safely, without that pesky arbitrary code execution vulnerability.}
10
10
  gem.summary = %q{SameYAML adds a ::safe_load method to Ruby's built-in YAML module to parse YAML data for only basic types (strings, symbols, numbers, arrays, and hashes).}
11
- gem.homepage = "http://dtao.github.com/safe_yaml/"
11
+ gem.homepage = "http://github.com/dtao/safe_yaml"
12
12
 
13
13
  gem.files = `git ls-files`.split($\)
14
14
  gem.test_files = gem.files.grep(%r{^spec/})
15
15
  gem.require_paths = ["lib"]
16
16
 
17
- gem.required_ruby_version = ">= 1.9.2"
17
+ gem.required_ruby_version = ">= 1.8.7"
18
18
  end
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ if RUBY_VERSION >= "1.9.2"
4
+ require "safe_yaml/psych_handler"
5
+
6
+ describe SafeYAML::PsychHandler do
7
+ let(:handler) { SafeYAML::PsychHandler.new }
8
+ let(:parser) { Psych::Parser.new(handler) }
9
+ let(:result) { handler.result }
10
+
11
+ def parse(yaml)
12
+ parser.parse(yaml.unindent)
13
+ end
14
+
15
+ include SharedSpecs
16
+ end
17
+ end
@@ -4,33 +4,36 @@ require "safe_yaml"
4
4
  require "exploitable_back_door"
5
5
 
6
6
  describe YAML do
7
- before :each do
8
- ExploitableBackDoor.reset
9
- end
10
-
11
7
  describe "load" do
12
8
  if RUBY_VERSION >= "1.9.3"
13
- it "allows exploits through objects defined in YAML w/ !ruby/hash" do
14
- YAML.load "--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n"
15
- ExploitableBackDoor.should be_exploited
9
+ it "allows exploits through objects defined in YAML w/ !ruby/hash through custom :[]= methods" do
10
+ backdoor = YAML.load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
11
+ backdoor.should be_exploited_through_setter
12
+ end
13
+ end
14
+
15
+ if RUBY_VERSION >= "1.9.2"
16
+ it "allows exploits through objects defined in YAML w/ !ruby/object through" do
17
+ backdoor = YAML.load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
18
+ backdoor.should be_exploited_through_init_with
16
19
  end
17
20
  end
18
21
 
19
- it "allows exploits through objects defined in YAML w/ !ruby/object" do
20
- YAML.load "--- !ruby/object:ExploitableBackDoor\nfoo: bar\n"
21
- ExploitableBackDoor.should be_exploited
22
+ it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do
23
+ backdoor = YAML.load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
24
+ backdoor.should be_exploited_through_ivars
22
25
  end
23
26
  end
24
27
 
25
28
  describe "safe_load" do
26
- it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
27
- YAML.safe_load "--- !ruby/object:ExploitableBackDoor\nfoo: bar\n"
28
- ExploitableBackDoor.should_not be_exploited
29
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
30
+ object = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
31
+ object.should_not be_a(ExploitableBackDoor)
29
32
  end
30
33
 
31
- it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
32
- YAML.safe_load "--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n"
33
- ExploitableBackDoor.should_not be_exploited
34
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
35
+ object = YAML.safe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
36
+ object.should_not be_a(ExploitableBackDoor)
34
37
  end
35
38
 
36
39
  it "loads a plain ol' YAML document just fine" do
@@ -53,5 +56,48 @@ describe YAML do
53
56
  }
54
57
  }
55
58
  end
59
+
60
+ it "works for YAML documents with anchors and aliases" do
61
+ result = YAML.safe_load <<-YAML
62
+ - &id001 {}
63
+ - *id001
64
+ - *id001
65
+ YAML
66
+
67
+ result.should == [{}, {}, {}]
68
+ end
69
+
70
+ it "works for YAML documents with sections" do
71
+ result = YAML.safe_load <<-YAML
72
+ mysql: &foo
73
+ adapter: mysql
74
+ pool: 30
75
+ login: &login
76
+ username: dan
77
+ password: gobbledygook
78
+ local: &local
79
+ <<: *foo
80
+ <<: *login
81
+ host: localhost
82
+ YAML
83
+
84
+ result.should == {
85
+ "mysql" => {
86
+ "adapter" => "mysql",
87
+ "pool" => 30
88
+ },
89
+ "login" => {
90
+ "username" => "dan",
91
+ "password" => "gobbledygook"
92
+ },
93
+ "local" => {
94
+ "adapter" => "mysql",
95
+ "pool" => 30,
96
+ "username" => "dan",
97
+ "password" => "gobbledygook",
98
+ "host" => "localhost"
99
+ }
100
+ }
101
+ end
56
102
  end
57
103
  end
@@ -0,0 +1,125 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ require "safe_yaml/transform"
4
+
5
+ module SharedSpecs
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ it "translates most values to strings" do
9
+ parse "key: value"
10
+ result.should == { "key" => "value" }
11
+ end
12
+
13
+ it "translates values starting with ':' to symbols" do
14
+ parse ":key: value"
15
+ result.should == { :key => "value" }
16
+ end
17
+
18
+ it "translates valid integral numbers to integers" do
19
+ parse "integer: 1"
20
+ result.should == { "integer" => 1 }
21
+ end
22
+
23
+ it "translates valid decimal numbers to floats" do
24
+ parse "float: 3.14"
25
+ result.should == { "float" => 3.14 }
26
+ end
27
+
28
+ it "translates valid true/false values to booleans" do
29
+ parse <<-YAML
30
+ - yes
31
+ - true
32
+ - no
33
+ - false
34
+ YAML
35
+
36
+ result.should == [true, true, false, false]
37
+ end
38
+
39
+ it "translates valid nulls to nil" do
40
+ parse <<-YAML
41
+ -
42
+ - ~
43
+ - null
44
+ YAML
45
+
46
+ result.should == [nil] * 3
47
+ end
48
+
49
+ it "applies the same transformations to values as to keys" do
50
+ parse <<-YAML
51
+ string: value
52
+ symbol: :value
53
+ integer: 1
54
+ float: 3.14
55
+ YAML
56
+
57
+ result.should == {
58
+ "string" => "value",
59
+ "symbol" => :value,
60
+ "integer" => 1,
61
+ "float" => 3.14
62
+ }
63
+ end
64
+
65
+ it "translates sequences to arrays" do
66
+ parse <<-YAML
67
+ - foo
68
+ - bar
69
+ - baz
70
+ YAML
71
+
72
+ result.should == ["foo", "bar", "baz"]
73
+ end
74
+
75
+ it "applies the same transformations to elements in sequences as to all values" do
76
+ parse <<-YAML
77
+ - string
78
+ - :symbol
79
+ - 1
80
+ - 3.14
81
+ YAML
82
+
83
+ result.should == ["string", :symbol, 1, 3.14]
84
+ end
85
+
86
+ it "translates maps to hashes" do
87
+ parse <<-YAML
88
+ foo: blah
89
+ bar: glah
90
+ baz: flah
91
+ YAML
92
+
93
+ result.should == {
94
+ "foo" => "blah",
95
+ "bar" => "glah",
96
+ "baz" => "flah"
97
+ }
98
+ end
99
+
100
+ it "applies the same transformations to values in hashes as to all values" do
101
+ parse <<-YAML
102
+ foo: :symbol
103
+ bar: 1
104
+ baz: 3.14
105
+ YAML
106
+
107
+ result.should == {
108
+ "foo" => :symbol,
109
+ "bar" => 1,
110
+ "baz" => 3.14
111
+ }
112
+ end
113
+
114
+ it "deals just fine with nested maps" do
115
+ parse <<-YAML
116
+ foo:
117
+ bar:
118
+ marco: polo
119
+ YAML
120
+
121
+ result.should == { "foo" => { "bar" => { "marco" => "polo" } } }
122
+ end
123
+ end
124
+ end
125
+ end
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,6 @@ $LOAD_PATH << File.join(ROOT, "lib")
5
5
  $LOAD_PATH << File.join(HERE, "support")
6
6
 
7
7
  require "heredoc_unindent"
8
+ require "pry"
9
+
10
+ require File.join(HERE, "shared_specs")
@@ -1,23 +1,29 @@
1
1
  class ExploitableBackDoor
2
- @@exploited = false
2
+ def exploited?
3
+ @exploited_through_setter || @exploited_through_init_with || @exploited_through_ivars
4
+ end
5
+
6
+ def exploited_through_setter?
7
+ @exploited_through_setter
8
+ end
3
9
 
4
- def self.exploited?
5
- @@exploited
10
+ def exploited_through_init_with?
11
+ @exploited_through_init_with
6
12
  end
7
13
 
8
- def self.reset
9
- @@exploited = false
14
+ def exploited_through_ivars?
15
+ self.instance_variables.any?
10
16
  end
11
17
 
12
18
  def init_with(command)
13
19
  # Note: this is how bad this COULD be.
14
20
  # system("#{command}")
15
- @@exploited = true
21
+ @exploited_through_init_with = true
16
22
  end
17
23
 
18
24
  def []=(command, arguments)
19
25
  # Note: this is how bad this COULD be.
20
26
  # system("#{command} #{arguments}")
21
- @@exploited = true
27
+ @exploited_through_setter = true
22
28
  end
23
29
  end
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ if RUBY_VERSION < "1.9.2"
4
+ require "safe_yaml/syck_resolver"
5
+
6
+ describe SafeYAML::SyckResolver do
7
+ let(:resolver) { SafeYAML::SyckResolver.new }
8
+ let(:result) { @result }
9
+
10
+ def parse(yaml)
11
+ tree = YAML.parse(yaml.unindent)
12
+ @result = resolver.resolve_tree(tree)
13
+ end
14
+
15
+ include SharedSpecs
16
+ end
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_yaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: '0.3'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-17 00:00:00.000000000 Z
12
+ date: 2013-01-18 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: Parse (simple) YAML safely, without that pesky arbitrary code execution
15
- vulnerability.
14
+ description: Parse YAML safely, without that pesky arbitrary code execution vulnerability.
16
15
  email: daniel.tao@gmail.com
17
16
  executables: []
18
17
  extensions: []
@@ -24,14 +23,18 @@ files:
24
23
  - README.md
25
24
  - Rakefile
26
25
  - lib/safe_yaml.rb
27
- - lib/safe_yaml/handler.rb
26
+ - lib/safe_yaml/psych_handler.rb
27
+ - lib/safe_yaml/syck_resolver.rb
28
+ - lib/safe_yaml/transform.rb
28
29
  - lib/safe_yaml/version.rb
29
30
  - safe_yaml.gemspec
30
- - spec/handler_spec.rb
31
+ - spec/psych_handler_spec.rb
31
32
  - spec/safe_yaml_spec.rb
33
+ - spec/shared_specs.rb
32
34
  - spec/spec_helper.rb
33
35
  - spec/support/exploitable_back_door.rb
34
- homepage: http://dtao.github.com/safe_yaml/
36
+ - spec/syck_resolver_spec.rb
37
+ homepage: http://github.com/dtao/safe_yaml
35
38
  licenses: []
36
39
  post_install_message:
37
40
  rdoc_options: []
@@ -42,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
45
  requirements:
43
46
  - - ! '>='
44
47
  - !ruby/object:Gem::Version
45
- version: 1.9.2
48
+ version: 1.8.7
46
49
  required_rubygems_version: !ruby/object:Gem::Requirement
47
50
  none: false
48
51
  requirements:
@@ -57,7 +60,9 @@ specification_version: 3
57
60
  summary: SameYAML adds a ::safe_load method to Ruby's built-in YAML module to parse
58
61
  YAML data for only basic types (strings, symbols, numbers, arrays, and hashes).
59
62
  test_files:
60
- - spec/handler_spec.rb
63
+ - spec/psych_handler_spec.rb
61
64
  - spec/safe_yaml_spec.rb
65
+ - spec/shared_specs.rb
62
66
  - spec/spec_helper.rb
63
67
  - spec/support/exploitable_back_door.rb
68
+ - spec/syck_resolver_spec.rb
data/spec/handler_spec.rb DELETED
@@ -1,172 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper")
2
-
3
- require "safe_yaml/handler"
4
-
5
- describe SafeYAML::Handler do
6
- let(:handler) { SafeYAML::Handler.new }
7
- let(:parser) { Psych::Parser.new(handler) }
8
- let(:result) { handler.result }
9
-
10
- def parse(yaml)
11
- parser.parse(yaml.unindent)
12
- end
13
-
14
- it "translates most values to strings" do
15
- parser.parse "key: value"
16
- result.should == { "key" => "value" }
17
- end
18
-
19
- it "translates values starting with ':' to symbols" do
20
- parser.parse ":key: value"
21
- result.should == { :key => "value" }
22
- end
23
-
24
- it "translates valid integral numbers to integers" do
25
- parser.parse "integer: 1"
26
- result.should == { "integer" => 1 }
27
- end
28
-
29
- it "translates valid decimal numbers to floats" do
30
- parser.parse "float: 3.14"
31
- result.should == { "float" => 3.14 }
32
- end
33
-
34
- it "translates valid true/false values to booleans" do
35
- parser.parse <<-YAML
36
- - yes
37
- - true
38
- - no
39
- - false
40
- YAML
41
-
42
- result.should == [true, true, false, false]
43
- end
44
-
45
- it "translates valid nulls to nil" do
46
- parser.parse <<-YAML
47
- -
48
- - ~
49
- - null
50
- YAML
51
-
52
- result.should == [nil] * 3
53
- end
54
-
55
- it "applies the same transformations to values as to keys" do
56
- parse <<-YAML
57
- string: value
58
- symbol: :value
59
- integer: 1
60
- float: 3.14
61
- YAML
62
-
63
- result.should == {
64
- "string" => "value",
65
- "symbol" => :value,
66
- "integer" => 1,
67
- "float" => 3.14
68
- }
69
- end
70
-
71
- it "translates sequences to arrays" do
72
- parse <<-YAML
73
- - foo
74
- - bar
75
- - baz
76
- YAML
77
-
78
- result.should == ["foo", "bar", "baz"]
79
- end
80
-
81
- it "applies the same transformations to elements in sequences as to all values" do
82
- parse <<-YAML
83
- - string
84
- - :symbol
85
- - 1
86
- - 3.14
87
- YAML
88
-
89
- result.should == ["string", :symbol, 1, 3.14]
90
- end
91
-
92
- it "translates maps to hashes" do
93
- parse <<-YAML
94
- foo: blah
95
- bar: glah
96
- baz: flah
97
- YAML
98
-
99
- result.should == {
100
- "foo" => "blah",
101
- "bar" => "glah",
102
- "baz" => "flah"
103
- }
104
- end
105
-
106
- it "applies the same transformations to values in hashes as to all values" do
107
- parse <<-YAML
108
- foo: :symbol
109
- bar: 1
110
- baz: 3.14
111
- YAML
112
-
113
- result.should == {
114
- "foo" => :symbol,
115
- "bar" => 1,
116
- "baz" => 3.14
117
- }
118
- end
119
-
120
- it "deals just fine with nested maps" do
121
- parse <<-YAML
122
- foo:
123
- bar:
124
- marco: polo
125
- YAML
126
-
127
- result.should == { "foo" => { "bar" => { "marco" => "polo" } } }
128
- end
129
-
130
- it "deals just fine with aliases and anchors" do
131
- parse <<-YAML
132
- - &id001 {}
133
- - *id001
134
- - *id001
135
- YAML
136
-
137
- result.should == [{}, {}, {}]
138
- end
139
-
140
- it "deals just fine with sections" do
141
- parse <<-YAML
142
- mysql: &mysql
143
- adapter: mysql
144
- pool: 30
145
- login: &login
146
- username: dan
147
- password: gobbledygook
148
- local: &local
149
- <<: *mysql
150
- <<: *login
151
- host: localhost
152
- YAML
153
-
154
- result.should == {
155
- "mysql" => {
156
- "adapter" => "mysql",
157
- "pool" => 30
158
- },
159
- "login" => {
160
- "username" => "dan",
161
- "password" => "gobbledygook"
162
- },
163
- "local" => {
164
- "adapter" => "mysql",
165
- "pool" => 30,
166
- "username" => "dan",
167
- "password" => "gobbledygook",
168
- "host" => "localhost"
169
- }
170
- }
171
- end
172
- end