Files
n8n-openai-adapter/lib/elixir/test/elixir/kernel/quote_test.exs
T

452 lines
11 KiB
Elixir

Code.require_file "../test_helper.exs", __DIR__
defmodule Kernel.QuoteTest do
use ExUnit.Case, async: true
test "list" do
assert quote(do: [1, 2, 3]) == [1, 2, 3]
end
test "tuple" do
assert quote(do: {:a, 1}) == {:a, 1}
end
test "keep line" do
# DO NOT MOVE THIS LINE
assert quote(location: :keep, do: bar(1, 2, 3)) ==
{:bar, [file: Path.relative_to_cwd(__ENV__.file), keep: 16], [1, 2, 3]}
end
test "fixed line" do
assert quote(line: 3, do: bar(1, 2, 3)) == {:bar, [line: 3], [1, 2, 3]}
end
test "quote line var" do
# DO NOT MOVE THIS LINE
line = __ENV__.line
assert quote(line: line, do: bar(1, 2, 3)) == {:bar, [line: 26], [1, 2, 3]}
end
test "generated" do
assert quote(generated: true, do: bar(1)) == {:bar, [generated: true], [1]}
end
test "unquote call" do
assert quote(do: foo(bar)[unquote(:baz)]) == quote(do: foo(bar)[:baz])
assert quote(do: unquote(:bar)()) == quote(do: bar())
assert quote(do: unquote(:bar)(1) do 2 + 3 end) == quote(do: bar(1) do 2 + 3 end)
assert quote(do: foo.unquote(:bar)) == quote(do: foo.bar)
assert quote(do: foo.unquote(:bar)(1)) == quote(do: foo.bar(1))
assert quote(do: foo.unquote(:bar)(1) do 2 + 3 end) == quote(do: foo.bar(1) do 2 + 3 end)
assert quote(do: foo.unquote({:bar, [], nil})) == quote(do: foo.bar)
assert quote(do: foo.unquote({:bar, [], [1, 2]})) == quote(do: foo.bar(1, 2))
assert Code.eval_quoted(quote(do: Foo.unquote(Bar))) == {Elixir.Foo.Bar, []}
assert Code.eval_quoted(quote(do: Foo.unquote(quote do: Bar))) == {Elixir.Foo.Bar, []}
assert_raise ArgumentError, fn ->
quote(do: foo.unquote(1))
end
end
test "nested quote" do
assert {:quote, _, [[do: {:unquote, _, _}]]} = quote(do: quote(do: unquote(x)))
end
defmacrop nested_quote_in_macro do
x = 1
quote do
x = unquote(x)
quote do
unquote(x)
end
end
end
test "nested quote in macro" do
assert nested_quote_in_macro() == 1
end
Enum.each [foo: 1, bar: 2, baz: 3], fn {k, v} ->
def unquote(k)(arg) do
unquote(v) + arg
end
end
test "dynamic definition with unquote" do
assert foo(1) == 2
assert bar(2) == 4
assert baz(3) == 6
end
test "splice on root" do
contents = [1, 2, 3]
assert quote(do: (unquote_splicing(contents))) == quote do: (1; 2; 3)
end
test "splice with tail" do
contents = [1, 2, 3]
assert quote(do: [unquote_splicing(contents) | [1, 2, 3]]) ==
[1, 2, 3, 1, 2, 3]
assert quote(do: [unquote_splicing(contents) | val]) ==
quote(do: [1, 2, 3 | val])
assert quote(do: [unquote_splicing(contents) | unquote([4])]) ==
quote(do: [1, 2, 3, 4])
end
test "splice on stab" do
{fun, []} =
Code.eval_quoted(quote(do: fn(unquote_splicing([1, 2, 3])) -> :ok end), [])
assert fun.(1, 2, 3) == :ok
{fun, []} =
Code.eval_quoted(quote(do: fn(1, unquote_splicing([2, 3])) -> :ok end), [])
assert fun.(1, 2, 3) == :ok
end
test "splice on definition" do
defmodule Hello do
def world([unquote_splicing(["foo", "bar"]) | rest]) do
rest
end
end
assert Hello.world(["foo", "bar", "baz"]) == ["baz"]
end
test "splice on map" do
assert %{unquote_splicing([foo: :bar])} == %{foo: :bar}
assert %{unquote_splicing([foo: :bar]), baz: :bat} == %{foo: :bar, baz: :bat}
assert %{unquote_splicing([foo: :bar]), :baz => :bat} == %{foo: :bar, baz: :bat}
assert %{:baz => :bat, unquote_splicing([foo: :bar])} == %{foo: :bar, baz: :bat}
map = %{foo: :default}
assert %{map | unquote_splicing([foo: :bar])} == %{foo: :bar}
end
test "when" do
assert [{:->, _, [[{:when, _, [1, 2, 3, 4]}], 5]}] = quote(do: (1, 2, 3 when 4 -> 5))
assert [{:->, _, [[{:when, _, [1, 2, 3, 4]}], 5]}] = quote(do: ((1, 2, 3) when 4 -> 5))
assert [{:->, _, [[{:when, _, [1, 2, 3, {:when, _, [4, 5]}]}], 6]}] =
quote(do: ((1, 2, 3) when 4 when 5 -> 6))
end
test "stab" do
assert [{:->, _, [[], 1]}] = (quote do -> 1 end)
assert [{:->, _, [[], 1]}] = (quote do: (-> 1))
end
test "bind quoted" do
assert quote(bind_quoted: [foo: 1 + 2], do: foo) == {:__block__, [], [
{:=, [], [{:foo, [], Kernel.QuoteTest}, 3]},
{:foo, [], Kernel.QuoteTest}
]}
end
test "literals" do
assert (quote do: []) == []
assert (quote do: nil) == nil
assert (quote do [] end) == []
assert (quote do nil end) == nil
end
defmacrop dynamic_opts do
[line: 3]
end
test "with dynamic opts" do
assert quote(dynamic_opts(), do: bar(1, 2, 3)) == {:bar, [line: 3], [1, 2, 3]}
end
test "unary with integer precedence" do
assert quote(do: +1.foo) == quote(do: (+1).foo)
assert quote(do: @1.foo) == quote(do: (@1).foo)
assert quote(do: &1.foo) == quote(do: (&1).foo)
end
test "operators slash arity" do
assert {:/, _, [{:+, _, _}, 2]} = quote do: +/2
assert {:/, _, [{:&&, _, _}, 3]} = quote do: &&/3
end
test "pipe precedence" do
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo |> bar |> baz)
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo do end |> bar |> baz)
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo |> bar do end |> baz)
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo |> bar |> baz do end)
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo do end |> bar |> baz do end)
assert {:|>, _, [{:|>, _, [{:foo, _, _}, {:bar, _, _}]}, {:baz, _, _}]} =
quote do: (foo do end |> bar do end |> baz do end)
end
end
# DO NOT MOVE THIS LINE
defmodule Kernel.QuoteTest.Errors do
defmacro defadd do
quote location: :keep do
def add(a, b), do: a + b
end
end
defmacro will_raise do
quote location: :keep, do: raise "omg"
end
end
defmodule Kernel.QuoteTest.ErrorsTest do
use ExUnit.Case, async: true
import Kernel.QuoteTest.Errors
# Defines the add function
defadd()
test "inside function error" do
assert_raise ArithmeticError, fn ->
add(:a, :b)
end
mod = Kernel.QuoteTest.ErrorsTest
file = __ENV__.file |> Path.relative_to_cwd |> String.to_charlist
assert [{^mod, :add, 2, [file: ^file, line: 200]} | _] = System.stacktrace
end
test "outside function error" do
assert_raise RuntimeError, fn ->
will_raise()
end
mod = Kernel.QuoteTest.ErrorsTest
file = __ENV__.file |> Path.relative_to_cwd |> String.to_charlist
assert [{^mod, _, _, [file: ^file, line: 228]} | _] = System.stacktrace
end
end
defmodule Kernel.QuoteTest.VarHygiene do
defmacro no_interference do
quote do: a = 1
end
defmacro write_interference do
quote do: var!(a) = 1
end
defmacro read_interference do
quote do: 10 = var!(a)
end
defmacro cross_module_interference do
quote do: var!(a, Kernel.QuoteTest.VarHygieneTest) = 1
end
end
defmodule Kernel.QuoteTest.VarHygieneTest do
use ExUnit.Case, async: true
import Kernel.QuoteTest.VarHygiene
defmacrop cross_module_no_interference do
quote do: a = 10
end
defmacrop read_cross_module do
quote do: var!(a, __MODULE__)
end
defmacrop nested(var, do: block) do
quote do
var = unquote(var)
unquote(block)
var
end
end
defmacrop hat do
quote do
var = 1
^var = 1
var
end
end
test "no interference" do
a = 10
no_interference()
assert a == 10
end
test "cross module interference" do
cross_module_no_interference()
cross_module_interference()
assert read_cross_module() == 1
end
test "write interference" do
write_interference()
assert a == 1
end
test "read interference" do
a = 10
read_interference()
end
test "nested" do
assert (nested 1 do
nested 2 do
_ = :ok
end
end) == 1
end
test "hat" do
assert hat() == 1
end
end
defmodule Kernel.QuoteTest.AliasHygiene do
alias Dict, as: SuperDict
defmacro dict do
quote do: Dict.Bar
end
defmacro super_dict do
quote do: SuperDict.Bar
end
end
defmodule Kernel.QuoteTest.AliasHygieneTest do
use ExUnit.Case, async: true
alias Dict, as: SuperDict
test "annotate aliases" do
assert {:__aliases__, [alias: false], [:Foo, :Bar]} =
quote(do: Foo.Bar)
assert {:__aliases__, [alias: false], [:Dict, :Bar]} =
quote(do: Dict.Bar)
assert {:__aliases__, [alias: Dict.Bar], [:SuperDict, :Bar]} =
quote(do: SuperDict.Bar)
end
test "expand aliases" do
assert Code.eval_quoted(quote do: SuperDict.Bar) == {Elixir.Dict.Bar, []}
assert Code.eval_quoted(quote do: alias!(SuperDict.Bar)) == {Elixir.SuperDict.Bar, []}
end
test "expand aliases without macro" do
alias HashDict, as: SuperDict
assert SuperDict.Bar == Elixir.HashDict.Bar
end
test "expand aliases with macro does not expand source alias" do
alias HashDict, as: Dict, warn: false
require Kernel.QuoteTest.AliasHygiene
assert Kernel.QuoteTest.AliasHygiene.dict == Elixir.Dict.Bar
end
test "expand aliases with macro has higher preference" do
alias HashDict, as: SuperDict, warn: false
require Kernel.QuoteTest.AliasHygiene
assert Kernel.QuoteTest.AliasHygiene.super_dict == Elixir.Dict.Bar
end
end
defmodule Kernel.QuoteTest.ImportsHygieneTest do
use ExUnit.Case, async: true
# We are redefining |> and using it inside the quote
# and only inside the quote. This code should still compile.
defmacro x |> f do
quote do
unquote(x) |> unquote(f)
end
end
defmacrop get_list_length do
quote do
length('hello')
end
end
defmacrop get_list_length_with_partial do
quote do
(&length(&1)).('hello')
end
end
defmacrop get_list_length_with_function do
quote do
(&length/1).('hello')
end
end
test "expand imports" do
import Kernel, except: [length: 1]
assert get_list_length() == 5
assert get_list_length_with_partial() == 5
assert get_list_length_with_function() == 5
end
defmacrop get_string_length do
import Kernel, except: [length: 1]
quote do
length("hello")
end
end
test "lazy expand imports" do
import Kernel, except: [length: 1]
import String, only: [length: 1]
assert get_string_length() == 5
end
test "lazy expand imports no conflicts" do
import Kernel, except: [length: 1]
import String, only: [length: 1]
assert get_list_length() == 5
assert get_list_length_with_partial() == 5
assert get_list_length_with_function() == 5
end
defmacrop with_length do
quote do
import Kernel, except: [length: 1]
import String, only: [length: 1]
length('hello')
end
end
test "explicitly overridden imports" do
assert with_length() == 5
end
defmodule BinaryUtils do
defmacro int32 do
quote do
integer-size(32)
end
end
end
test "checks the context also for variables to zero-arity functions" do
import BinaryUtils
{:int32, meta, __MODULE__} = quote do: int32
assert meta[:import] == BinaryUtils
end
end