1# frozen_string_literal: false 2require 'test/unit' 3 4class TestKeywordArguments < Test::Unit::TestCase 5 def f1(str: "foo", num: 424242) 6 [str, num] 7 end 8 9 def test_f1 10 assert_equal(["foo", 424242], f1) 11 assert_equal(["bar", 424242], f1(str: "bar")) 12 assert_equal(["foo", 111111], f1(num: 111111)) 13 assert_equal(["bar", 111111], f1(str: "bar", num: 111111)) 14 assert_raise(ArgumentError) { f1(str: "bar", check: true) } 15 assert_raise(ArgumentError) { f1("string") } 16 end 17 18 19 def f2(x, str: "foo", num: 424242) 20 [x, str, num] 21 end 22 23 def test_f2 24 assert_equal([:xyz, "foo", 424242], f2(:xyz)) 25 assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42)) 26 end 27 28 29 def f3(str: "foo", num: 424242, **h) 30 [str, num, h] 31 end 32 33 def test_f3 34 assert_equal(["foo", 424242, {}], f3) 35 assert_equal(["bar", 424242, {}], f3(str: "bar")) 36 assert_equal(["foo", 111111, {}], f3(num: 111111)) 37 assert_equal(["bar", 111111, {}], f3(str: "bar", num: 111111)) 38 assert_equal(["bar", 424242, {:check=>true}], f3(str: "bar", check: true)) 39 assert_raise(ArgumentError) { f3("string") } 40 end 41 42 43 define_method(:f4) {|str: "foo", num: 424242| [str, num] } 44 45 def test_f4 46 assert_equal(["foo", 424242], f4) 47 assert_equal(["bar", 424242], f4(str: "bar")) 48 assert_equal(["foo", 111111], f4(num: 111111)) 49 assert_equal(["bar", 111111], f4(str: "bar", num: 111111)) 50 assert_raise(ArgumentError) { f4(str: "bar", check: true) } 51 assert_raise(ArgumentError) { f4("string") } 52 end 53 54 55 define_method(:f5) {|str: "foo", num: 424242, **h| [str, num, h] } 56 57 def test_f5 58 assert_equal(["foo", 424242, {}], f5) 59 assert_equal(["bar", 424242, {}], f5(str: "bar")) 60 assert_equal(["foo", 111111, {}], f5(num: 111111)) 61 assert_equal(["bar", 111111, {}], f5(str: "bar", num: 111111)) 62 assert_equal(["bar", 424242, {:check=>true}], f5(str: "bar", check: true)) 63 assert_raise(ArgumentError) { f5("string") } 64 end 65 66 67 def f6(str: "foo", num: 424242, **h, &blk) 68 [str, num, h, blk] 69 end 70 71 def test_f6 # [ruby-core:40518] 72 assert_equal(["foo", 424242, {}, nil], f6) 73 assert_equal(["bar", 424242, {}, nil], f6(str: "bar")) 74 assert_equal(["foo", 111111, {}, nil], f6(num: 111111)) 75 assert_equal(["bar", 111111, {}, nil], f6(str: "bar", num: 111111)) 76 assert_equal(["bar", 424242, {:check=>true}, nil], f6(str: "bar", check: true)) 77 a = f6 {|x| x + 42 } 78 assert_equal(["foo", 424242, {}], a[0, 3]) 79 assert_equal(43, a.last.call(1)) 80 end 81 82 def f7(*r, str: "foo", num: 424242, **h) 83 [r, str, num, h] 84 end 85 86 def test_f7 # [ruby-core:41772] 87 assert_equal([[], "foo", 424242, {}], f7) 88 assert_equal([[], "bar", 424242, {}], f7(str: "bar")) 89 assert_equal([[], "foo", 111111, {}], f7(num: 111111)) 90 assert_equal([[], "bar", 111111, {}], f7(str: "bar", num: 111111)) 91 assert_equal([[1], "foo", 424242, {}], f7(1)) 92 assert_equal([[1, 2], "foo", 424242, {}], f7(1, 2)) 93 assert_equal([[1, 2, 3], "foo", 424242, {}], f7(1, 2, 3)) 94 assert_equal([[1], "bar", 424242, {}], f7(1, str: "bar")) 95 assert_equal([[1, 2], "bar", 424242, {}], f7(1, 2, str: "bar")) 96 assert_equal([[1, 2, 3], "bar", 424242, {}], f7(1, 2, 3, str: "bar")) 97 end 98 99 define_method(:f8) { |opt = :ion, *rest, key: :word| 100 [opt, rest, key] 101 } 102 103 def test_f8 104 assert_equal([:ion, [], :word], f8) 105 assert_equal([1, [], :word], f8(1)) 106 assert_equal([1, [2], :word], f8(1, 2)) 107 end 108 109 def f9(r, o=42, *args, p, k: :key, **kw, &b) 110 [r, o, args, p, k, kw, b] 111 end 112 113 def test_f9 114 assert_equal([1, 42, [], 2, :key, {}, nil], f9(1, 2)) 115 assert_equal([1, 2, [], 3, :key, {}, nil], f9(1, 2, 3)) 116 assert_equal([1, 2, [3], 4, :key, {}, nil], f9(1, 2, 3, 4)) 117 assert_equal([1, 2, [3, 4], 5, :key, {str: "bar"}, nil], f9(1, 2, 3, 4, 5, str: "bar")) 118 end 119 120 def f10(a: 1, **) 121 a 122 end 123 124 def test_f10 125 assert_equal(42, f10(a: 42)) 126 assert_equal(1, f10(b: 42)) 127 end 128 129 def test_method_parameters 130 assert_equal([[:key, :str], [:key, :num]], method(:f1).parameters); 131 assert_equal([[:req, :x], [:key, :str], [:key, :num]], method(:f2).parameters); 132 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f3).parameters); 133 assert_equal([[:key, :str], [:key, :num]], method(:f4).parameters); 134 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f5).parameters); 135 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], method(:f6).parameters); 136 assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], method(:f7).parameters); 137 assert_equal([[:opt, :opt], [:rest, :rest], [:key, :key]], method(:f8).parameters) # [Bug #7540] [ruby-core:50735] 138 assert_equal([[:req, :r], [:opt, :o], [:rest, :args], [:req, :p], [:key, :k], 139 [:keyrest, :kw], [:block, :b]], method(:f9).parameters) 140 end 141 142 def test_lambda 143 f = ->(str: "foo", num: 424242) { [str, num] } 144 assert_equal(["foo", 424242], f[]) 145 assert_equal(["bar", 424242], f[str: "bar"]) 146 assert_equal(["foo", 111111], f[num: 111111]) 147 assert_equal(["bar", 111111], f[str: "bar", num: 111111]) 148 end 149 150 151 def p1 152 Proc.new do |str: "foo", num: 424242| 153 [str, num] 154 end 155 end 156 157 def test_p1 158 assert_equal(["foo", 424242], p1[]) 159 assert_equal(["bar", 424242], p1[str: "bar"]) 160 assert_equal(["foo", 111111], p1[num: 111111]) 161 assert_equal(["bar", 111111], p1[str: "bar", num: 111111]) 162 assert_raise(ArgumentError) { p1[str: "bar", check: true] } 163 assert_equal(["foo", 424242], p1["string"] ) 164 end 165 166 167 def p2 168 Proc.new do |x, str: "foo", num: 424242| 169 [x, str, num] 170 end 171 end 172 173 def test_p2 174 assert_equal([nil, "foo", 424242], p2[]) 175 assert_equal([:xyz, "foo", 424242], p2[:xyz]) 176 end 177 178 179 def p3 180 Proc.new do |str: "foo", num: 424242, **h| 181 [str, num, h] 182 end 183 end 184 185 def test_p3 186 assert_equal(["foo", 424242, {}], p3[]) 187 assert_equal(["bar", 424242, {}], p3[str: "bar"]) 188 assert_equal(["foo", 111111, {}], p3[num: 111111]) 189 assert_equal(["bar", 111111, {}], p3[str: "bar", num: 111111]) 190 assert_equal(["bar", 424242, {:check=>true}], p3[str: "bar", check: true]) 191 assert_equal(["foo", 424242, {}], p3["string"]) 192 end 193 194 195 def p4 196 Proc.new do |str: "foo", num: 424242, **h, &blk| 197 [str, num, h, blk] 198 end 199 end 200 201 def test_p4 202 assert_equal(["foo", 424242, {}, nil], p4[]) 203 assert_equal(["bar", 424242, {}, nil], p4[str: "bar"]) 204 assert_equal(["foo", 111111, {}, nil], p4[num: 111111]) 205 assert_equal(["bar", 111111, {}, nil], p4[str: "bar", num: 111111]) 206 assert_equal(["bar", 424242, {:check=>true}, nil], p4[str: "bar", check: true]) 207 a = p4.call {|x| x + 42 } 208 assert_equal(["foo", 424242, {}], a[0, 3]) 209 assert_equal(43, a.last.call(1)) 210 end 211 212 213 def p5 214 Proc.new do |*r, str: "foo", num: 424242, **h| 215 [r, str, num, h] 216 end 217 end 218 219 def test_p5 220 assert_equal([[], "foo", 424242, {}], p5[]) 221 assert_equal([[], "bar", 424242, {}], p5[str: "bar"]) 222 assert_equal([[], "foo", 111111, {}], p5[num: 111111]) 223 assert_equal([[], "bar", 111111, {}], p5[str: "bar", num: 111111]) 224 assert_equal([[1], "foo", 424242, {}], p5[1]) 225 assert_equal([[1, 2], "foo", 424242, {}], p5[1, 2]) 226 assert_equal([[1, 2, 3], "foo", 424242, {}], p5[1, 2, 3]) 227 assert_equal([[1], "bar", 424242, {}], p5[1, str: "bar"]) 228 assert_equal([[1, 2], "bar", 424242, {}], p5[1, 2, str: "bar"]) 229 assert_equal([[1, 2, 3], "bar", 424242, {}], p5[1, 2, 3, str: "bar"]) 230 end 231 232 233 def p6 234 Proc.new do |o1, o2=42, *args, p, k: :key, **kw, &b| 235 [o1, o2, args, p, k, kw, b] 236 end 237 end 238 239 def test_p6 240 assert_equal([nil, 42, [], nil, :key, {}, nil], p6[]) 241 assert_equal([1, 42, [], 2, :key, {}, nil], p6[1, 2]) 242 assert_equal([1, 2, [], 3, :key, {}, nil], p6[1, 2, 3]) 243 assert_equal([1, 2, [3], 4, :key, {}, nil], p6[1, 2, 3, 4]) 244 assert_equal([1, 2, [3, 4], 5, :key, {str: "bar"}, nil], p6[1, 2, 3, 4, 5, str: "bar"]) 245 end 246 247 def test_proc_parameters 248 assert_equal([[:key, :str], [:key, :num]], p1.parameters); 249 assert_equal([[:opt, :x], [:key, :str], [:key, :num]], p2.parameters); 250 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], p3.parameters); 251 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], p4.parameters); 252 assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], p5.parameters); 253 assert_equal([[:opt, :o1], [:opt, :o2], [:rest, :args], [:opt, :p], [:key, :k], 254 [:keyrest, :kw], [:block, :b]], p6.parameters) 255 end 256 257 def m1(*args) 258 yield(*args) 259 end 260 261 def test_block 262 blk = Proc.new {|str: "foo", num: 424242| [str, num] } 263 assert_equal(["foo", 424242], m1(&blk)) 264 assert_equal(["bar", 424242], m1(str: "bar", &blk)) 265 assert_equal(["foo", 111111], m1(num: 111111, &blk)) 266 assert_equal(["bar", 111111], m1(str: "bar", num: 111111, &blk)) 267 end 268 269 def rest_keyrest(*args, **opt) 270 return *args, opt 271 end 272 273 def test_rest_keyrest 274 bug7665 = '[ruby-core:51278]' 275 bug8463 = '[ruby-core:55203] [Bug #8463]' 276 expect = [*%w[foo bar], {zzz: 42}] 277 assert_equal(expect, rest_keyrest(*expect), bug7665) 278 pr = proc {|*args, **opt| next *args, opt} 279 assert_equal(expect, pr.call(*expect), bug7665) 280 assert_equal(expect, pr.call(expect), bug8463) 281 pr = proc {|a, *b, **opt| next a, *b, opt} 282 assert_equal(expect, pr.call(expect), bug8463) 283 pr = proc {|a, **opt| next a, opt} 284 assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) 285 end 286 287 def test_bare_kwrest 288 # valid syntax, but its semantics is undefined 289 assert_valid_syntax("def bug7662(**) end") 290 assert_valid_syntax("def bug7662(*, **) end") 291 assert_valid_syntax("def bug7662(a, **) end") 292 end 293 294 def test_without_paren 295 bug7942 = '[ruby-core:52820] [Bug #7942]' 296 assert_valid_syntax("def bug7942 a: 1; end") 297 assert_valid_syntax("def bug7942 a: 1, **; end") 298 299 o = Object.new 300 eval("def o.bug7942 a: 1; a; end", nil, __FILE__, __LINE__) 301 assert_equal(1, o.bug7942(), bug7942) 302 assert_equal(42, o.bug7942(a: 42), bug7942) 303 304 o = Object.new 305 eval("def o.bug7942 a: 1, **; a; end", nil, __FILE__, __LINE__) 306 assert_equal(1, o.bug7942(), bug7942) 307 assert_equal(42, o.bug7942(a: 42), bug7942) 308 end 309 310 def test_required_keyword 311 feature7701 = '[ruby-core:51454] [Feature #7701] required keyword argument' 312 o = Object.new 313 assert_nothing_raised(SyntaxError, feature7701) do 314 eval("def o.foo(a:) a; end", nil, "xyzzy") 315 eval("def o.bar(a:,**b) [a, b]; end") 316 end 317 assert_raise_with_message(ArgumentError, /missing keyword/, feature7701) {o.foo} 318 assert_raise_with_message(ArgumentError, /unknown keyword/, feature7701) {o.foo(a:0, b:1)} 319 begin 320 o.foo(a: 0, b: 1) 321 rescue => e 322 assert_equal('xyzzy', e.backtrace_locations[0].path) 323 end 324 assert_equal(42, o.foo(a: 42), feature7701) 325 assert_equal([[:keyreq, :a]], o.method(:foo).parameters, feature7701) 326 327 bug8139 = '[ruby-core:53608] [Bug #8139] required keyword argument with rest hash' 328 assert_equal([42, {}], o.bar(a: 42), feature7701) 329 assert_equal([42, {c: feature7701}], o.bar(a: 42, c: feature7701), feature7701) 330 assert_equal([[:keyreq, :a], [:keyrest, :b]], o.method(:bar).parameters, feature7701) 331 assert_raise_with_message(ArgumentError, /missing keyword/, bug8139) {o.bar(c: bug8139)} 332 assert_raise_with_message(ArgumentError, /missing keyword/, bug8139) {o.bar} 333 end 334 335 def test_required_keyword_with_newline 336 bug9669 = '[ruby-core:61658] [Bug #9669]' 337 assert_nothing_raised(SyntaxError, bug9669) do 338 eval(<<-'end;', nil, __FILE__, __LINE__) 339 def bug9669.foo a: 340 return a 341 end 342 end; 343 end 344 assert_equal(42, bug9669.foo(a: 42)) 345 o = nil 346 assert_nothing_raised(SyntaxError, bug9669) do 347 eval(<<-'end;', nil, __FILE__, __LINE__) 348 o = { 349 a: 350 1 351 } 352 end; 353 end 354 assert_equal({a: 1}, o, bug9669) 355 end 356 357 def test_required_keyword_with_reserved 358 bug10279 = '[ruby-core:65211] [Bug #10279]' 359 h = nil 360 assert_nothing_raised(SyntaxError, bug10279) do 361 break eval(<<-'end;', nil, __FILE__, __LINE__) 362 h = {a: if true then 42 end} 363 end; 364 end 365 assert_equal({a: 42}, h, bug10279) 366 end 367 368 def test_block_required_keyword 369 feature7701 = '[ruby-core:51454] [Feature #7701] required keyword argument' 370 b = assert_nothing_raised(SyntaxError, feature7701) do 371 break eval("proc {|a:| a}", nil, 'xyzzy', __LINE__) 372 end 373 assert_raise_with_message(ArgumentError, /missing keyword/, feature7701) {b.call} 374 e = assert_raise_with_message(ArgumentError, /unknown keyword/, feature7701) {b.call(a:0, b:1)} 375 assert_equal('xyzzy', e.backtrace_locations[0].path) 376 377 assert_equal(42, b.call(a: 42), feature7701) 378 assert_equal([[:keyreq, :a]], b.parameters, feature7701) 379 380 bug8139 = '[ruby-core:53608] [Bug #8139] required keyword argument with rest hash' 381 b = assert_nothing_raised(SyntaxError, feature7701) do 382 break eval("proc {|a:, **bl| [a, bl]}", nil, __FILE__, __LINE__) 383 end 384 assert_equal([42, {}], b.call(a: 42), feature7701) 385 assert_equal([42, {c: feature7701}], b.call(a: 42, c: feature7701), feature7701) 386 assert_equal([[:keyreq, :a], [:keyrest, :bl]], b.parameters, feature7701) 387 assert_raise_with_message(ArgumentError, /missing keyword/, bug8139) {b.call(c: bug8139)} 388 assert_raise_with_message(ArgumentError, /missing keyword/, bug8139) {b.call} 389 390 b = assert_nothing_raised(SyntaxError, feature7701) do 391 break eval("proc {|m, a:| [m, a]}", nil, 'xyzzy', __LINE__) 392 end 393 assert_raise_with_message(ArgumentError, /missing keyword/) {b.call} 394 assert_equal([:ok, 42], b.call(:ok, a: 42)) 395 e = assert_raise_with_message(ArgumentError, /unknown keyword/) {b.call(42, a:0, b:1)} 396 assert_equal('xyzzy', e.backtrace_locations[0].path) 397 assert_equal([[:opt, :m], [:keyreq, :a]], b.parameters) 398 end 399 400 def test_super_with_keyword 401 bug8236 = '[ruby-core:54094] [Bug #8236]' 402 base = Class.new do 403 def foo(*args) 404 args 405 end 406 end 407 a = Class.new(base) do 408 def foo(arg, bar: 'x') 409 super 410 end 411 end 412 b = Class.new(base) do 413 def foo(*args, bar: 'x') 414 super 415 end 416 end 417 assert_equal([42, {:bar=>"x"}], a.new.foo(42), bug8236) 418 assert_equal([42, {:bar=>"x"}], b.new.foo(42), bug8236) 419 end 420 421 def test_zsuper_only_named_kwrest 422 bug8416 = '[ruby-core:55033] [Bug #8416]' 423 base = Class.new do 424 def foo(**h) 425 h 426 end 427 end 428 a = Class.new(base) do 429 def foo(**h) 430 super 431 end 432 end 433 assert_equal({:bar=>"x"}, a.new.foo(bar: "x"), bug8416) 434 end 435 436 def test_zsuper_only_anonymous_kwrest 437 bug8416 = '[ruby-core:55033] [Bug #8416]' 438 base = Class.new do 439 def foo(**h) 440 h 441 end 442 end 443 a = Class.new(base) do 444 def foo(**) 445 super 446 end 447 end 448 assert_equal({:bar=>"x"}, a.new.foo(bar: "x"), bug8416) 449 end 450 451 def test_precedence_of_keyword_arguments 452 bug8040 = '[ruby-core:53199] [Bug #8040]' 453 a = Class.new do 454 def foo(x, **h) 455 [x, h] 456 end 457 end 458 assert_equal([{}, {}], a.new.foo({})) 459 assert_equal([{}, {:bar=>"x"}], a.new.foo({}, bar: "x"), bug8040) 460 end 461 462 def test_precedence_of_keyword_arguments_with_post_argument 463 bug8993 = '[ruby-core:57706] [Bug #8993]' 464 a = Class.new do 465 def foo(a, b, c=1, *d, e, f:2, **g) 466 [a, b, c, d, e, f, g] 467 end 468 end 469 assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993) 470 end 471 472 def test_splat_keyword_nondestructive 473 bug9776 = '[ruby-core:62161] [Bug #9776]' 474 475 h = {a: 1} 476 assert_equal({a:1, b:2}, {**h, b:2}) 477 assert_equal({a:1}, h, bug9776) 478 479 pr = proc {|**opt| next opt} 480 assert_equal({a: 1}, pr.call(**h)) 481 assert_equal({a: 1, b: 2}, pr.call(**h, b: 2)) 482 assert_equal({a: 1}, h, bug9776) 483 end 484 485 def test_splat_hash_conversion 486 bug9898 = '[ruby-core:62921] [Bug #9898]' 487 488 o = Object.new 489 def o.to_hash() { a: 1 } end 490 assert_equal({a: 1}, m1(**o) {|x| break x}, bug9898) 491 o2 = Object.new 492 def o2.to_hash() { b: 2 } end 493 assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898) 494 end 495 496 def test_implicit_hash_conversion 497 bug10016 = '[ruby-core:63593] [Bug #10016]' 498 499 o = Object.new 500 def o.to_hash() { k: 9 } end 501 assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o)) 502 assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016) 503 assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016) 504 end 505 506 def test_splat_hash 507 m = Object.new 508 def m.f() :ok; end 509 def m.f1(a) a; end 510 def m.f2(a = nil) a; end 511 def m.f3(**a) a; end 512 def m.f4(*a) a; end 513 o = {a: 1} 514 assert_raise_with_message(ArgumentError, /unknown keyword: a/) { 515 m.f(**o) 516 } 517 o = {} 518 assert_equal(:ok, m.f(**o), '[ruby-core:68124] [Bug #10856]') 519 a = [] 520 assert_equal(:ok, m.f(*a, **o), '[ruby-core:83638] [Bug #10856]') 521 522 o = {a: 42} 523 assert_warning('', 'splat to kwrest') do 524 assert_equal({a: 42}, m.f3(**o)) 525 end 526 assert_warning('', 'splat to rest') do 527 assert_equal([{a: 42}], m.f4(**o)) 528 end 529 530 assert_warning('') do 531 assert_equal({a: 42}, m.f2("a".to_sym => 42), '[ruby-core:82291] [Bug #13793]') 532 end 533 534 o = {} 535 a = [:ok] 536 assert_equal(:ok, m.f2(*a, **o), '[ruby-core:83638] [Bug #10856]') 537 end 538 539 def test_gced_object_in_stack 540 bug8964 = '[ruby-dev:47729] [Bug #8964]' 541 assert_normal_exit %q{ 542 def m(a: []) 543 end 544 GC.stress = true 545 tap { m } 546 GC.start 547 tap { m } 548 }, bug8964 549 assert_normal_exit %q{ 550 prc = Proc.new {|a: []|} 551 GC.stress = true 552 tap { prc.call } 553 GC.start 554 tap { prc.call } 555 }, bug8964 556 end 557 558 def test_dynamic_symbol_keyword 559 bug10266 = '[ruby-dev:48564] [Bug #10266]' 560 assert_separately(['-', bug10266], "#{<<~"begin;"}\n#{<<~'end;'}") 561 begin; 562 bug = ARGV.shift 563 "hoge".to_sym 564 assert_nothing_raised(bug) {eval("def a(hoge:); end")} 565 end; 566 end 567 568 def test_unknown_keyword_with_block 569 bug10413 = '[ruby-core:65837] [Bug #10413]' 570 class << (o = Object.new) 571 def bar(k2: 'v2') 572 end 573 574 def foo 575 bar(k1: 1) 576 end 577 end 578 assert_raise_with_message(ArgumentError, /unknown keyword: k1/, bug10413) { 579 o.foo {raise "unreachable"} 580 } 581 end 582 583 def test_unknown_keyword 584 bug13004 = '[ruby-dev:49893] [Bug #13004]' 585 assert_raise_with_message(ArgumentError, /unknown keyword: invalid-argument/, bug13004) { 586 [].sample(random: nil, "invalid-argument": nil) 587 } 588 end 589 590 def test_super_with_anon_restkeywords 591 bug10659 = '[ruby-core:67157] [Bug #10659]' 592 593 foo = Class.new do 594 def foo(**h) 595 h 596 end 597 end 598 599 class << (obj = foo.new) 600 def foo(bar: "bar", **) 601 super 602 end 603 end 604 605 assert_nothing_raised(TypeError, bug10659) { 606 assert_equal({:bar => "bar"}, obj.foo, bug10659) 607 } 608 end 609 610 def m(a) yield a end 611 612 def test_nonsymbol_key 613 result = m(["a" => 10]) { |a = nil, **b| [a, b] } 614 assert_equal([{"a" => 10}, {}], result) 615 end 616 617 def method_for_test_to_hash_call_during_setup_complex_parameters k1:, k2:, **rest_kw 618 [k1, k2, rest_kw] 619 end 620 621 def test_to_hash_call_during_setup_complex_parameters 622 sym = "sym_#{Time.now}".to_sym 623 h = method_for_test_to_hash_call_during_setup_complex_parameters k1: "foo", k2: "bar", sym => "baz" 624 assert_equal ["foo", "bar", {sym => "baz"}], h, '[Bug #11027]' 625 end 626 627 class AttrSetTest 628 attr_accessor :foo 629 alias set_foo :foo= 630 end 631 632 def test_attr_set_method_cache 633 obj = AttrSetTest.new 634 h = {a: 1, b: 2} 635 2.times{ 636 obj.foo = 1 637 assert_equal(1, obj.foo) 638 obj.set_foo 2 639 assert_equal(2, obj.foo) 640 obj.set_foo(x: 1, y: 2) 641 assert_equal({x: 1, y: 2}, obj.foo) 642 obj.set_foo(x: 1, y: 2, **h) 643 assert_equal({x: 1, y: 2, **h}, obj.foo) 644 } 645 end 646 647 def test_kwrest_overwritten 648 bug13015 = '[ruby-core:78536] [Bug #13015]' 649 650 klass = EnvUtil.labeled_class("Parent") do 651 def initialize(d:) 652 end 653 end 654 655 klass = EnvUtil.labeled_class("Child", klass) do 656 def initialize(d:, **h) 657 h = [2, 3] 658 super 659 end 660 end 661 662 assert_raise_with_message(TypeError, /expected Hash/, bug13015) do 663 klass.new(d: 4) 664 end 665 end 666 667 def test_non_keyword_hash_subclass 668 bug12884 = '[ruby-core:77813] [Bug #12884]' 669 klass = EnvUtil.labeled_class("Child", Hash) 670 obj = Object.new 671 def obj.t(params = klass.new, d: nil); params; end 672 x = klass.new 673 x["foo"] = "bar" 674 result = obj.t(x) 675 assert_equal(x, result) 676 assert_kind_of(klass, result, bug12884) 677 end 678 679 def test_arity_error_message 680 obj = Object.new 681 def obj.t(x:) end 682 assert_raise_with_message(ArgumentError, /required keyword: x\)/) do 683 obj.t(42) 684 end 685 obj = Object.new 686 def obj.t(x:, y:, z: nil) end 687 assert_raise_with_message(ArgumentError, /required keywords: x, y\)/) do 688 obj.t(42) 689 end 690 end 691 692 def many_kwargs(a0: '', a1: '', a2: '', a3: '', a4: '', a5: '', a6: '', a7: '', 693 b0: '', b1: '', b2: '', b3: '', b4: '', b5: '', b6: '', b7: '', 694 c0: '', c1: '', c2: '', c3: '', c4: '', c5: '', c6: '', c7: '', 695 d0: '', d1: '', d2: '', d3: '', d4: '', d5: '', d6: '', d7: '', 696 e0: '') 697 [a0, a1, a2, a3, a4, a5, a6, a7, 698 b0, b1, b2, b3, b4, b5, b6, b7, 699 c0, c1, c2, c3, c4, c5, c6, c7, 700 d0, d1, d2, d3, d4, d5, d6, d7, 701 e0] 702 end 703 704 def test_many_kwargs 705 i = 0 706 assert_equal(:ok, many_kwargs(a0: :ok)[i], "#{i}: a0"); i+=1 707 assert_equal(:ok, many_kwargs(a1: :ok)[i], "#{i}: a1"); i+=1 708 assert_equal(:ok, many_kwargs(a2: :ok)[i], "#{i}: a2"); i+=1 709 assert_equal(:ok, many_kwargs(a3: :ok)[i], "#{i}: a3"); i+=1 710 assert_equal(:ok, many_kwargs(a4: :ok)[i], "#{i}: a4"); i+=1 711 assert_equal(:ok, many_kwargs(a5: :ok)[i], "#{i}: a5"); i+=1 712 assert_equal(:ok, many_kwargs(a6: :ok)[i], "#{i}: a6"); i+=1 713 assert_equal(:ok, many_kwargs(a7: :ok)[i], "#{i}: a7"); i+=1 714 715 assert_equal(:ok, many_kwargs(b0: :ok)[i], "#{i}: b0"); i+=1 716 assert_equal(:ok, many_kwargs(b1: :ok)[i], "#{i}: b1"); i+=1 717 assert_equal(:ok, many_kwargs(b2: :ok)[i], "#{i}: b2"); i+=1 718 assert_equal(:ok, many_kwargs(b3: :ok)[i], "#{i}: b3"); i+=1 719 assert_equal(:ok, many_kwargs(b4: :ok)[i], "#{i}: b4"); i+=1 720 assert_equal(:ok, many_kwargs(b5: :ok)[i], "#{i}: b5"); i+=1 721 assert_equal(:ok, many_kwargs(b6: :ok)[i], "#{i}: b6"); i+=1 722 assert_equal(:ok, many_kwargs(b7: :ok)[i], "#{i}: b7"); i+=1 723 724 assert_equal(:ok, many_kwargs(c0: :ok)[i], "#{i}: c0"); i+=1 725 assert_equal(:ok, many_kwargs(c1: :ok)[i], "#{i}: c1"); i+=1 726 assert_equal(:ok, many_kwargs(c2: :ok)[i], "#{i}: c2"); i+=1 727 assert_equal(:ok, many_kwargs(c3: :ok)[i], "#{i}: c3"); i+=1 728 assert_equal(:ok, many_kwargs(c4: :ok)[i], "#{i}: c4"); i+=1 729 assert_equal(:ok, many_kwargs(c5: :ok)[i], "#{i}: c5"); i+=1 730 assert_equal(:ok, many_kwargs(c6: :ok)[i], "#{i}: c6"); i+=1 731 assert_equal(:ok, many_kwargs(c7: :ok)[i], "#{i}: c7"); i+=1 732 733 assert_equal(:ok, many_kwargs(d0: :ok)[i], "#{i}: d0"); i+=1 734 assert_equal(:ok, many_kwargs(d1: :ok)[i], "#{i}: d1"); i+=1 735 assert_equal(:ok, many_kwargs(d2: :ok)[i], "#{i}: d2"); i+=1 736 assert_equal(:ok, many_kwargs(d3: :ok)[i], "#{i}: d3"); i+=1 737 assert_equal(:ok, many_kwargs(d4: :ok)[i], "#{i}: d4"); i+=1 738 assert_equal(:ok, many_kwargs(d5: :ok)[i], "#{i}: d5"); i+=1 739 assert_equal(:ok, many_kwargs(d6: :ok)[i], "#{i}: d6"); i+=1 740 assert_equal(:ok, many_kwargs(d7: :ok)[i], "#{i}: d7"); i+=1 741 742 assert_equal(:ok, many_kwargs(e0: :ok)[i], "#{i}: e0"); i+=1 743 end 744 745 def test_splat_empty_hash_with_block_passing 746 assert_valid_syntax("bug15087(**{}, &nil)") 747 end 748end 749