diff options
Diffstat (limited to 'test/ruby/test_sprintf.rb')
| -rw-r--r-- | test/ruby/test_sprintf.rb | 252 |
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 |
