summaryrefslogtreecommitdiff
path: root/test/ruby/test_sprintf.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_sprintf.rb')
-rw-r--r--test/ruby/test_sprintf.rb252
1 files changed, 205 insertions, 47 deletions
diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb
index b7a29e9ebe..1c7e89c265 100644
--- a/test/ruby/test_sprintf.rb
+++ b/test/ruby/test_sprintf.rb
@@ -1,5 +1,5 @@
+# frozen_string_literal: false
require 'test/unit'
-require_relative 'envutil'
class TestSprintf < Test::Unit::TestCase
def test_positional
@@ -84,6 +84,18 @@ class TestSprintf < Test::Unit::TestCase
assert_equal("NaN", sprintf("%-f", nan))
assert_equal("+NaN", sprintf("%+f", nan))
+ assert_equal("NaN", sprintf("%3f", nan))
+ assert_equal("NaN", sprintf("%-3f", nan))
+ assert_equal("+NaN", sprintf("%+3f", nan))
+
+ assert_equal(" NaN", sprintf("% 3f", nan))
+ assert_equal(" NaN", sprintf("%- 3f", nan))
+ assert_equal("+NaN", sprintf("%+ 3f", nan))
+
+ assert_equal(" NaN", sprintf("% 03f", nan))
+ assert_equal(" NaN", sprintf("%- 03f", nan))
+ assert_equal("+NaN", sprintf("%+ 03f", nan))
+
assert_equal(" NaN", sprintf("%8f", nan))
assert_equal("NaN ", sprintf("%-8f", nan))
assert_equal(" +NaN", sprintf("%+8f", nan))
@@ -107,6 +119,26 @@ class TestSprintf < Test::Unit::TestCase
assert_equal("Inf", sprintf("%-f", inf))
assert_equal("+Inf", sprintf("%+f", inf))
+ assert_equal(" Inf", sprintf("% f", inf))
+ assert_equal(" Inf", sprintf("%- f", inf))
+ assert_equal("+Inf", sprintf("%+ f", inf))
+
+ assert_equal(" Inf", sprintf("% 0f", inf))
+ assert_equal(" Inf", sprintf("%- 0f", inf))
+ assert_equal("+Inf", sprintf("%+ 0f", inf))
+
+ assert_equal("Inf", sprintf("%3f", inf))
+ assert_equal("Inf", sprintf("%-3f", inf))
+ assert_equal("+Inf", sprintf("%+3f", inf))
+
+ assert_equal(" Inf", sprintf("% 3f", inf))
+ assert_equal(" Inf", sprintf("%- 3f", inf))
+ assert_equal("+Inf", sprintf("%+ 3f", inf))
+
+ assert_equal(" Inf", sprintf("% 03f", inf))
+ assert_equal(" Inf", sprintf("%- 03f", inf))
+ assert_equal("+Inf", sprintf("%+ 03f", inf))
+
assert_equal(" Inf", sprintf("%8f", inf))
assert_equal("Inf ", sprintf("%-8f", inf))
assert_equal(" +Inf", sprintf("%+8f", inf))
@@ -127,6 +159,26 @@ class TestSprintf < Test::Unit::TestCase
assert_equal("-Inf", sprintf("%-f", -inf))
assert_equal("-Inf", sprintf("%+f", -inf))
+ assert_equal("-Inf", sprintf("% f", -inf))
+ assert_equal("-Inf", sprintf("%- f", -inf))
+ assert_equal("-Inf", sprintf("%+ f", -inf))
+
+ assert_equal("-Inf", sprintf("% 0f", -inf))
+ assert_equal("-Inf", sprintf("%- 0f", -inf))
+ assert_equal("-Inf", sprintf("%+ 0f", -inf))
+
+ assert_equal("-Inf", sprintf("%4f", -inf))
+ assert_equal("-Inf", sprintf("%-4f", -inf))
+ assert_equal("-Inf", sprintf("%+4f", -inf))
+
+ assert_equal("-Inf", sprintf("% 4f", -inf))
+ assert_equal("-Inf", sprintf("%- 4f", -inf))
+ assert_equal("-Inf", sprintf("%+ 4f", -inf))
+
+ assert_equal("-Inf", sprintf("% 04f", -inf))
+ assert_equal("-Inf", sprintf("%- 04f", -inf))
+ assert_equal("-Inf", sprintf("%+ 04f", -inf))
+
assert_equal(" -Inf", sprintf("%8f", -inf))
assert_equal("-Inf ", sprintf("%-8f", -inf))
assert_equal(" -Inf", sprintf("%+8f", -inf))
@@ -149,6 +201,53 @@ class TestSprintf < Test::Unit::TestCase
assert_equal(" Inf", sprintf("% e", inf), '[ruby-dev:34002]')
end
+ def test_bignum
+ assert_match(/\A10{120}\.0+\z/, sprintf("%f", 100**60))
+ assert_match(/\A10{180}\.0+\z/, sprintf("%f", 1000**60))
+ end
+
+ def test_rational
+ assert_match(/\A0\.10+\z/, sprintf("%.60f", 0.1r))
+ assert_match(/\A0\.010+\z/, sprintf("%.60f", 0.01r))
+ assert_match(/\A0\.0010+\z/, sprintf("%.60f", 0.001r))
+ assert_match(/\A0\.3+\z/, sprintf("%.60f", 1/3r))
+ assert_match(/\A1\.20+\z/, sprintf("%.60f", 1.2r))
+
+ ["", *"0".."9"].each do |len|
+ ["", *".0"..".9"].each do |prec|
+ ['', '+', '-', ' ', '0', '+0', '-0', ' 0', '+ ', '- ', '+ 0', '- 0'].each do |flags|
+ fmt = "%#{flags}#{len}#{prec}f"
+ [0, 0.1, 0.01, 0.001, 1.001, 100.0, 100.001, 10000000000.0, 0.00000000001, 1/3r, 2/3r, 1.2r, 10r].each do |num|
+ assert_equal(sprintf(fmt, num.to_f), sprintf(fmt, num.to_r), "sprintf(#{fmt.inspect}, #{num.inspect}.to_r)")
+ assert_equal(sprintf(fmt, -num.to_f), sprintf(fmt, -num.to_r), "sprintf(#{fmt.inspect}, #{(-num).inspect}.to_r)") if num > 0
+ end
+ end
+ end
+ end
+
+ bug11766 = '[ruby-core:71806] [Bug #11766]'
+ assert_equal("x"*10+" 1.0", sprintf("x"*10+"%8.1f", 1r), bug11766)
+
+ require 'rbconfig/sizeof'
+ fmin, fmax = RbConfig::LIMITS.values_at("FIXNUM_MIN", "FIXNUM_MAX")
+ assert_match(/\A-\d+\.\d+\z/, sprintf("%f", Rational(fmin, fmax)))
+ end
+
+ def test_rational_precision
+ assert_match(/\A0\.\d{600}\z/, sprintf("%.600f", 600**~60))
+ end
+
+ def test_hash
+ options = {:capture=>/\d+/}
+ assert_equal("with options #{options.inspect}", sprintf("with options %p" % options))
+ end
+
+ def test_inspect
+ obj = Object.new
+ def obj.inspect; "TEST"; end
+ assert_equal("<TEST>", sprintf("<%p>", obj))
+ end
+
def test_invalid
# Star precision before star width:
assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.**d", 5, 10, 1)}
@@ -171,8 +270,8 @@ class TestSprintf < Test::Unit::TestCase
# Specifying the precision multiple times with negative star arguments:
assert_raise(ArgumentError, "[ruby-core:11570]") {sprintf("%.*.*.*.*f", -1, -1, -1, 5, 1)}
- # Null bytes after percent signs are removed:
- assert_equal("%\0x hello", sprintf("%\0x hello"), "[ruby-core:11571]")
+ assert_raise(ArgumentError) {sprintf("%\0x hello")}
+ assert_raise(ArgumentError) {sprintf("%\nx hello")}
assert_raise(ArgumentError, "[ruby-core:11573]") {sprintf("%.25555555555555555555555555555555555555s", "hello")}
@@ -184,10 +283,9 @@ class TestSprintf < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$*d", 3) }
assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$.*d", 3) }
- verbose, $VERBOSE = $VERBOSE, nil
- assert_nothing_raised { sprintf("", 1) }
- ensure
- $VERBOSE = verbose
+ assert_warning(/too many arguments/) do
+ sprintf("", 1)
+ end
end
def test_float
@@ -195,8 +293,9 @@ class TestSprintf < Test::Unit::TestCase
sprintf("%20.0f", 36893488147419107329.0))
assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
assert_equal(" -0.", sprintf("%#10.0f", -0.5), "[ruby-dev:42552]")
- assert_equal("0x1p+2", sprintf('%.0a', Float('0x1.fp+1')), "[ruby-dev:42551]")
- assert_equal("-0x1.0p+2", sprintf('%.1a', Float('-0x1.ffp+1')), "[ruby-dev:42551]")
+ # out of spec
+ #assert_equal("0x1p+2", sprintf('%.0a', Float('0x1.fp+1')), "[ruby-dev:42551]")
+ #assert_equal("-0x1.0p+2", sprintf('%.1a', Float('-0x1.ffp+1')), "[ruby-dev:42551]")
end
def test_float_hex
@@ -244,6 +343,19 @@ class TestSprintf < Test::Unit::TestCase
assert_equal(" 0x1.000p+0", sprintf("%20.3a", 1), bug3979)
end
+ def test_float_prec
+ assert_equal("5.00", sprintf("%.2f",5.005))
+ assert_equal("5.02", sprintf("%.2f",5.015))
+ assert_equal("5.02", sprintf("%.2f",5.025))
+ assert_equal("5.04", sprintf("%.2f",5.035))
+ bug12889 = '[ruby-core:77864] [Bug #12889]'
+ assert_equal("1234567892", sprintf("%.0f", 1234567891.99999))
+ assert_equal("1234567892", sprintf("%.0f", 1234567892.49999))
+ assert_equal("1234567892", sprintf("%.0f", 1234567892.50000))
+ assert_equal("1234567894", sprintf("%.0f", 1234567893.50000))
+ assert_equal("1234567892", sprintf("%.0f", 1234567892.00000), bug12889)
+ end
+
BSIZ = 120
def test_skip
@@ -253,11 +365,16 @@ class TestSprintf < Test::Unit::TestCase
def test_char
assert_equal("a", sprintf("%c", 97))
assert_equal("a", sprintf("%c", ?a))
- assert_raise(ArgumentError) { sprintf("%c", sprintf("%c%c", ?a, ?a)) }
+ assert_equal("a", sprintf("%c", "a"))
+ assert_equal("a", sprintf("%c", sprintf("%c%c", ?a, ?a)))
assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%c", ?a))
assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%-1c", ?a))
assert_equal(" " * BSIZ + "a", sprintf("%#{ BSIZ + 1 }c", ?a))
assert_equal("a" + " " * BSIZ, sprintf("%-#{ BSIZ + 1 }c", ?a))
+ assert_raise(ArgumentError) { sprintf("%c", -1) }
+ s = sprintf("%c".encode(Encoding::US_ASCII), 0x80)
+ assert_equal("\x80".b, s)
+ assert_predicate(s, :valid_encoding?)
end
def test_string
@@ -309,12 +426,28 @@ class TestSprintf < Test::Unit::TestCase
def test_star
assert_equal("-1 ", sprintf("%*d", -3, -1))
+ assert_raise_with_message(ArgumentError, /width too big/) {
+ sprintf("%*999999999999999999999999999999999999999999999999999999999999$d", 1)
+ }
+ assert_raise_with_message(ArgumentError, /prec too big/) {
+ sprintf("%.*999999999999999999999999999999999999999999999999999999999999$d", 1)
+ }
end
def test_escape
assert_equal("%" * BSIZ, sprintf("%%" * BSIZ))
end
+ def test_percent_sign_at_end
+ assert_raise_with_message(ArgumentError, "incomplete format specifier; use %% (double %) instead") do
+ sprintf("%")
+ end
+
+ assert_raise_with_message(ArgumentError, "incomplete format specifier; use %% (double %) instead") do
+ sprintf("abc%")
+ end
+ end
+
def test_rb_sprintf
assert_match(/^#<TestSprintf::T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:0x[0-9a-f]+>$/,
T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.new.inspect)
@@ -325,75 +458,100 @@ class TestSprintf < Test::Unit::TestCase
s2 = sprintf("%0x", -0x40000001)
b1 = (/\.\./ =~ s1) != nil
b2 = (/\.\./ =~ s2) != nil
- assert(b1 == b2, "[ruby-dev:33224]")
+ assert_equal(b1, b2, "[ruby-dev:33224]")
end
def test_named_untyped
assert_equal("value", sprintf("%<key>s", :key => "value"))
- e = assert_raise(ArgumentError) {sprintf("%1$<key2>s", :key => "value")}
- assert_equal("named<key2> after numbered", e.message)
- e = assert_raise(ArgumentError) {sprintf("%s%s%<key2>s", "foo", "bar", :key => "value")}
- assert_equal("named<key2> after unnumbered(2)", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<key><key2>s", :key => "value")}
- assert_equal("named<key2> after <key>", e.message)
- e = assert_raise(KeyError) {sprintf("%<key>s", {})}
- assert_equal("key<key> not found", e.message)
+ assert_raise_with_message(ArgumentError, "named<key2> after numbered") {sprintf("%1$<key2>s", :key => "value")}
+ assert_raise_with_message(ArgumentError, "named<key2> after unnumbered(2)") {sprintf("%s%s%<key2>s", "foo", "bar", :key => "value")}
+ assert_raise_with_message(ArgumentError, "named<key2> after <key>") {sprintf("%<key><key2>s", :key => "value")}
+ h = {}
+ e = assert_raise_with_message(KeyError, "key<key> not found") {sprintf("%<key>s", h)}
+ assert_same(h, e.receiver)
+ assert_equal(:key, e.key)
end
def test_named_untyped_enc
key = "\u{3012}"
[Encoding::UTF_8, Encoding::EUC_JP].each do |enc|
k = key.encode(enc)
- e = assert_raise(ArgumentError) {sprintf("%1$<#{k}>s", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named<#{k}> after numbered") {sprintf("%1$<#{k}>s", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named<#{k}> after numbered", e.message)
- e = assert_raise(ArgumentError) {sprintf("%s%s%<#{k}>s", "foo", "bar", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named<#{k}> after unnumbered(2)") {sprintf("%s%s%<#{k}>s", "foo", "bar", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named<#{k}> after unnumbered(2)", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<key><#{k}>s", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named<#{k}> after <key>") {sprintf("%<key><#{k}>s", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named<#{k}> after <key>", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<#{k}><key>s", k.to_sym => "value")}
+ e = assert_raise_with_message(ArgumentError, "named<key> after <#{k}>") {sprintf("%<#{k}><key>s", k.to_sym => "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named<key> after <#{k}>", e.message)
- e = assert_raise(KeyError) {sprintf("%<#{k}>s", {})}
+ e = assert_raise_with_message(KeyError, "key<#{k}> not found") {sprintf("%<#{k}>s", {})}
assert_equal(enc, e.message.encoding)
- assert_equal("key<#{k}> not found", e.message)
end
end
def test_named_typed
assert_equal("value", sprintf("%{key}", :key => "value"))
- e = assert_raise(ArgumentError) {sprintf("%1${key2}", :key => "value")}
- assert_equal("named{key2} after numbered", e.message)
- e = assert_raise(ArgumentError) {sprintf("%s%s%{key2}", "foo", "bar", :key => "value")}
- assert_equal("named{key2} after unnumbered(2)", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<key>{key2}", :key => "value")}
- assert_equal("named{key2} after <key>", e.message)
+ assert_raise_with_message(ArgumentError, "named{key2} after numbered") {sprintf("%1${key2}", :key => "value")}
+ assert_raise_with_message(ArgumentError, "named{key2} after unnumbered(2)") {sprintf("%s%s%{key2}", "foo", "bar", :key => "value")}
+ assert_raise_with_message(ArgumentError, "named{key2} after <key>") {sprintf("%<key>{key2}", :key => "value")}
assert_equal("value{key2}", sprintf("%{key}{key2}", :key => "value"))
- e = assert_raise(KeyError) {sprintf("%{key}", {})}
- assert_equal("key{key} not found", e.message)
+ assert_raise_with_message(KeyError, "key{key} not found") {sprintf("%{key}", {})}
end
def test_named_typed_enc
key = "\u{3012}"
[Encoding::UTF_8, Encoding::EUC_JP].each do |enc|
k = key.encode(enc)
- e = assert_raise(ArgumentError) {sprintf("%1${#{k}}s", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named{#{k}} after numbered") {sprintf("%1${#{k}}s", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named{#{k}} after numbered", e.message)
- e = assert_raise(ArgumentError) {sprintf("%s%s%{#{k}}s", "foo", "bar", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named{#{k}} after unnumbered(2)") {sprintf("%s%s%{#{k}}s", "foo", "bar", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named{#{k}} after unnumbered(2)", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<key>{#{k}}s", key: "value")}
+ e = assert_raise_with_message(ArgumentError, "named{#{k}} after <key>") {sprintf("%<key>{#{k}}s", key: "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named{#{k}} after <key>", e.message)
- e = assert_raise(ArgumentError) {sprintf("%<#{k}>{key}s", k.to_sym => "value")}
+ e = assert_raise_with_message(ArgumentError, "named{key} after <#{k}>") {sprintf("%<#{k}>{key}s", k.to_sym => "value")}
assert_equal(enc, e.message.encoding)
- assert_equal("named{key} after <#{k}>", e.message)
- e = assert_raise(KeyError) {sprintf("%{#{k}}", {})}
+ e = assert_raise_with_message(KeyError, "key{#{k}} not found") {sprintf("%{#{k}}", {})}
assert_equal(enc, e.message.encoding)
- assert_equal("key{#{k}} not found", e.message)
+ end
+ end
+
+ def test_coderange
+ format_str = "wrong constant name %s"
+ interpolated_str = "\u3042"
+ assert_predicate format_str, :ascii_only?
+ refute_predicate interpolated_str, :ascii_only?
+
+ str = format_str % interpolated_str
+ refute_predicate str, :ascii_only?
+ end
+
+ def test_named_default
+ h = Hash.new('world')
+ assert_equal("hello world", "hello %{location}" % h)
+ assert_equal("hello world", "hello %<location>s" % h)
+ end
+
+ def test_named_with_nil
+ h = { key: nil, key2: "key2_val" }
+ assert_equal("key is , key2 is key2_val", "key is %{key}, key2 is %{key2}" % h)
+ end
+
+ def test_width_underflow
+ bug = 'https://github.com/mruby/mruby/issues/3347'
+ assert_equal("!", sprintf("%*c", 0, ?!.ord), bug)
+ end
+
+ def test_negative_width_overflow
+ assert_raise_with_message(ArgumentError, /too big/) do
+ sprintf("%*s", RbConfig::LIMITS["INT_MIN"], "")
+ end
+ end
+
+ def test_binary_format_coderange
+ 1.upto(500) do |i|
+ str = sprintf("%*s".b, i, "\xe2".b)
+ refute_predicate str, :ascii_only?
+ assert_equal i, str.bytesize
end
end
end