1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# frozen_string_literal: true
require_relative 'helper'
module Psych
class TestHash < TestCase
class X < Hash
end
class HashWithIvar < Hash
def initialize
@keys = []
super
end
def []=(k, v)
@keys << k
super(k, v)
end
end
class HashWithCustomInit < Hash
attr_reader :obj
def initialize(obj)
@obj = obj
end
end
class HashWithCustomInitNoIvar < Hash
def initialize(obj)
# *shrug*
end
end
def setup
super
@hash = { :a => 'b' }
end
def test_hash_with_ivar
t1 = HashWithIvar.new
t1[:foo] = :bar
t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
def test_referenced_hash_with_ivar
a = [1,2,3,4,5]
t1 = [HashWithCustomInit.new(a)]
t1 << t1.first
assert_cycle t1
end
def test_custom_initialized
a = [1,2,3,4,5]
t1 = HashWithCustomInit.new(a)
t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
def test_custom_initialize_no_ivar
t1 = HashWithCustomInitNoIvar.new(nil)
t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
def test_hash_subclass_with_ivars
x = X.new
x[:a] = 'b'
x.instance_variable_set :@foo, 'bar'
dup = Psych.unsafe_load Psych.dump x
assert_cycle x
assert_equal 'bar', dup.instance_variable_get(:@foo)
assert_equal X, dup.class
end
def test_load_with_class_syck_compatibility
hash = Psych.unsafe_load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n"
assert_equal({ user_id: 7, username: 'Lucas'}, hash)
end
def test_empty_subclass
assert_match "!ruby/hash:#{X}", Psych.dump(X.new)
x = Psych.unsafe_load Psych.dump X.new
assert_equal X, x.class
end
def test_map
x = Psych.unsafe_load "--- !map:#{X} { }\n"
assert_equal X, x.class
end
def test_self_referential
@hash['self'] = @hash
assert_cycle(@hash)
end
def test_cycles
assert_cycle(@hash)
end
def test_ref_append
hash = Psych.unsafe_load(<<~eoyml)
---
foo: &foo
hello: world
bar:
<<: *foo
eoyml
assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
end
def test_anchor_reuse
hash = Psych.unsafe_load(<<~eoyml)
---
foo: &foo
hello: world
bar: *foo
eoyml
assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
assert_same(hash.fetch("foo"), hash.fetch("bar"))
end
def test_raises_if_anchor_not_defined
assert_raise(Psych::BadAlias) do
Psych.unsafe_load(<<~eoyml)
---
foo: &foo
hello: world
bar: *not_foo
eoyml
end
end
def test_recursive_hash
h = { }
h["recursive_reference"] = h
loaded = Psych.load(Psych.dump(h), aliases: true)
assert_same loaded, loaded.fetch("recursive_reference")
end
def test_recursive_hash_uses_alias
h = { }
h["recursive_reference"] = h
assert_raise(AliasesNotEnabled) do
Psych.load(Psych.dump(h), aliases: false)
end
end
def test_key_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
pend "This Ruby implementation doesn't support string deduplication"
end
hashes = Psych.load(<<~eoyml)
---
- unique_identifier: 1
- unique_identifier: 2
eoyml
assert_same hashes[0].keys.first, hashes[1].keys.first
end
end
end
|