2 # frozen_string_literal: false
4 # include this module to a Test::Unit::TestCase and define encode(o) and
5 # decode(s) methods. e.g.
15 NegativeZero = (-1.0 / (1.0 / 0.0))
22 print str.dump, "\n" if $DEBUG
27 def marshal_equal(o1, msg = nil)
28 msg = msg ? msg + "(#{ caller[0] })" : caller[0]
30 assert_equal(o1.class, o2.class, msg)
31 iv1 = o1.instance_variables.sort
32 iv2 = o2.instance_variables.sort
33 assert_equal(iv1, iv2)
34 val1 = iv1.map {|var| o1.instance_eval {eval var.to_s}}
35 val2 = iv1.map {|var| o2.instance_eval {eval var.to_s}}
36 assert_equal(val1, val2, msg)
38 assert_equal(yield(o1), yield(o2), msg)
40 assert_equal(o1, o2, msg)
44 def marshal_equal_with_ancestry(o1, msg = nil)
45 marshal_equal(o1, msg) do |o|
46 ancestry = o.singleton_class.ancestors
47 ancestry[ancestry.index(o.singleton_class)] = :singleton_class
52 class MyObject; def initialize(v) @v = v end; attr_reader :v; end
55 o1.instance_eval { @iv = 1 }
56 marshal_equal(o1) {|o| o.instance_eval { @iv }}
59 def test_object_subclass
60 marshal_equal(MyObject.new(2)) {|o| o.v}
63 def test_object_extend
66 marshal_equal_with_ancestry(o1)
68 marshal_equal_with_ancestry(o1)
71 def test_object_subclass_extend
74 marshal_equal_with_ancestry(o1)
76 marshal_equal_with_ancestry(o1)
79 def test_object_prepend
80 bug8041 = '[ruby-core:53202] [Bug #8041]'
83 o1.singleton_class.class_eval {prepend Mod1}
84 assert_nothing_raised(ArgumentError, bug8041) {
85 marshal_equal_with_ancestry(o1, bug8041)
90 def initialize(v, *args)
97 marshal_equal([1,2,3])
100 def test_array_subclass
101 marshal_equal(MyArray.new(0, 1, 2, 3))
106 o1.instance_eval { @iv = 1 }
107 marshal_equal(o1) {|o| o.instance_eval { @iv }}
110 class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end
112 marshal_equal(Exception.new('foo')) {|o| o.message}
114 e = assert_raise(NoMethodError) {obj.no_such_method()}
115 marshal_equal(e) {|o| o.message.lines.first.chomp}
118 def test_exception_subclass
119 marshal_equal(MyException.new(20, "bar")) {|o| [o.message, o.v]}
126 class MyHash < Hash; def initialize(v, *args) super(*args); @v = v; end end
128 marshal_equal({1=>2, 3=>4})
131 def test_hash_default
132 h = Hash.new(:default)
137 def test_hash_subclass
143 def test_hash_default_proc
145 assert_raise(TypeError) { marshaltest(h) }
150 o1.instance_eval { @iv = 1 }
151 marshal_equal(o1) {|o| o.instance_eval { @iv }}
157 marshal_equal_with_ancestry(o1)
159 marshal_equal_with_ancestry(o1)
162 def test_hash_subclass_extend
165 marshal_equal_with_ancestry(o1)
167 marshal_equal_with_ancestry(o1)
171 marshal_equal(-0x4000_0000_0000_0001)
172 marshal_equal(-0x4000_0001)
173 marshal_equal(0x4000_0000)
174 marshal_equal(0x4000_0000_0000_0000)
178 marshal_equal(-0x4000_0000)
179 marshal_equal(-0x3fff_ffff)
183 marshal_equal(0x3fff_ffff)
192 def test_float_inf_nan
193 marshal_equal(1.0/0.0)
194 marshal_equal(-1.0/0.0)
195 marshal_equal(0.0/0.0) {|o| o.nan?}
196 marshal_equal(NegativeZero) {|o| 1.0/o}
199 class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end
205 def test_range_subclass
206 marshal_equal(MyRange.new(4,5,8, false))
209 class MyRegexp < Regexp; def initialize(v, *args) super(*args); @v = v; end end
214 marshal_equal(/a\u3042/)
215 marshal_equal(/ać/)
216 assert_equal(Regexp.new("ć".force_encoding("ASCII-8BIT")),
217 Marshal.load("\004\b/\b\343\201\202\000"))
218 assert_equal(/au3042/, Marshal.load("\004\b/\fa\\u3042\000"))
219 #assert_equal(/au3042/u, Marshal.load("\004\b/\fa\\u3042@")) # spec
222 def test_regexp_subclass
223 marshal_equal(MyRegexp.new(10, "a"))
226 class MyString < String; def initialize(v, *args) super(*args); @v = v; end end
233 o1.instance_eval { @iv = 1 }
234 marshal_equal(o1) {|o| o.instance_eval { @iv }}
237 def test_string_subclass
238 marshal_equal(MyString.new(10, "a"))
241 def test_string_subclass_cycle
242 str = MyString.new(10, "b")
243 str.instance_eval { @v = str }
244 marshal_equal(str) { |o|
245 assert_same(o, o.instance_eval { @v })
246 o.instance_eval { @v }
250 def test_string_subclass_extend
253 str = MyString.new(o, "c")
254 marshal_equal(str) { |v|
255 assert_kind_of(Mod1, v.instance_eval { @v })
259 MyStruct = Struct.new("MyStruct", :a, :b)
260 class MySubStruct < MyStruct; def initialize(v, *args) super(*args); @v = v; end end
262 marshal_equal(MyStruct.new(1,2))
265 def test_struct_subclass
266 marshal_equal(MySubStruct.new(10,1,2))
271 o1.instance_eval { @iv = 1 }
272 marshal_equal(o1) {|o| o.instance_eval { @iv }}
275 def test_struct_subclass_extend
278 marshal_equal_with_ancestry(o1)
280 marshal_equal_with_ancestry(o1)
313 marshal_equal("a b".intern)
316 class MyTime < Time; def initialize(v, *args) super(*args); @v = v; end end
318 # once there was a bug caused by usec overflow. try a little harder.
321 marshal_equal(t, t.usec.to_s)
325 def test_time_subclass
326 marshal_equal(MyTime.new(10))
331 o1.instance_eval { @iv = 1 }
332 marshal_equal(o1) {|o| o.instance_eval { @iv }}
335 def test_time_in_array
337 assert_equal([t,t], Marshal.load(Marshal.dump([t, t])), "[ruby-dev:34159]")
352 assert_same(o2.first, o2.last)
355 class CyclicRange < Range
356 def <=>(other); true; end
358 def test_range_cyclic
359 return unless CyclicRange.respond_to?(:allocate) # test for 1.8
360 o1 = CyclicRange.allocate
361 o1.instance_eval { initialize(o1, o1) }
363 assert_same(o2, o2.begin)
364 assert_same(o2, o2.end)
370 assert_raise(TypeError) { marshaltest(o) }
372 bug8043 = '[ruby-core:53206] [Bug #8043]'
373 class << o; prepend Mod1; end
374 assert_raise(TypeError, bug8043) {marshaltest(o)}
381 assert_raise(TypeError) { marshaltest(o) }
382 assert_raise(TypeError) { marshaltest(c) }
383 assert_raise(TypeError) { marshaltest(ARGF) }
384 assert_raise(TypeError) { marshaltest(ENV) }
390 marshal_equal(o) { |obj| obj.kind_of? Mod1 }
394 marshal_equal_with_ancestry(o)
397 assert_raise(TypeError) { marshaltest(o) }
400 def test_extend_string
403 marshal_equal(o) { |obj| obj.kind_of? Mod1 }
407 marshal_equal_with_ancestry(o)
410 assert_raise(TypeError) { marshaltest(o) }
415 assert_raise(TypeError) { marshaltest(c) }
417 assert_raise(TypeError) { marshaltest(o) }
419 assert_raise(TypeError) { marshaltest(m) }
422 def test_string_empty
427 marshal_equal("\r\n")
430 def test_string_escape
431 marshal_equal("\0<;;>\1;;")
434 MyStruct2 = Struct.new(:a, :b)
435 def test_struct_toplevel
436 o = MyStruct2.new(1,2)