diff options
Diffstat (limited to 'trunk/test/ruby/test_marshal.rb')
-rw-r--r-- | trunk/test/ruby/test_marshal.rb | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/trunk/test/ruby/test_marshal.rb b/trunk/test/ruby/test_marshal.rb new file mode 100644 index 0000000000..af389d2b2d --- /dev/null +++ b/trunk/test/ruby/test_marshal.rb @@ -0,0 +1,194 @@ +require 'test/unit' +require_relative 'marshaltestlib' + +class TestMarshal < Test::Unit::TestCase + include MarshalTestLib + + def setup + @verbose = $VERBOSE + $VERBOSE = nil + end + + def teardown + $VERBOSE = @verbose + end + + def encode(o) + Marshal.dump(o) + end + + def decode(s) + Marshal.load(s) + end + + def fact(n) + return 1 if n == 0 + f = 1 + while n>0 + f *= n + n -= 1 + end + return f + end + + def test_marshal + x = [1, 2, 3, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)] + assert_equal x, Marshal.load(Marshal.dump(x)) + + [[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z| + obj = (x.to_f + y.to_f / z.to_f) * Math.exp(w.to_f / (x.to_f + y.to_f / z.to_f)) + assert_equal obj, Marshal.load(Marshal.dump(obj)) + } + end + + StrClone = String.clone + def test_marshal_cloned_class + assert_instance_of(StrClone, Marshal.load(Marshal.dump(StrClone.new("abc")))) + end + + def test_inconsistent_struct + TestMarshal.const_set :StructOrNot, Struct.new(:a) + s = Marshal.dump(StructOrNot.new(1)) + TestMarshal.instance_eval { remove_const :StructOrNot } + TestMarshal.const_set :StructOrNot, Class.new + assert_raise(TypeError, "[ruby-dev:31709]") { Marshal.load(s) } + end + + def test_struct_invalid_members + TestMarshal.const_set :StructInvalidMembers, Struct.new(:a) + Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo") + assert_raise(TypeError, "[ruby-dev:31759]") { + TestMarshal::StructInvalidMembers.members + } + end + + class C + def initialize(str) + @str = str + end + attr_reader :str + def _dump(limit) + @str + end + def self._load(s) + new(s) + end + end + + def test_too_long_string + data = Marshal.dump(C.new("a".force_encoding("ascii-8bit"))) + data[-2, 1] = "\003\377\377\377" + e = assert_raise(ArgumentError, "[ruby-dev:32054]") { + Marshal.load(data) + } + assert_equal("marshal data too short", e.message) + end + + + def test_userdef_encoding + s1 = "\xa4\xa4".force_encoding("euc-jp") + o1 = C.new(s1) + m = Marshal.dump(o1) + o2 = Marshal.load(m) + s2 = o2.str + assert_equal(s1, s2) + end + + def test_pipe + o1 = C.new("a" * 10000) + + r, w = IO.pipe + t = Thread.new { Marshal.load(r) } + Marshal.dump(o1, w) + o2 = t.value + assert_equal(o1.str, o2.str) + + r, w = IO.pipe + t = Thread.new { Marshal.load(r) } + Marshal.dump(o1, w, 2) + o2 = t.value + assert_equal(o1.str, o2.str) + + assert_raise(TypeError) { Marshal.dump("foo", Object.new) } + assert_raise(TypeError) { Marshal.load(Object.new) } + end + + def test_limit + assert_equal([[[]]], Marshal.load(Marshal.dump([[[]]], 3))) + assert_raise(ArgumentError) { Marshal.dump([[[]]], 2) } + end + + def test_userdef_invalid + o = C.new(nil) + assert_raise(TypeError) { Marshal.dump(o) } + end + + def test_class + o = class << Object.new; self; end + assert_raise(TypeError) { Marshal.dump(o) } + assert_equal(Object, Marshal.load(Marshal.dump(Object))) + assert_equal(Enumerable, Marshal.load(Marshal.dump(Enumerable))) + end + + class C2 + def initialize(ary) + @ary = ary + end + def _dump(s) + @ary.clear + "foo" + end + end + + def test_modify_array_during_dump + a = [] + o = C2.new(a) + a << o << nil + assert_raise(RuntimeError) { Marshal.dump(a) } + end + + def test_change_class_name + eval("class C3; def _dump(s); 'foo'; end; end") + m = Marshal.dump(C3.new) + assert_raise(TypeError) { Marshal.load(m) } + eval("C3 = nil") + assert_raise(TypeError) { Marshal.load(m) } + end + + def test_change_struct + eval("C3 = Struct.new(:foo, :bar)") + m = Marshal.dump(C3.new("FOO", "BAR")) + eval("C3 = Struct.new(:foo)") + assert_raise(TypeError) { Marshal.load(m) } + eval("C3 = Struct.new(:foo, :baz)") + assert_raise(TypeError) { Marshal.load(m) } + end + + class C4 + def initialize(gc) + @gc = gc + end + def _dump(s) + GC.start if @gc + "foo" + end + end + + def test_gc + assert_nothing_raised do + Marshal.dump((0..1000).map {|x| C4.new(x % 50 == 25) }) + end + end + + def test_taint_and_untrust + x = Object.new + x.taint + x.untrust + s = Marshal.dump(x) + assert_equal(true, s.tainted?) + assert_equal(true, s.untrusted?) + y = Marshal.load(s) + assert_equal(true, y.tainted?) + assert_equal(true, y.untrusted?) + end +end |