require 'test/unit' class TestMarshal < Test::Unit::TestCase # # Check that two arrays contain the same "bag" of elements. # A mathematical bag differs from a "set" by counting the # occurences of each element. So as a bag [1,2,1] differs from # [2,1] (but is equal to [1,1,2]). # # The method only relies on the == operator to match objects # from the two arrays. The elements of the arrays may contain # objects that are not "Comparable". # # FIXME: This should be moved to common location. def assert_bag_equal(expected, actual) # For each object in "actual" we remove an equal object # from "expected". If we can match objects pairwise from the # two arrays we have two equal "bags". The method Array#index # uses == internally. We operate on a copy of "expected" to # avoid destructively changing the argument. # expected_left = expected.dup actual.each do |x| if j = expected_left.index(x) expected_left.slice!(j) end end assert( expected.length == actual.length && expected_left.length == 0, "Expected: #{expected.inspect}, Actual: #{actual.inspect}") end class A attr :a1 attr :a2 def initialize(a1, a2) @a1, @a2 = a1, a2 end end class B attr :b1 attr :b2 def initialize(b1, b2) @b1 = A.new(b1, 2*b1) @b2 = b2 end end # Dump/load to string def test_s_dump_load1 b = B.new(10, "wombat") assert_equal(10, b.b1.a1) assert_equal(20, b.b1.a2) assert_equal("wombat", b.b2) s = Marshal.dump(b) assert_instance_of(String, s) newb = Marshal.load(s) assert_equal(10, newb.b1.a1) assert_equal(20, newb.b1.a2) assert_equal("wombat", newb.b2) assert(newb.__id__ != b.__id__) assert_raise(ArgumentError) { Marshal.dump(b, 1) } end def test_s_dump_load2 b = B.new(10, "wombat") assert_equal(10, b.b1.a1) assert_equal(20, b.b1.a2) assert_equal("wombat", b.b2) File.open("_dl", "w") { |f| Marshal.dump(b, f) } begin newb = nil File.open("_dl") { |f| newb = Marshal.load(f) } assert_equal(10, newb.b1.a1) assert_equal(20, newb.b1.a2) assert_equal("wombat", newb.b2) ensure File.delete("_dl") end end def test_s_dump_load3 b = B.new(10, "wombat") s = Marshal.dump(b) res = [] newb = Marshal.load(s, proc { |obj| res << obj unless obj.kind_of?(Fixnum)}) assert_equal(10, newb.b1.a1) assert_equal(20, newb.b1.a2) assert_equal("wombat", newb.b2) assert_bag_equal([newb, newb.b1, newb.b2], res) end # there was a bug Marshaling Bignums, so def test_s_dump_load4 b1 = 123456789012345678901234567890 b2 = -123**99 b3 = 2**32 assert_equal(b1, Marshal.load(Marshal.dump(b1))) assert_equal(b2, Marshal.load(Marshal.dump(b2))) assert_equal(b3, Marshal.load(Marshal.dump(b3))) end def test_s_dump_load5 x = [1, 2, 3, [4, 5, "foo"], {1=>"bar"}, 2.5, 9**30] y = Marshal.dump(x) assert_equal(x, Marshal.load(y)) end def test_s_restore b = B.new(10, "wombat") assert_equal(10, b.b1.a1) assert_equal(20, b.b1.a2) assert_equal("wombat", b.b2) s = Marshal.dump(b) assert_instance_of(String, s) newb = Marshal.restore(s) assert_equal(10, newb.b1.a1) assert_equal(20, newb.b1.a2) assert_equal("wombat", newb.b2) assert(newb.__id__ != b.__id__) end end