PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/test/ruby/test_sprintf.rb

http://github.com/ruby/ruby
Ruby | 546 lines | 443 code | 92 blank | 11 comment | 3 complexity | edf6fc63c7a4d04fb01459c970539478 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. class TestSprintf < Test::Unit::TestCase
  4. def test_positional
  5. assert_equal(" 00001", sprintf("%*1$.*2$3$d", 10, 5, 1))
  6. end
  7. def test_binary
  8. assert_equal("0", sprintf("%b", 0))
  9. assert_equal("1", sprintf("%b", 1))
  10. assert_equal("10", sprintf("%b", 2))
  11. assert_equal("..1", sprintf("%b", -1))
  12. assert_equal(" 0", sprintf("%4b", 0))
  13. assert_equal(" 1", sprintf("%4b", 1))
  14. assert_equal(" 10", sprintf("%4b", 2))
  15. assert_equal(" ..1", sprintf("%4b", -1))
  16. assert_equal("0000", sprintf("%04b", 0))
  17. assert_equal("0001", sprintf("%04b", 1))
  18. assert_equal("0010", sprintf("%04b", 2))
  19. assert_equal("..11", sprintf("%04b", -1))
  20. assert_equal("0000", sprintf("%.4b", 0))
  21. assert_equal("0001", sprintf("%.4b", 1))
  22. assert_equal("0010", sprintf("%.4b", 2))
  23. assert_equal("..11", sprintf("%.4b", -1))
  24. assert_equal(" 0000", sprintf("%6.4b", 0))
  25. assert_equal(" 0001", sprintf("%6.4b", 1))
  26. assert_equal(" 0010", sprintf("%6.4b", 2))
  27. assert_equal(" ..11", sprintf("%6.4b", -1))
  28. assert_equal(" 0", sprintf("%#4b", 0))
  29. assert_equal(" 0b1", sprintf("%#4b", 1))
  30. assert_equal("0b10", sprintf("%#4b", 2))
  31. assert_equal("0b..1", sprintf("%#4b", -1))
  32. assert_equal("0000", sprintf("%#04b", 0))
  33. assert_equal("0b01", sprintf("%#04b", 1))
  34. assert_equal("0b10", sprintf("%#04b", 2))
  35. assert_equal("0b..1", sprintf("%#04b", -1))
  36. assert_equal("0000", sprintf("%#.4b", 0))
  37. assert_equal("0b0001", sprintf("%#.4b", 1))
  38. assert_equal("0b0010", sprintf("%#.4b", 2))
  39. assert_equal("0b..11", sprintf("%#.4b", -1))
  40. assert_equal(" 0000", sprintf("%#6.4b", 0))
  41. assert_equal("0b0001", sprintf("%#6.4b", 1))
  42. assert_equal("0b0010", sprintf("%#6.4b", 2))
  43. assert_equal("0b..11", sprintf("%#6.4b", -1))
  44. assert_equal("+0", sprintf("%+b", 0))
  45. assert_equal("+1", sprintf("%+b", 1))
  46. assert_equal("+10", sprintf("%+b", 2))
  47. assert_equal("-1", sprintf("%+b", -1))
  48. assert_equal(" +0", sprintf("%+4b", 0))
  49. assert_equal(" +1", sprintf("%+4b", 1))
  50. assert_equal(" +10", sprintf("%+4b", 2))
  51. assert_equal(" -1", sprintf("%+4b", -1))
  52. assert_equal("+000", sprintf("%+04b", 0))
  53. assert_equal("+001", sprintf("%+04b", 1))
  54. assert_equal("+010", sprintf("%+04b", 2))
  55. assert_equal("-001", sprintf("%+04b", -1))
  56. assert_equal("+0000", sprintf("%+.4b", 0))
  57. assert_equal("+0001", sprintf("%+.4b", 1))
  58. assert_equal("+0010", sprintf("%+.4b", 2))
  59. assert_equal("-0001", sprintf("%+.4b", -1))
  60. assert_equal(" +0000", sprintf("%+6.4b", 0))
  61. assert_equal(" +0001", sprintf("%+6.4b", 1))
  62. assert_equal(" +0010", sprintf("%+6.4b", 2))
  63. assert_equal(" -0001", sprintf("%+6.4b", -1))
  64. end
  65. def test_nan
  66. nan = 0.0 / 0.0
  67. assert_equal("NaN", sprintf("%f", nan))
  68. assert_equal("NaN", sprintf("%-f", nan))
  69. assert_equal("+NaN", sprintf("%+f", nan))
  70. assert_equal("NaN", sprintf("%3f", nan))
  71. assert_equal("NaN", sprintf("%-3f", nan))
  72. assert_equal("+NaN", sprintf("%+3f", nan))
  73. assert_equal(" NaN", sprintf("% 3f", nan))
  74. assert_equal(" NaN", sprintf("%- 3f", nan))
  75. assert_equal("+NaN", sprintf("%+ 3f", nan))
  76. assert_equal(" NaN", sprintf("% 03f", nan))
  77. assert_equal(" NaN", sprintf("%- 03f", nan))
  78. assert_equal("+NaN", sprintf("%+ 03f", nan))
  79. assert_equal(" NaN", sprintf("%8f", nan))
  80. assert_equal("NaN ", sprintf("%-8f", nan))
  81. assert_equal(" +NaN", sprintf("%+8f", nan))
  82. assert_equal(" NaN", sprintf("%08f", nan))
  83. assert_equal("NaN ", sprintf("%-08f", nan))
  84. assert_equal(" +NaN", sprintf("%+08f", nan))
  85. assert_equal(" NaN", sprintf("% 8f", nan))
  86. assert_equal(" NaN ", sprintf("%- 8f", nan))
  87. assert_equal(" +NaN", sprintf("%+ 8f", nan))
  88. assert_equal(" NaN", sprintf("% 08f", nan))
  89. assert_equal(" NaN ", sprintf("%- 08f", nan))
  90. assert_equal(" +NaN", sprintf("%+ 08f", nan))
  91. end
  92. def test_inf
  93. inf = 1.0 / 0.0
  94. assert_equal("Inf", sprintf("%f", inf))
  95. assert_equal("Inf", sprintf("%-f", inf))
  96. assert_equal("+Inf", sprintf("%+f", inf))
  97. assert_equal(" Inf", sprintf("% f", inf))
  98. assert_equal(" Inf", sprintf("%- f", inf))
  99. assert_equal("+Inf", sprintf("%+ f", inf))
  100. assert_equal(" Inf", sprintf("% 0f", inf))
  101. assert_equal(" Inf", sprintf("%- 0f", inf))
  102. assert_equal("+Inf", sprintf("%+ 0f", inf))
  103. assert_equal("Inf", sprintf("%3f", inf))
  104. assert_equal("Inf", sprintf("%-3f", inf))
  105. assert_equal("+Inf", sprintf("%+3f", inf))
  106. assert_equal(" Inf", sprintf("% 3f", inf))
  107. assert_equal(" Inf", sprintf("%- 3f", inf))
  108. assert_equal("+Inf", sprintf("%+ 3f", inf))
  109. assert_equal(" Inf", sprintf("% 03f", inf))
  110. assert_equal(" Inf", sprintf("%- 03f", inf))
  111. assert_equal("+Inf", sprintf("%+ 03f", inf))
  112. assert_equal(" Inf", sprintf("%8f", inf))
  113. assert_equal("Inf ", sprintf("%-8f", inf))
  114. assert_equal(" +Inf", sprintf("%+8f", inf))
  115. assert_equal(" Inf", sprintf("%08f", inf))
  116. assert_equal("Inf ", sprintf("%-08f", inf))
  117. assert_equal(" +Inf", sprintf("%+08f", inf))
  118. assert_equal(" Inf", sprintf("% 8f", inf))
  119. assert_equal(" Inf ", sprintf("%- 8f", inf))
  120. assert_equal(" +Inf", sprintf("%+ 8f", inf))
  121. assert_equal(" Inf", sprintf("% 08f", inf))
  122. assert_equal(" Inf ", sprintf("%- 08f", inf))
  123. assert_equal(" +Inf", sprintf("%+ 08f", inf))
  124. assert_equal("-Inf", sprintf("%f", -inf))
  125. assert_equal("-Inf", sprintf("%-f", -inf))
  126. assert_equal("-Inf", sprintf("%+f", -inf))
  127. assert_equal("-Inf", sprintf("% f", -inf))
  128. assert_equal("-Inf", sprintf("%- f", -inf))
  129. assert_equal("-Inf", sprintf("%+ f", -inf))
  130. assert_equal("-Inf", sprintf("% 0f", -inf))
  131. assert_equal("-Inf", sprintf("%- 0f", -inf))
  132. assert_equal("-Inf", sprintf("%+ 0f", -inf))
  133. assert_equal("-Inf", sprintf("%4f", -inf))
  134. assert_equal("-Inf", sprintf("%-4f", -inf))
  135. assert_equal("-Inf", sprintf("%+4f", -inf))
  136. assert_equal("-Inf", sprintf("% 4f", -inf))
  137. assert_equal("-Inf", sprintf("%- 4f", -inf))
  138. assert_equal("-Inf", sprintf("%+ 4f", -inf))
  139. assert_equal("-Inf", sprintf("% 04f", -inf))
  140. assert_equal("-Inf", sprintf("%- 04f", -inf))
  141. assert_equal("-Inf", sprintf("%+ 04f", -inf))
  142. assert_equal(" -Inf", sprintf("%8f", -inf))
  143. assert_equal("-Inf ", sprintf("%-8f", -inf))
  144. assert_equal(" -Inf", sprintf("%+8f", -inf))
  145. assert_equal(" -Inf", sprintf("%08f", -inf))
  146. assert_equal("-Inf ", sprintf("%-08f", -inf))
  147. assert_equal(" -Inf", sprintf("%+08f", -inf))
  148. assert_equal(" -Inf", sprintf("% 8f", -inf))
  149. assert_equal("-Inf ", sprintf("%- 8f", -inf))
  150. assert_equal(" -Inf", sprintf("%+ 8f", -inf))
  151. assert_equal(" -Inf", sprintf("% 08f", -inf))
  152. assert_equal("-Inf ", sprintf("%- 08f", -inf))
  153. assert_equal(" -Inf", sprintf("%+ 08f", -inf))
  154. assert_equal('..f00000000',
  155. sprintf("%x", -2**32), '[ruby-dev:32351]')
  156. assert_equal("..101111111111111111111111111111111",
  157. sprintf("%b", -2147483649), '[ruby-dev:32365]')
  158. assert_equal(" Inf", sprintf("% e", inf), '[ruby-dev:34002]')
  159. end
  160. def test_bignum
  161. assert_match(/\A10{120}\.0+\z/, sprintf("%f", 100**60))
  162. assert_match(/\A10{180}\.0+\z/, sprintf("%f", 1000**60))
  163. end
  164. def test_rational
  165. assert_match(/\A0\.10+\z/, sprintf("%.60f", 0.1r))
  166. assert_match(/\A0\.010+\z/, sprintf("%.60f", 0.01r))
  167. assert_match(/\A0\.0010+\z/, sprintf("%.60f", 0.001r))
  168. assert_match(/\A0\.3+\z/, sprintf("%.60f", 1/3r))
  169. assert_match(/\A1\.20+\z/, sprintf("%.60f", 1.2r))
  170. ["", *"0".."9"].each do |len|
  171. ["", *".0"..".9"].each do |prec|
  172. ['', '+', '-', ' ', '0', '+0', '-0', ' 0', '+ ', '- ', '+ 0', '- 0'].each do |flags|
  173. fmt = "%#{flags}#{len}#{prec}f"
  174. [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|
  175. assert_equal(sprintf(fmt, num.to_f), sprintf(fmt, num.to_r), "sprintf(#{fmt.inspect}, #{num.inspect}.to_r)")
  176. assert_equal(sprintf(fmt, -num.to_f), sprintf(fmt, -num.to_r), "sprintf(#{fmt.inspect}, #{(-num).inspect}.to_r)") if num > 0
  177. end
  178. end
  179. end
  180. end
  181. bug11766 = '[ruby-core:71806] [Bug #11766]'
  182. assert_equal("x"*10+" 1.0", sprintf("x"*10+"%8.1f", 1r), bug11766)
  183. end
  184. def test_rational_precision
  185. assert_match(/\A0\.\d{600}\z/, sprintf("%.600f", 600**~60))
  186. end
  187. def test_hash
  188. options = {:capture=>/\d+/}
  189. assert_equal("with options {:capture=>/\\d+/}", sprintf("with options %p" % options))
  190. end
  191. def test_inspect
  192. obj = Object.new
  193. def obj.inspect; "TEST"; end
  194. assert_equal("<TEST>", sprintf("<%p>", obj))
  195. end
  196. def test_invalid
  197. # Star precision before star width:
  198. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.**d", 5, 10, 1)}
  199. # Precision before flags and width:
  200. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.5+05d", 5)}
  201. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.5 5d", 5)}
  202. # Overriding a star width with a numeric one:
  203. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%*1s", 5, 1)}
  204. # Width before flags:
  205. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%5+0d", 1)}
  206. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%5 0d", 1)}
  207. # Specifying width multiple times:
  208. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%50+30+20+10+5d", 5)}
  209. assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%50 30 20 10 5d", 5)}
  210. # Specifying the precision multiple times with negative star arguments:
  211. assert_raise(ArgumentError, "[ruby-core:11570]") {sprintf("%.*.*.*.*f", -1, -1, -1, 5, 1)}
  212. # Null bytes after percent signs are removed:
  213. assert_equal("%\0x hello", sprintf("%\0x hello"), "[ruby-core:11571]")
  214. assert_raise(ArgumentError, "[ruby-core:11573]") {sprintf("%.25555555555555555555555555555555555555s", "hello")}
  215. assert_raise(ArgumentError) { sprintf("%\1", 1) }
  216. assert_raise(ArgumentError) { sprintf("%!", 1) }
  217. assert_raise(ArgumentError) { sprintf("%1$1$d", 1) }
  218. assert_raise(ArgumentError) { sprintf("%0%") }
  219. assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$*d", 3) }
  220. assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$.*d", 3) }
  221. verbose, $VERBOSE = $VERBOSE, nil
  222. assert_nothing_raised { sprintf("", 1) }
  223. ensure
  224. $VERBOSE = verbose
  225. end
  226. def test_float
  227. assert_equal("36893488147419111424",
  228. sprintf("%20.0f", 36893488147419107329.0))
  229. assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
  230. assert_equal(" -0.", sprintf("%#10.0f", -0.5), "[ruby-dev:42552]")
  231. # out of spec
  232. #assert_equal("0x1p+2", sprintf('%.0a', Float('0x1.fp+1')), "[ruby-dev:42551]")
  233. #assert_equal("-0x1.0p+2", sprintf('%.1a', Float('-0x1.ffp+1')), "[ruby-dev:42551]")
  234. end
  235. def test_float_hex
  236. assert_equal("-0x0p+0", sprintf("%a", -0.0))
  237. assert_equal("0x0p+0", sprintf("%a", 0.0))
  238. assert_equal("0x1p-1", sprintf("%a", 0.5))
  239. assert_equal("0x1p+0", sprintf("%a", 1.0))
  240. assert_equal("0x1p+1", sprintf("%a", 2.0))
  241. assert_equal("0x1p+10", sprintf("%a", 1024))
  242. assert_equal("0x1.23456p+789", sprintf("%a", 3.704450999893983e+237))
  243. assert_equal("0x1p-1074", sprintf("%a", 4.9e-324))
  244. assert_equal("Inf", sprintf("%e", Float::INFINITY))
  245. assert_equal("Inf", sprintf("%E", Float::INFINITY))
  246. assert_equal("NaN", sprintf("%e", Float::NAN))
  247. assert_equal("NaN", sprintf("%E", Float::NAN))
  248. assert_equal(" -0x1p+0", sprintf("%10a", -1))
  249. assert_equal(" -0x1.8p+0", sprintf("%10a", -1.5))
  250. assert_equal(" -0x1.4p+0", sprintf("%10a", -1.25))
  251. assert_equal(" -0x1.2p+0", sprintf("%10a", -1.125))
  252. assert_equal(" -0x1.1p+0", sprintf("%10a", -1.0625))
  253. assert_equal("-0x1.08p+0", sprintf("%10a", -1.03125))
  254. bug3962 = '[ruby-core:32841]'
  255. assert_equal("-0x0001p+0", sprintf("%010a", -1), bug3962)
  256. assert_equal("-0x01.8p+0", sprintf("%010a", -1.5), bug3962)
  257. assert_equal("-0x01.4p+0", sprintf("%010a", -1.25), bug3962)
  258. assert_equal("-0x01.2p+0", sprintf("%010a", -1.125), bug3962)
  259. assert_equal("-0x01.1p+0", sprintf("%010a", -1.0625), bug3962)
  260. assert_equal("-0x1.08p+0", sprintf("%010a", -1.03125), bug3962)
  261. bug3964 = '[ruby-core:32848]'
  262. assert_equal("0x000000000000000p+0", sprintf("%020a", 0), bug3964)
  263. assert_equal("0x000000000000001p+0", sprintf("%020a", 1), bug3964)
  264. assert_equal("-0x00000000000001p+0", sprintf("%020a", -1), bug3964)
  265. assert_equal("0x00000000000000.p+0", sprintf("%#020a", 0), bug3964)
  266. bug3965 = '[ruby-dev:42431]'
  267. assert_equal("0x1.p+0", sprintf("%#.0a", 1), bug3965)
  268. assert_equal("0x00000000000000.p+0", sprintf("%#020a", 0), bug3965)
  269. assert_equal("0x0000.0000000000p+0", sprintf("%#020.10a", 0), bug3965)
  270. bug3979 = '[ruby-dev:42453]'
  271. assert_equal(" 0x0.000p+0", sprintf("%20.3a", 0), bug3979)
  272. assert_equal(" 0x1.000p+0", sprintf("%20.3a", 1), bug3979)
  273. end
  274. def test_float_prec
  275. assert_equal("5.00", sprintf("%.2f",5.005))
  276. assert_equal("5.02", sprintf("%.2f",5.015))
  277. assert_equal("5.02", sprintf("%.2f",5.025))
  278. assert_equal("5.04", sprintf("%.2f",5.035))
  279. bug12889 = '[ruby-core:77864] [Bug #12889]'
  280. assert_equal("1234567892", sprintf("%.0f", 1234567891.99999))
  281. assert_equal("1234567892", sprintf("%.0f", 1234567892.49999))
  282. assert_equal("1234567892", sprintf("%.0f", 1234567892.50000))
  283. assert_equal("1234567894", sprintf("%.0f", 1234567893.50000))
  284. assert_equal("1234567892", sprintf("%.0f", 1234567892.00000), bug12889)
  285. end
  286. BSIZ = 120
  287. def test_skip
  288. assert_equal(" " * BSIZ + "1", sprintf(" " * BSIZ + "%d", 1))
  289. end
  290. def test_char
  291. assert_equal("a", sprintf("%c", 97))
  292. assert_equal("a", sprintf("%c", ?a))
  293. assert_raise(ArgumentError) { sprintf("%c", sprintf("%c%c", ?a, ?a)) }
  294. assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%c", ?a))
  295. assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%-1c", ?a))
  296. assert_equal(" " * BSIZ + "a", sprintf("%#{ BSIZ + 1 }c", ?a))
  297. assert_equal("a" + " " * BSIZ, sprintf("%-#{ BSIZ + 1 }c", ?a))
  298. end
  299. def test_string
  300. assert_equal("foo", sprintf("%s", "foo"))
  301. assert_equal("fo", sprintf("%.2s", "foo"))
  302. assert_equal(" " * BSIZ, sprintf("%s", " " * BSIZ))
  303. assert_equal(" " * (BSIZ - 1) + "foo", sprintf("%#{ BSIZ - 1 + 3 }s", "foo"))
  304. assert_equal(" " * BSIZ + "foo", sprintf("%#{ BSIZ + 3 }s", "foo"))
  305. assert_equal("foo" + " " * BSIZ, sprintf("%-#{ BSIZ + 3 }s", "foo"))
  306. end
  307. def test_integer
  308. assert_equal("01", sprintf("%#o", 1))
  309. assert_equal("0x1", sprintf("%#x", 1))
  310. assert_equal("0X1", sprintf("%#X", 1))
  311. assert_equal("0b1", sprintf("%#b", 1))
  312. assert_equal("0B1", sprintf("%#B", 1))
  313. assert_equal("1", sprintf("%d", 1.0))
  314. assert_equal("4294967296", sprintf("%d", (2**32).to_f))
  315. assert_equal("-2147483648", sprintf("%d", -(2**31).to_f))
  316. assert_equal("18446744073709551616", sprintf("%d", (2**64).to_f))
  317. assert_equal("-9223372036854775808", sprintf("%d", -(2**63).to_f))
  318. assert_equal("1", sprintf("%d", "1"))
  319. o = Object.new; def o.to_int; 1; end
  320. assert_equal("1", sprintf("%d", o))
  321. assert_equal("+1", sprintf("%+d", 1))
  322. assert_equal(" 1", sprintf("% d", 1))
  323. assert_equal("..f", sprintf("%x", -1))
  324. assert_equal("..7", sprintf("%o", -1))
  325. one = (2**32).coerce(1).first
  326. mone = (2**32).coerce(-1).first
  327. assert_equal("+1", sprintf("%+d", one))
  328. assert_equal(" 1", sprintf("% d", one))
  329. assert_equal("..f", sprintf("%x", mone))
  330. assert_equal("..7", sprintf("%o", mone))
  331. assert_equal(" " * BSIZ + "1", sprintf("%#{ BSIZ + 1 }d", one))
  332. assert_equal(" " * (BSIZ - 1) + "1", sprintf(" " * (BSIZ - 1) + "%d", 1))
  333. end
  334. def test_float2
  335. inf = 1.0 / 0.0
  336. assert_equal(" " * BSIZ + "Inf", sprintf("%#{ BSIZ + 3 }.1f", inf))
  337. assert_equal("+Inf", sprintf("%+-f", inf))
  338. assert_equal(" " * BSIZ + "1.0", sprintf("%#{ BSIZ + 3 }.1f", 1.0))
  339. end
  340. class T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
  341. end
  342. def test_star
  343. assert_equal("-1 ", sprintf("%*d", -3, -1))
  344. assert_raise_with_message(ArgumentError, /width too big/) {
  345. sprintf("%*999999999999999999999999999999999999999999999999999999999999$d", 1)
  346. }
  347. assert_raise_with_message(ArgumentError, /prec too big/) {
  348. sprintf("%.*999999999999999999999999999999999999999999999999999999999999$d", 1)
  349. }
  350. end
  351. def test_escape
  352. assert_equal("%" * BSIZ, sprintf("%%" * BSIZ))
  353. end
  354. def test_percent_sign_at_end
  355. assert_raise_with_message(ArgumentError, "incomplete format specifier; use %% (double %) instead") do
  356. sprintf("%")
  357. end
  358. assert_raise_with_message(ArgumentError, "incomplete format specifier; use %% (double %) instead") do
  359. sprintf("abc%")
  360. end
  361. end
  362. def test_rb_sprintf
  363. assert_match(/^#<TestSprintf::T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:0x[0-9a-f]+>$/,
  364. T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.new.inspect)
  365. end
  366. def test_negative_hex
  367. s1 = sprintf("%0x", -0x40000000)
  368. s2 = sprintf("%0x", -0x40000001)
  369. b1 = (/\.\./ =~ s1) != nil
  370. b2 = (/\.\./ =~ s2) != nil
  371. assert_equal(b1, b2, "[ruby-dev:33224]")
  372. end
  373. def test_named_untyped
  374. assert_equal("value", sprintf("%<key>s", :key => "value"))
  375. assert_raise_with_message(ArgumentError, "named<key2> after numbered") {sprintf("%1$<key2>s", :key => "value")}
  376. assert_raise_with_message(ArgumentError, "named<key2> after unnumbered(2)") {sprintf("%s%s%<key2>s", "foo", "bar", :key => "value")}
  377. assert_raise_with_message(ArgumentError, "named<key2> after <key>") {sprintf("%<key><key2>s", :key => "value")}
  378. h = {}
  379. e = assert_raise_with_message(KeyError, "key<key> not found") {sprintf("%<key>s", h)}
  380. assert_same(h, e.receiver)
  381. assert_equal(:key, e.key)
  382. end
  383. def test_named_untyped_enc
  384. key = "\u{3012}"
  385. [Encoding::UTF_8, Encoding::EUC_JP].each do |enc|
  386. k = key.encode(enc)
  387. e = assert_raise_with_message(ArgumentError, "named<#{k}> after numbered") {sprintf("%1$<#{k}>s", key: "value")}
  388. assert_equal(enc, e.message.encoding)
  389. e = assert_raise_with_message(ArgumentError, "named<#{k}> after unnumbered(2)") {sprintf("%s%s%<#{k}>s", "foo", "bar", key: "value")}
  390. assert_equal(enc, e.message.encoding)
  391. e = assert_raise_with_message(ArgumentError, "named<#{k}> after <key>") {sprintf("%<key><#{k}>s", key: "value")}
  392. assert_equal(enc, e.message.encoding)
  393. e = assert_raise_with_message(ArgumentError, "named<key> after <#{k}>") {sprintf("%<#{k}><key>s", k.to_sym => "value")}
  394. assert_equal(enc, e.message.encoding)
  395. e = assert_raise_with_message(KeyError, "key<#{k}> not found") {sprintf("%<#{k}>s", {})}
  396. assert_equal(enc, e.message.encoding)
  397. end
  398. end
  399. def test_named_typed
  400. assert_equal("value", sprintf("%{key}", :key => "value"))
  401. assert_raise_with_message(ArgumentError, "named{key2} after numbered") {sprintf("%1${key2}", :key => "value")}
  402. assert_raise_with_message(ArgumentError, "named{key2} after unnumbered(2)") {sprintf("%s%s%{key2}", "foo", "bar", :key => "value")}
  403. assert_raise_with_message(ArgumentError, "named{key2} after <key>") {sprintf("%<key>{key2}", :key => "value")}
  404. assert_equal("value{key2}", sprintf("%{key}{key2}", :key => "value"))
  405. assert_raise_with_message(KeyError, "key{key} not found") {sprintf("%{key}", {})}
  406. end
  407. def test_named_typed_enc
  408. key = "\u{3012}"
  409. [Encoding::UTF_8, Encoding::EUC_JP].each do |enc|
  410. k = key.encode(enc)
  411. e = assert_raise_with_message(ArgumentError, "named{#{k}} after numbered") {sprintf("%1${#{k}}s", key: "value")}
  412. assert_equal(enc, e.message.encoding)
  413. e = assert_raise_with_message(ArgumentError, "named{#{k}} after unnumbered(2)") {sprintf("%s%s%{#{k}}s", "foo", "bar", key: "value")}
  414. assert_equal(enc, e.message.encoding)
  415. e = assert_raise_with_message(ArgumentError, "named{#{k}} after <key>") {sprintf("%<key>{#{k}}s", key: "value")}
  416. assert_equal(enc, e.message.encoding)
  417. e = assert_raise_with_message(ArgumentError, "named{key} after <#{k}>") {sprintf("%<#{k}>{key}s", k.to_sym => "value")}
  418. assert_equal(enc, e.message.encoding)
  419. e = assert_raise_with_message(KeyError, "key{#{k}} not found") {sprintf("%{#{k}}", {})}
  420. assert_equal(enc, e.message.encoding)
  421. end
  422. end
  423. def test_named_default
  424. h = Hash.new('world')
  425. assert_equal("hello world", "hello %{location}" % h)
  426. assert_equal("hello world", "hello %<location>s" % h)
  427. end
  428. def test_named_with_nil
  429. h = { key: nil, key2: "key2_val" }
  430. assert_equal("key is , key2 is key2_val", "key is %{key}, key2 is %{key2}" % h)
  431. end
  432. def test_width_underflow
  433. bug = 'https://github.com/mruby/mruby/issues/3347'
  434. assert_equal("!", sprintf("%*c", 0, ?!.ord), bug)
  435. end
  436. def test_negative_width_overflow
  437. assert_raise_with_message(ArgumentError, /too big/) do
  438. sprintf("%*s", RbConfig::LIMITS["INT_MIN"], "")
  439. end
  440. end
  441. def test_no_hidden_garbage
  442. skip unless Thread.list.size == 1
  443. fmt = [4, 2, 2].map { |x| "%0#{x}d" }.join('-') # defeats optimization
  444. ObjectSpace.count_objects(res = {}) # creates strings on first call
  445. GC.disable
  446. before = ObjectSpace.count_objects(res)[:T_STRING]
  447. val = sprintf(fmt, 1970, 1, 1)
  448. after = ObjectSpace.count_objects(res)[:T_STRING]
  449. assert_equal before + 1, after, 'only new string is the created one'
  450. assert_equal '1970-01-01', val
  451. ensure
  452. GC.enable
  453. end
  454. end