aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-08-17 06:35:21 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-08-17 06:35:21 +0000
commit4e8d6c105c22c40f1abf1aab357419e8f4ef2f5b (patch)
tree8663c427f448abbc89539c56d9f9e185e0e44d70
parentb30d203fed8c29fd05d010631ca8e4750ce34849 (diff)
downloadruby-4e8d6c105c22c40f1abf1aab357419e8f4ef2f5b.tar.gz
Merge branch '5172_bigdecimal_gc_issue' into trunk
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog18
-rw-r--r--ext/bigdecimal/bigdecimal.c28
-rw-r--r--test/bigdecimal/test_bigdecimal.rb45
-rw-r--r--test/bigdecimal/testbase.rb7
4 files changed, 91 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 073126fdfe..9471274c1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Wed Aug 17 15:27:00 2011 Kenta Murata <mrkn@mrkn.jp>
+
+ * ext/bigdecimal/bigdecimal.c (cannot_be_coerced_into_BigDecimal):
+ add a new function for raising error when an object cannot coerce
+ into BigDecimal. [Bug #5172]
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimalValueWithPrec): use
+ cannot_be_coerced_into_BigDecimal function.
+
+ * ext/bigdecimal/bigdecimal.c (BigMath_s_exp): ditto.
+
+ * ext/bigdecimal/bigdecimal.c (BigMath_s_log): ditto.
+
+ * test/bigdecimal/test_bigdecimal.rb: test for the avobe changes.
+
+ * test/bigdecimal/testbase.rb (under_gc_stress): add a new utility
+ method to run tests under the condition of GC.stress = true.
+
Wed Aug 17 10:16:00 2011 Kenta Murata <mrkn@mrkn.jp>
* rational.c (nurat_coerce): Rational#coerce should converts itself
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 67c093efbb..151a68cea6 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -174,6 +174,25 @@ ToValue(Real *p)
return p->obj;
}
+NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
+
+static void
+cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
+{
+ VALUE str;
+
+ if (rb_special_const_p(v)) {
+ str = rb_str_cat2(rb_str_dup(rb_inspect(v)),
+ " can't be coerced into BigDecimal");
+ }
+ else {
+ str = rb_str_cat2(rb_str_dup(rb_class_name(rb_obj_class(v))),
+ " can't be coerced into BigDecimal");
+ }
+
+ rb_exc_raise(rb_exc_new3(exc_class, str));
+}
+
static VALUE BigDecimal_div2(int, VALUE*, VALUE);
static Real*
@@ -240,8 +259,7 @@ again:
SomeOneMayDoIt:
if (must) {
- rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
- rb_special_const_p(v) ? RSTRING_PTR(rb_inspect(v)) : rb_obj_classname(v));
+ cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
}
return NULL; /* NULL means to coerce */
@@ -2463,8 +2481,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
return ToValue(vy);
}
else if (vx == NULL) {
- rb_raise(rb_eArgError, "%s can't be coerced into BigDecimal",
- rb_special_const_p(x) ? RSTRING_PTR(rb_inspect(x)) : rb_obj_classname(x));
+ cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
}
RB_GC_GUARD(vx->obj);
@@ -2619,8 +2636,7 @@ get_vp_value:
"Zero or negative argument for log");
}
else if (vx == NULL) {
- rb_raise(rb_eArgError, "%s can't be coerced into BigDecimal",
- rb_special_const_p(x) ? RSTRING_PTR(rb_inspect(x)) : rb_obj_classname(x));
+ cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
}
x = ToValue(vx);
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index e3ae631820..a9524bb2ae 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -1086,7 +1086,7 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-1E-1" + "0" * 10000).sign)
end
- def test_gc
+ def test_split_under_gc_stress
bug3258 = '[ruby-dev:41213]'
stress, GC.stress = GC.stress, true
10.upto(20) do |i|
@@ -1097,6 +1097,21 @@ class TestBigDecimal < Test::Unit::TestCase
GC.stress = stress
end
+ def test_coerce_under_gc_stress
+ expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
+ under_gc_stress do
+ b = BigDecimal.new("1")
+ 10.times do
+ begin
+ b.coerce(:too_long_to_embed_as_string)
+ rescue => e
+ assert_instance_of TypeError, e
+ assert_equal expect, e.message
+ end
+ end
+ end
+ end
+
def test_INFINITY
assert(BigDecimal::INFINITY.infinite?, "BigDecimal::INFINITY is not a infinity")
end
@@ -1157,6 +1172,20 @@ class TestBigDecimal < Test::Unit::TestCase
assert_in_epsilon(Math.exp(-40), BigMath.exp(BigDecimal("-40"), n))
end
+ def test_BigMath_exp_under_gc_stress
+ expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
+ under_gc_stress do
+ 10.times do
+ begin
+ BigMath.exp(:too_long_to_embed_as_string, 6)
+ rescue => e
+ assert_instance_of ArgumentError, e
+ assert_equal expect, e.message
+ end
+ end
+ end
+ end
+
def test_BigMath_log_with_nil
assert_raise(ArgumentError) do
BigMath.log(nil, 20)
@@ -1241,4 +1270,18 @@ class TestBigDecimal < Test::Unit::TestCase
assert_in_delta(Math.log(1e-42), BigMath.log(1e-42, 20))
assert_in_delta(Math.log(1e-42), BigMath.log(BigDecimal("1e-42"), 20))
end
+
+ def test_BigMath_log_under_gc_stress
+ expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
+ under_gc_stress do
+ 10.times do
+ begin
+ BigMath.log(:too_long_to_embed_as_string, 6)
+ rescue => e
+ assert_instance_of ArgumentError, e
+ assert_equal expect, e.message
+ end
+ end
+ end
+ end
end
diff --git a/test/bigdecimal/testbase.rb b/test/bigdecimal/testbase.rb
index 275b1b2b5d..c014e61e92 100644
--- a/test/bigdecimal/testbase.rb
+++ b/test/bigdecimal/testbase.rb
@@ -17,4 +17,11 @@ module TestBigDecimalBase
BigDecimal.mode(mode, !(@mode & mode).zero?)
end
end
+
+ def under_gc_stress
+ stress, GC.stress = GC.stress, true
+ yield
+ ensure
+ GC.stress = stress
+ end
end