       {[a: 1, b: 2], [11 | 12]},
       {[a: 1, b: 2], [{:x, 1}, :y, :z]},
       {[a: 1, b: 2], [:x | :y]},
-      {[a: 1, b: 2], [{:x, 1} | :y]},
+      {[a: 1, b: 2], [{:x, 1} | :y]}
     ]
 
     for {arg1, arg2} <- args do

      {[a: 1, b: 2, a: 3], [c: 11, d: 12]},
      {[a: 1, b: 2, a: 3], [a: 11]},
      {[a: 1, b: 2], [c: 11, c: 12, d: 13]},
      {[a: 1, b: 2, c: 3, c: 4], [c: 11, c: 12, d: 13]},
    ]

    args_error = [

  end

  test "is a :: operator on ambiguity" do
    assert [{:::, _, [{:a, _, _}, {:b, _, _}]}] = quote(do: [a :: b])
  end

  test "supports optional comma" do
    [a: 1, b: 2, c: 3]
  end

  test "implements (almost) all functions in Map" do
    assert Map.__info__(:functions) -- Keyword.__info__(:functions) == [from_struct: 1]
  end

  test "get_and_update/3 raises on bad return value from the argument function" do
    message = "the given function must return a two-element tuple or :pop, got: 1"

    assert_raise RuntimeError, message, fn ->
      Keyword.get_and_update([a: 1], :a, fn value -> value end)
    end

    message = "the given function must return a two-element tuple or :pop, got: nil"

    assert_raise RuntimeError, message, fn ->
      Keyword.get_and_update([], :a, fn value -> value end)
    end
  end

  test "get_and_update!/3 raises on bad return value from the argument function" do
    message = "the given function must return a two-element tuple or :pop, got: 1"

    assert_raise RuntimeError, message, fn ->
      Keyword.get_and_update!([a: 1], :a, fn value -> value end)
    end
  end

  test "merge/2" do
    assert Keyword.merge([a: 1, b: 2], c: 11, d: 12) == [a: 1, b: 2, c: 11, d: 12]
    assert Keyword.merge([], c: 11, d: 12) == [c: 11, d: 12]
    assert Keyword.merge([a: 1, b: 2], []) == [a: 1, b: 2]

    message = "expected a keyword list as the first argument, got: [1, 2]"

    assert_raise ArgumentError, message, fn ->
      Keyword.merge([1, 2], c: 11, d: 12)
    end

    message = "expected a keyword list as the first argument, got: [1 | 2]"

    assert_raise ArgumentError, message, fn ->
      Keyword.merge([1 | 2], c: 11, d: 12)
    end

    message = "expected a keyword list as the second argument, got: [11, 12, 0]"

    assert_raise ArgumentError, message, fn ->
      Keyword.merge([a: 1, b: 2], [11, 12, 0])
    end

    message = "expected a keyword list as the second argument, got: [11 | 12]"

    assert_raise ArgumentError, message, fn ->
      Keyword.merge([a: 1, b: 2], [11 | 12])
    end

    # duplicate keys in keywords1 are kept if key is not present in keywords2
    assert Keyword.merge([a: 1, b: 2, a: 3], c: 11, d: 12) == [a: 1, b: 2, a: 3, c: 11, d: 12]
    assert Keyword.merge([a: 1, b: 2, a: 3], a: 11) == [b: 2, a: 11]

    # duplicate keys in keywords2 are always kept
    assert Keyword.merge([a: 1, b: 2], c: 11, c: 12, d: 13) == [a: 1, b: 2, c: 11, c: 12, d: 13]

    # any key in keywords1 is removed if key is present in keyword2
    assert Keyword.merge([a: 1, b: 2, c: 3, c: 4], c: 11, c: 12, d: 13) == [
             a: 1,
             b: 2,
             c: 11,
             c: 12,
             d: 13
           ]
  end

  test "merge/3" do
