1require 'test/unit' 2require_relative 'envutil' 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 test_method_parameters 121 assert_equal([[:key, :str], [:key, :num]], method(:f1).parameters); 122 assert_equal([[:req, :x], [:key, :str], [:key, :num]], method(:f2).parameters); 123 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f3).parameters); 124 assert_equal([[:key, :str], [:key, :num]], method(:f4).parameters); 125 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f5).parameters); 126 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], method(:f6).parameters); 127 assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], method(:f7).parameters); 128 assert_equal([[:opt, :opt], [:rest, :rest], [:key, :key]], method(:f8).parameters) # [Bug #7540] [ruby-core:50735] 129 assert_equal([[:req, :r], [:opt, :o], [:rest, :args], [:req, :p], [:key, :k], 130 [:keyrest, :kw], [:block, :b]], method(:f9).parameters) 131 end 132 133 def test_lambda 134 f = ->(str: "foo", num: 424242) { [str, num] } 135 assert_equal(["foo", 424242], f[]) 136 assert_equal(["bar", 424242], f[str: "bar"]) 137 assert_equal(["foo", 111111], f[num: 111111]) 138 assert_equal(["bar", 111111], f[str: "bar", num: 111111]) 139 end 140 141 142 def p1 143 Proc.new do |str: "foo", num: 424242| 144 [str, num] 145 end 146 end 147 148 def test_p1 149 assert_equal(["foo", 424242], p1[]) 150 assert_equal(["bar", 424242], p1[str: "bar"]) 151 assert_equal(["foo", 111111], p1[num: 111111]) 152 assert_equal(["bar", 111111], p1[str: "bar", num: 111111]) 153 assert_raise(ArgumentError) { p1[str: "bar", check: true] } 154 assert_equal(["foo", 424242], p1["string"] ) 155 end 156 157 158 def p2 159 Proc.new do |x, str: "foo", num: 424242| 160 [x, str, num] 161 end 162 end 163 164 def test_p2 165 assert_equal([nil, "foo", 424242], p2[]) 166 assert_equal([:xyz, "foo", 424242], p2[:xyz]) 167 end 168 169 170 def p3 171 Proc.new do |str: "foo", num: 424242, **h| 172 [str, num, h] 173 end 174 end 175 176 def test_p3 177 assert_equal(["foo", 424242, {}], p3[]) 178 assert_equal(["bar", 424242, {}], p3[str: "bar"]) 179 assert_equal(["foo", 111111, {}], p3[num: 111111]) 180 assert_equal(["bar", 111111, {}], p3[str: "bar", num: 111111]) 181 assert_equal(["bar", 424242, {:check=>true}], p3[str: "bar", check: true]) 182 assert_equal(["foo", 424242, {}], p3["string"]) 183 end 184 185 186 def p4 187 Proc.new do |str: "foo", num: 424242, **h, &blk| 188 [str, num, h, blk] 189 end 190 end 191 192 def test_p4 193 assert_equal(["foo", 424242, {}, nil], p4[]) 194 assert_equal(["bar", 424242, {}, nil], p4[str: "bar"]) 195 assert_equal(["foo", 111111, {}, nil], p4[num: 111111]) 196 assert_equal(["bar", 111111, {}, nil], p4[str: "bar", num: 111111]) 197 assert_equal(["bar", 424242, {:check=>true}, nil], p4[str: "bar", check: true]) 198 a = p4.call {|x| x + 42 } 199 assert_equal(["foo", 424242, {}], a[0, 3]) 200 assert_equal(43, a.last.call(1)) 201 end 202 203 204 def p5 205 Proc.new do |*r, str: "foo", num: 424242, **h| 206 [r, str, num, h] 207 end 208 end 209 210 def test_p5 211 assert_equal([[], "foo", 424242, {}], p5[]) 212 assert_equal([[], "bar", 424242, {}], p5[str: "bar"]) 213 assert_equal([[], "foo", 111111, {}], p5[num: 111111]) 214 assert_equal([[], "bar", 111111, {}], p5[str: "bar", num: 111111]) 215 assert_equal([[1], "foo", 424242, {}], p5[1]) 216 assert_equal([[1, 2], "foo", 424242, {}], p5[1, 2]) 217 assert_equal([[1, 2, 3], "foo", 424242, {}], p5[1, 2, 3]) 218 assert_equal([[1], "bar", 424242, {}], p5[1, str: "bar"]) 219 assert_equal([[1, 2], "bar", 424242, {}], p5[1, 2, str: "bar"]) 220 assert_equal([[1, 2, 3], "bar", 424242, {}], p5[1, 2, 3, str: "bar"]) 221 end 222 223 224 def p6 225 Proc.new do |o1, o2=42, *args, p, k: :key, **kw, &b| 226 [o1, o2, args, p, k, kw, b] 227 end 228 end 229 230 def test_p6 231 assert_equal([nil, 42, [], nil, :key, {}, nil], p6[]) 232 assert_equal([1, 42, [], 2, :key, {}, nil], p6[1, 2]) 233 assert_equal([1, 2, [], 3, :key, {}, nil], p6[1, 2, 3]) 234 assert_equal([1, 2, [3], 4, :key, {}, nil], p6[1, 2, 3, 4]) 235 assert_equal([1, 2, [3, 4], 5, :key, {str: "bar"}, nil], p6[1, 2, 3, 4, 5, str: "bar"]) 236 end 237 238 def test_proc_parameters 239 assert_equal([[:key, :str], [:key, :num]], p1.parameters); 240 assert_equal([[:opt, :x], [:key, :str], [:key, :num]], p2.parameters); 241 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], p3.parameters); 242 assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], p4.parameters); 243 assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], p5.parameters); 244 assert_equal([[:opt, :o1], [:opt, :o2], [:rest, :args], [:opt, :p], [:key, :k], 245 [:keyrest, :kw], [:block, :b]], p6.parameters) 246 end 247 248 def m1(*args) 249 yield *args 250 end 251 252 def test_block 253 blk = Proc.new {|str: "foo", num: 424242| [str, num] } 254 assert_equal(["foo", 424242], m1(&blk)) 255 assert_equal(["bar", 424242], m1(str: "bar", &blk)) 256 assert_equal(["foo", 111111], m1(num: 111111, &blk)) 257 assert_equal(["bar", 111111], m1(str: "bar", num: 111111, &blk)) 258 end 259 260 def rest_keyrest(*args, **opt) 261 return *args, opt 262 end 263 264 def test_rest_keyrest 265 bug7665 = '[ruby-core:51278]' 266 bug8463 = '[ruby-core:55203] [Bug #8463]' 267 expect = [*%w[foo bar], {zzz: 42}] 268 assert_equal(expect, rest_keyrest(*expect), bug7665) 269 pr = proc {|*args, **opt| next *args, opt} 270 assert_equal(expect, pr.call(*expect), bug7665) 271 assert_equal(expect, pr.call(expect), bug8463) 272 pr = proc {|a, *b, **opt| next a, *b, opt} 273 assert_equal(expect, pr.call(expect), bug8463) 274 pr = proc {|a, **opt| next a, opt} 275 assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) 276 end 277 278 def test_bare_kwrest 279 # valid syntax, but its semantics is undefined 280 assert_valid_syntax("def bug7662(**) end") 281 assert_valid_syntax("def bug7662(*, **) end") 282 assert_valid_syntax("def bug7662(a, **) end") 283 end 284 285 def test_without_paren 286 bug7942 = '[ruby-core:52820] [Bug #7942]' 287 assert_valid_syntax("def bug7942 a: 1; end") 288 assert_valid_syntax("def bug7942 a: 1, **; end") 289 290 o = Object.new 291 eval("def o.bug7942 a: 1; a; end", nil, __FILE__, __LINE__) 292 assert_equal(1, o.bug7942(), bug7942) 293 assert_equal(42, o.bug7942(a: 42), bug7942) 294 295 o = Object.new 296 eval("def o.bug7942 a: 1, **; a; end", nil, __FILE__, __LINE__) 297 assert_equal(1, o.bug7942(), bug7942) 298 assert_equal(42, o.bug7942(a: 42), bug7942) 299 end 300 301 def test_super_with_keyword 302 bug8236 = '[ruby-core:54094] [Bug #8236]' 303 base = Class.new do 304 def foo(*args) 305 args 306 end 307 end 308 a = Class.new(base) do 309 def foo(arg, bar: 'x') 310 super 311 end 312 end 313 b = Class.new(base) do 314 def foo(*args, bar: 'x') 315 super 316 end 317 end 318 assert_equal([42, {:bar=>"x"}], a.new.foo(42), bug8236) 319 assert_equal([42, {:bar=>"x"}], b.new.foo(42), bug8236) 320 end 321 322 def test_zsuper_only_named_kwrest 323 bug8416 = '[ruby-core:55033] [Bug #8416]' 324 base = Class.new do 325 def foo(**h) 326 h 327 end 328 end 329 a = Class.new(base) do 330 def foo(**h) 331 super 332 end 333 end 334 assert_equal({:bar=>"x"}, a.new.foo(bar: "x"), bug8416) 335 end 336 337 def test_zsuper_only_anonymous_kwrest 338 bug8416 = '[ruby-core:55033] [Bug #8416]' 339 base = Class.new do 340 def foo(**h) 341 h 342 end 343 end 344 a = Class.new(base) do 345 def foo(**) 346 super 347 end 348 end 349 assert_equal({:bar=>"x"}, a.new.foo(bar: "x"), bug8416) 350 end 351 352 def test_precedence_of_keyword_arguments 353 bug8040 = '[ruby-core:53199] [Bug #8040]' 354 a = Class.new do 355 def foo(x, **h) 356 [x, h] 357 end 358 end 359 assert_equal([{}, {}], a.new.foo({})) 360 assert_equal([{}, {:bar=>"x"}], a.new.foo({}, bar: "x")) 361 end 362end 363