ruby-changes:14129
From: yugui <ko1@a...>
Date: Fri, 27 Nov 2009 11:54:45 +0900 (JST)
Subject: [ruby-changes:14129] Ruby:r25943 (ruby_1_9_1): merges r25010 from trunk into ruby_1_9_1 and adds tests for it.
yugui 2009-11-27 11:54:29 +0900 (Fri, 27 Nov 2009) New Revision: 25943 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=25943 Log: merges r25010 from trunk into ruby_1_9_1 and adds tests for it. -- * struct.c (rb_struct_equal, rb_struct_eql): Handle comparison of recursive structures [ruby-core:24759] * range.c (range_eq, range_eql): ditto for ranges -- test for r25010 * test/ruby/test_struct.rb (TestStruct#test_comparison_when_recursive): new test. * test/ruby/test_range.rb (TestRange#test_comparison_when_recursive): new test. Modified files: branches/ruby_1_9_1/ChangeLog branches/ruby_1_9_1/range.c branches/ruby_1_9_1/struct.c branches/ruby_1_9_1/test/ruby/test_range.rb branches/ruby_1_9_1/test/ruby/test_struct.rb branches/ruby_1_9_1/version.h Index: ruby_1_9_1/ChangeLog =================================================================== --- ruby_1_9_1/ChangeLog (revision 25942) +++ ruby_1_9_1/ChangeLog (revision 25943) @@ -1,3 +1,10 @@ +Sun Sep 20 11:11:34 2009 Marc-Andre Lafortune <ruby-core@m...> + + * struct.c (rb_struct_equal, rb_struct_eql): Handle comparison of + recursive structures [ruby-core:24759] + + * range.c (range_eq, range_eql): ditto for ranges + Fri Sep 18 23:51:17 2009 Nobuyoshi Nakada <nobu@r...> * marshal.c (r_object0): entry regexp object before its encoding Index: ruby_1_9_1/range.c =================================================================== --- ruby_1_9_1/range.c (revision 25942) +++ ruby_1_9_1/range.c (revision 25943) @@ -105,7 +105,21 @@ return EXCL(range) ? Qtrue : Qfalse; } +static VALUE +recursive_equal(VALUE range, VALUE obj, int recur) +{ + if (recur) return Qtrue; /* Subtle! */ + if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj))) + return Qfalse; + if (!rb_equal(RANGE_END(range), RANGE_END(obj))) + return Qfalse; + if (EXCL(range) != EXCL(obj)) + return Qfalse; + return Qtrue; +} + + /* * call-seq: * rng == obj => true or false @@ -128,15 +142,7 @@ if (!rb_obj_is_kind_of(obj, rb_cRange)) return Qfalse; - if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj))) - return Qfalse; - if (!rb_equal(RANGE_END(range), RANGE_END(obj))) - return Qfalse; - - if (EXCL(range) != EXCL(obj)) - return Qfalse; - - return Qtrue; + return rb_exec_recursive_paired(recursive_equal, range, obj, obj); } static int @@ -168,6 +174,20 @@ } +static VALUE +recursive_eql(VALUE range, VALUE obj, int recur) +{ + if (recur) return Qtrue; /* Subtle! */ + if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj))) + return Qfalse; + if (!rb_eql(RANGE_END(range), RANGE_END(obj))) + return Qfalse; + + if (EXCL(range) != EXCL(obj)) + return Qfalse; + return Qtrue; +} + /* * call-seq: * rng.eql?(obj) => true or false @@ -189,16 +209,7 @@ return Qtrue; if (!rb_obj_is_kind_of(obj, rb_cRange)) return Qfalse; - - if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj))) - return Qfalse; - if (!rb_eql(RANGE_END(range), RANGE_END(obj))) - return Qfalse; - - if (EXCL(range) != EXCL(obj)) - return Qfalse; - - return Qtrue; + return rb_exec_recursive_paired(recursive_eql, range, obj, obj); } /* Index: ruby_1_9_1/struct.c =================================================================== --- ruby_1_9_1/struct.c (revision 25942) +++ ruby_1_9_1/struct.c (revision 25943) @@ -760,6 +760,18 @@ return result; } +static VALUE +recursive_equal(VALUE s, VALUE s2, int recur) +{ + long i; + + if (recur) return Qtrue; /* Subtle! */ + for (i=0; i<RSTRUCT_LEN(s); i++) { + if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; + } + return Qtrue; +} + /* * call-seq: * struct == other_struct => true or false @@ -780,8 +792,6 @@ static VALUE rb_struct_equal(VALUE s, VALUE s2) { - long i; - if (s == s2) return Qtrue; if (TYPE(s2) != T_STRUCT) return Qfalse; if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse; @@ -789,10 +799,7 @@ rb_bug("inconsistent struct"); /* should never happen */ } - for (i=0; i<RSTRUCT_LEN(s); i++) { - if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; - } - return Qtrue; + return rb_exec_recursive_paired(recursive_equal, s, s2, s2); } /* @@ -817,6 +824,18 @@ return LONG2FIX(h); } +static VALUE +recursive_eql(VALUE s, VALUE s2, int recur) +{ + long i; + + if (recur) return Qtrue; /* Subtle! */ + for (i=0; i<RSTRUCT_LEN(s); i++) { + if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; + } + return Qtrue; +} + /* * code-seq: * struct.eql?(other) => true or false @@ -828,8 +847,6 @@ static VALUE rb_struct_eql(VALUE s, VALUE s2) { - long i; - if (s == s2) return Qtrue; if (TYPE(s2) != T_STRUCT) return Qfalse; if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse; @@ -837,10 +854,7 @@ rb_bug("inconsistent struct"); /* should never happen */ } - for (i=0; i<RSTRUCT_LEN(s); i++) { - if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; - } - return Qtrue; + return rb_exec_recursive_paired(recursive_eql, s, s2, s2); } /* Index: ruby_1_9_1/version.h =================================================================== --- ruby_1_9_1/version.h (revision 25942) +++ ruby_1_9_1/version.h (revision 25943) @@ -1,5 +1,5 @@ #define RUBY_VERSION "1.9.1" -#define RUBY_PATCHLEVEL 344 +#define RUBY_PATCHLEVEL 345 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 9 #define RUBY_VERSION_TEENY 1 Index: ruby_1_9_1/test/ruby/test_struct.rb =================================================================== --- ruby_1_9_1/test/ruby/test_struct.rb (revision 25942) +++ ruby_1_9_1/test/ruby/test_struct.rb (revision 25943) @@ -1,4 +1,5 @@ require 'test/unit' +require 'timeout' class TestStruct < Test::Unit::TestCase def test_struct @@ -219,4 +220,33 @@ a = struct_test.new(42) assert_equal("#<struct Struct::R\u{e9}sum\u{e9} r\u{e9}sum\u{e9}=42>", a.inspect, '[ruby-core:24849]') end + + def test_comparison_when_recursive + klass1 = Struct.new(:a, :b, :c) + + x = klass1.new(1, 2, nil); x.c = x + y = klass1.new(1, 2, nil); y.c = y + Timeout.timeout(1) { + assert x == y + assert x.eql? y + } + + z = klass1.new(:something, :other, nil); z.c = z + Timeout.timeout(1) { + assert x != z + assert !x.eql?(z) + } + + x.c = y; y.c = x + Timeout.timeout(1) { + assert x == y + assert x.eql?(y) + } + + x.c = z; z.c = x + Timeout.timeout(1) { + assert x != z + assert !x.eql?(z) + } + end end Index: ruby_1_9_1/test/ruby/test_range.rb =================================================================== --- ruby_1_9_1/test/ruby/test_range.rb (revision 25942) +++ ruby_1_9_1/test/ruby/test_range.rb (revision 25943) @@ -1,4 +1,5 @@ require 'test/unit' +require 'timeout' class TestRange < Test::Unit::TestCase def test_range_string @@ -280,4 +281,37 @@ o.instance_eval { initialize(o, 1) } assert_equal("(... .. ...)..1", o.inspect) end + + def test_comparison_when_recursive + x = CyclicRange.allocate; x.send(:initialize, x, 1) + y = CyclicRange.allocate; y.send(:initialize, y, 1) + Timeout.timeout(1) { + assert x == y + assert x.eql? y + } + + z = CyclicRange.allocate; z.send(:initialize, z, :another) + Timeout.timeout(1) { + assert x != z + assert !x.eql?(z) + } + + x = CyclicRange.allocate + y = CyclicRange.allocate + x.send(:initialize, y, 1) + y.send(:initialize, x, 1) + Timeout.timeout(1) { + assert x == y + assert x.eql?(y) + } + + x = CyclicRange.allocate + z = CyclicRange.allocate + x.send(:initialize, z, 1) + z.send(:initialize, x, :other) + Timeout.timeout(1) { + assert x != z + assert !x.eql?(z) + } + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/