* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / ruby / marshaltestlib.rb
blob7f100b787362b40eecc24f7a8e4bd8165dabad1a
1 # coding: utf-8
2 # frozen_string_literal: false
3 module MarshalTestLib
4   # include this module to a Test::Unit::TestCase and define encode(o) and
5   # decode(s) methods.  e.g.
6   #
7   # def encode(o)
8   #   SOAPMarshal.dump(o)
9   # end
10   #
11   # def decode(s)
12   #   SOAPMarshal.load(s)
13   # end
15   NegativeZero = (-1.0 / (1.0 / 0.0))
17   module Mod1; end
18   module Mod2; end
20   def marshaltest(o1)
21     str = encode(o1)
22     print str.dump, "\n" if $DEBUG
23     o2 = decode(str)
24     o2
25   end
27   def marshal_equal(o1, msg = nil)
28     msg = msg ? msg + "(#{ caller[0] })" : caller[0]
29     o2 = marshaltest(o1)
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)
37     if block_given?
38       assert_equal(yield(o1), yield(o2), msg)
39     else
40       assert_equal(o1, o2, msg)
41     end
42   end
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
48       ancestry
49     end
50   end
52   class MyObject; def initialize(v) @v = v end; attr_reader :v; end
53   def test_object
54     o1 = Object.new
55     o1.instance_eval { @iv = 1 }
56     marshal_equal(o1) {|o| o.instance_eval { @iv }}
57   end
59   def test_object_subclass
60     marshal_equal(MyObject.new(2)) {|o| o.v}
61   end
63   def test_object_extend
64     o1 = Object.new
65     o1.extend(Mod1)
66     marshal_equal_with_ancestry(o1)
67     o1.extend(Mod2)
68     marshal_equal_with_ancestry(o1)
69   end
71   def test_object_subclass_extend
72     o1 = MyObject.new(2)
73     o1.extend(Mod1)
74     marshal_equal_with_ancestry(o1)
75     o1.extend(Mod2)
76     marshal_equal_with_ancestry(o1)
77   end
79   def test_object_prepend
80     bug8041 = '[ruby-core:53202] [Bug #8041]'
82     o1 = MyObject.new(42)
83     o1.singleton_class.class_eval {prepend Mod1}
84     assert_nothing_raised(ArgumentError, bug8041) {
85       marshal_equal_with_ancestry(o1, bug8041)
86     }
87   end
89   class MyArray < Array
90     def initialize(v, *args)
91       super(args)
92       @v = v
93     end
94   end
95   def test_array
96     marshal_equal(5)
97     marshal_equal([1,2,3])
98   end
100   def test_array_subclass
101     marshal_equal(MyArray.new(0, 1, 2, 3))
102   end
104   def test_array_ivar
105     o1 = Array.new
106     o1.instance_eval { @iv = 1 }
107     marshal_equal(o1) {|o| o.instance_eval { @iv }}
108   end
110   class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end
111   def test_exception
112     marshal_equal(Exception.new('foo')) {|o| o.message}
113     obj = Object.new
114     e = assert_raise(NoMethodError) {obj.no_such_method()}
115     marshal_equal(e) {|o| o.message.lines.first.chomp}
116   end
118   def test_exception_subclass
119     marshal_equal(MyException.new(20, "bar")) {|o| [o.message, o.v]}
120   end
122   def test_false
123     marshal_equal(false)
124   end
126   class MyHash < Hash; def initialize(v, *args) super(*args); @v = v; end end
127   def test_hash
128     marshal_equal({1=>2, 3=>4})
129   end
131   def test_hash_default
132     h = Hash.new(:default)
133     h[5] = 6
134     marshal_equal(h)
135   end
137   def test_hash_subclass
138     h = MyHash.new(7, 8)
139     h[4] = 5
140     marshal_equal(h)
141   end
143   def test_hash_default_proc
144     h = Hash.new {}
145     assert_raise(TypeError) { marshaltest(h) }
146   end
148   def test_hash_ivar
149     o1 = Hash.new
150     o1.instance_eval { @iv = 1 }
151     marshal_equal(o1) {|o| o.instance_eval { @iv }}
152   end
154   def test_hash_extend
155     o1 = Hash.new
156     o1.extend(Mod1)
157     marshal_equal_with_ancestry(o1)
158     o1.extend(Mod2)
159     marshal_equal_with_ancestry(o1)
160   end
162   def test_hash_subclass_extend
163     o1 = MyHash.new(2)
164     o1.extend(Mod1)
165     marshal_equal_with_ancestry(o1)
166     o1.extend(Mod2)
167     marshal_equal_with_ancestry(o1)
168   end
170   def test_bignum
171     marshal_equal(-0x4000_0000_0000_0001)
172     marshal_equal(-0x4000_0001)
173     marshal_equal(0x4000_0000)
174     marshal_equal(0x4000_0000_0000_0000)
175   end
177   def test_fixnum
178     marshal_equal(-0x4000_0000)
179     marshal_equal(-0x3fff_ffff)
180     marshal_equal(-1)
181     marshal_equal(0)
182     marshal_equal(1)
183     marshal_equal(0x3fff_ffff)
184   end
186   def test_float
187     marshal_equal(-1.0)
188     marshal_equal(0.0)
189     marshal_equal(1.0)
190   end
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}
197   end
199   class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end
200   def test_range
201     marshal_equal(1..2)
202     marshal_equal(1...3)
203   end
205   def test_range_subclass
206     marshal_equal(MyRange.new(4,5,8, false))
207   end
209   class MyRegexp < Regexp; def initialize(v, *args) super(*args); @v = v; end end
210   def test_regexp
211     marshal_equal(/a/)
212     marshal_equal(/A/i)
213     marshal_equal(/A/mx)
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
220   end
222   def test_regexp_subclass
223     marshal_equal(MyRegexp.new(10, "a"))
224   end
226   class MyString < String; def initialize(v, *args) super(*args); @v = v; end end
227   def test_string
228     marshal_equal("abc")
229   end
231   def test_string_ivar
232     o1 = ""
233     o1.instance_eval { @iv = 1 }
234     marshal_equal(o1) {|o| o.instance_eval { @iv }}
235   end
237   def test_string_subclass
238     marshal_equal(MyString.new(10, "a"))
239   end
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 }
247     }
248   end
250   def test_string_subclass_extend
251     o = "abc"
252     o.extend(Mod1)
253     str = MyString.new(o, "c")
254     marshal_equal(str) { |v|
255       assert_kind_of(Mod1, v.instance_eval { @v })
256     }
257   end
259   MyStruct = Struct.new("MyStruct", :a, :b)
260   class MySubStruct < MyStruct; def initialize(v, *args) super(*args); @v = v; end end
261   def test_struct
262     marshal_equal(MyStruct.new(1,2))
263   end
265   def test_struct_subclass
266     marshal_equal(MySubStruct.new(10,1,2))
267   end
269   def test_struct_ivar
270     o1 = MyStruct.new
271     o1.instance_eval { @iv = 1 }
272     marshal_equal(o1) {|o| o.instance_eval { @iv }}
273   end
275   def test_struct_subclass_extend
276     o1 = MyStruct.new
277     o1.extend(Mod1)
278     marshal_equal_with_ancestry(o1)
279     o1.extend(Mod2)
280     marshal_equal_with_ancestry(o1)
281   end
283   def test_symbol
284     marshal_equal(:a)
285     marshal_equal(:a?)
286     marshal_equal(:a!)
287     marshal_equal(:a=)
288     marshal_equal(:|)
289     marshal_equal(:^)
290     marshal_equal(:&)
291     marshal_equal(:<=>)
292     marshal_equal(:==)
293     marshal_equal(:===)
294     marshal_equal(:=~)
295     marshal_equal(:>)
296     marshal_equal(:>=)
297     marshal_equal(:<)
298     marshal_equal(:<=)
299     marshal_equal(:<<)
300     marshal_equal(:>>)
301     marshal_equal(:+)
302     marshal_equal(:-)
303     marshal_equal(:*)
304     marshal_equal(:/)
305     marshal_equal(:%)
306     marshal_equal(:**)
307     marshal_equal(:~)
308     marshal_equal(:+@)
309     marshal_equal(:-@)
310     marshal_equal(:[])
311     marshal_equal(:[]=)
312     marshal_equal(:`)   #`
313     marshal_equal("a b".intern)
314   end
316   class MyTime < Time; def initialize(v, *args) super(*args); @v = v; end end
317   def test_time
318     # once there was a bug caused by usec overflow.  try a little harder.
319     10.times do
320       t = Time.now
321       marshal_equal(t, t.usec.to_s)
322     end
323   end
325   def test_time_subclass
326     marshal_equal(MyTime.new(10))
327   end
329   def test_time_ivar
330     o1 = Time.now
331     o1.instance_eval { @iv = 1 }
332     marshal_equal(o1) {|o| o.instance_eval { @iv }}
333   end
335   def test_time_in_array
336     t = Time.now
337     assert_equal([t,t], Marshal.load(Marshal.dump([t, t])), "[ruby-dev:34159]")
338   end
340   def test_true
341     marshal_equal(true)
342   end
344   def test_nil
345     marshal_equal(nil)
346   end
348   def test_share
349     o = [:share]
350     o1 = [o, o]
351     o2 = marshaltest(o1)
352     assert_same(o2.first, o2.last)
353   end
355   class CyclicRange < Range
356     def <=>(other); true; end
357   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) }
362     o2 = marshaltest(o1)
363     assert_same(o2, o2.begin)
364     assert_same(o2, o2.end)
365   end
367   def test_singleton
368     o = Object.new
369     def o.m() 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)}
376     o = Object.new
377     c = class << o
378       @v = 1
379       class C; self; end
380     end
381     assert_raise(TypeError) { marshaltest(o) }
382     assert_raise(TypeError) { marshaltest(c) }
383     assert_raise(TypeError) { marshaltest(ARGF) }
384     assert_raise(TypeError) { marshaltest(ENV) }
385   end
387   def test_extend
388     o = Object.new
389     o.extend Mod1
390     marshal_equal(o) { |obj| obj.kind_of? Mod1 }
391     o = Object.new
392     o.extend Mod1
393     o.extend Mod2
394     marshal_equal_with_ancestry(o)
395     o = Object.new
396     o.extend Module.new
397     assert_raise(TypeError) { marshaltest(o) }
398   end
400   def test_extend_string
401     o = ""
402     o.extend Mod1
403     marshal_equal(o) { |obj| obj.kind_of? Mod1 }
404     o = ""
405     o.extend Mod1
406     o.extend Mod2
407     marshal_equal_with_ancestry(o)
408     o = ""
409     o.extend Module.new
410     assert_raise(TypeError) { marshaltest(o) }
411   end
413   def test_anonymous
414     c = Class.new
415     assert_raise(TypeError) { marshaltest(c) }
416     o = c.new
417     assert_raise(TypeError) { marshaltest(o) }
418     m = Module.new
419     assert_raise(TypeError) { marshaltest(m) }
420   end
422   def test_string_empty
423     marshal_equal("")
424   end
426   def test_string_crlf
427     marshal_equal("\r\n")
428   end
430   def test_string_escape
431     marshal_equal("\0<;;>\1;;")
432   end
434   MyStruct2 = Struct.new(:a, :b)
435   def test_struct_toplevel
436     o = MyStruct2.new(1,2)
437     marshal_equal(o)
438   end