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

402 lines
10 KiB
Elixir

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2021 The Elixir Team
# SPDX-FileCopyrightText: 2012 Plataformatec
Code.require_file("../test_helper.exs", __DIR__)
defmodule Kernel.TracersTest do
use ExUnit.Case
defp compile_string(string) do
string
|> Code.string_to_quoted!(columns: true)
|> Code.compile_quoted()
end
def trace(event, %Macro.Env{} = env) do
for {pid, _} <- Registry.lookup(__MODULE__, :tracers) do
send(pid, {event, env})
end
:ok
end
setup_all do
start_supervised!({Registry, keys: :duplicate, name: __MODULE__})
Code.put_compiler_option(:tracers, [__MODULE__])
on_exit(fn ->
Code.put_compiler_option(:tracers, [])
end)
end
setup do
Registry.register(__MODULE__, :tracers, :unused)
:ok
end
test "traces start and stop" do
compile_string("""
Foo
""")
assert_received {:start, %{lexical_tracker: pid}} when is_pid(pid)
assert_received {:stop, %{lexical_tracker: pid}} when is_pid(pid)
end
test "traces alias references" do
compile_string("""
Foo
""")
assert_received {{:alias_reference, meta, Foo}, _}
assert meta[:line] == 1
assert meta[:column] == 1
end
test "traces aliases" do
compile_string("""
alias Hello.World
World
alias Foo, as: Bar, warn: true
Bar
""")
assert_received {{:alias, meta, Hello.World, World, []}, _}
assert meta[:line] == 1
assert meta[:column] == 1
assert_received {{:alias_expansion, meta, World, Hello.World}, _}
assert meta[:line] == 2
assert meta[:column] == 1
assert_received {{:alias, meta, Foo, Bar, [as: Bar, warn: true]}, _}
assert meta[:line] == 4
assert meta[:column] == 1
assert_received {{:alias_expansion, meta, Bar, Foo}, _}
assert meta[:line] == 5
assert meta[:column] == 1
end
test "traces imports" do
compile_string("""
import Integer, only: [is_odd: 1, parse: 1]
true = is_odd(1)
{1, ""} = parse("1")
""")
assert_received {{:import, meta, Integer, only: [is_odd: 1, parse: 1]}, _}
assert meta[:line] == 1
assert meta[:column] == 1
assert_received {{:imported_macro, meta, Integer, :is_odd, 1}, _}
assert meta[:line] == 2
assert meta[:column] == 8
assert_received {{:imported_function, meta, Integer, :parse, 1}, _}
assert meta[:line] == 3
assert meta[:column] == 11
refute_received {{:remote_function, _, Integer, :parse, 1}, _}
end
test "traces imports via capture" do
compile_string("""
import Integer, only: [is_odd: 1, parse: 1]
&is_odd/1
&parse/1
""")
assert_received {{:import, meta, Integer, only: [is_odd: 1, parse: 1]}, _}
assert meta[:line] == 1
assert meta[:column] == 1
assert_received {{:imported_macro, meta, Integer, :is_odd, 1}, _}
assert meta[:line] == 2
assert meta[:column] == 2
assert_received {{:imported_function, meta, Integer, :parse, 1}, _}
assert meta[:line] == 3
assert meta[:column] == 2
refute_received {{:remote_function, _meta, Integer, :parse, 1}, _}
end
test "traces structs" do
compile_string("""
%URI{path: "/"}
""")
assert_received {{:struct_expansion, meta, URI, [:path]}, _}
assert meta[:line] == 1
assert meta[:column] == 1
end
test "traces remote" do
compile_string("""
require Integer
true = Integer.is_odd(1)
{1, ""} = Integer.parse("1")
"foo" = Atom.to_string(:foo)
""")
assert_received {{:remote_macro, meta, Integer, :is_odd, 1}, _}
assert meta[:line] == 2
assert meta[:column] == 16
assert_received {{:remote_function, meta, Integer, :parse, 1}, _}
assert meta[:line] == 3
assert meta[:column] == 19
assert_received {{:remote_function, meta, Atom, :to_string, 1}, _}
assert meta[:line] == 4
assert meta[:column] == 14
end
test "traces remote via captures" do
compile_string("""
require Integer
&Integer.is_odd/1
&Integer.parse/1
""")
assert_received {{:remote_macro, meta, Integer, :is_odd, 1}, _}
assert meta[:line] == 2
assert meta[:column] == 10
assert_received {{:remote_function, meta, Integer, :parse, 1}, _}
assert meta[:line] == 3
assert meta[:column] == 10
end
test "traces locals" do
compile_string("""
defmodule Sample do
defmacro foo(arg), do: arg
def bar(arg), do: arg
def baz(arg), do: foo(arg) + bar(arg)
end
""")
assert_received {{:local_macro, meta, :foo, 1}, _}
assert meta[:line] == 4
assert meta[:column] == 21
assert_received {{:local_function, meta, :bar, 1}, _}
assert meta[:line] == 4
assert meta[:column] == 32
after
:code.purge(Sample)
:code.delete(Sample)
end
test "traces locals with capture" do
compile_string("""
defmodule Sample do
defmacro foo(arg), do: arg
def bar(arg), do: arg
def baz(_), do: {&foo/1, &bar/1}
end
""")
assert_received {{:local_macro, meta, :foo, 1}, _}
assert meta[:line] == 4
assert meta[:column] == 21
assert_received {{:local_function, meta, :bar, 1}, _}
assert meta[:line] == 4
assert meta[:column] == 29
after
:code.purge(Sample)
:code.delete(Sample)
end
test "traces modules" do
compile_string("""
defmodule Sample do
:ok
end
""")
assert_received {:defmodule, %{module: Sample, function: nil}}
assert_received {{:on_module, <<_::binary>>, :none}, %{module: Sample, function: nil}}
after
:code.purge(Sample)
:code.delete(Sample)
end
test "traces dynamic modules" do
compile_string("""
Module.create(Sample, :ok, __ENV__)
""")
assert_received {:defmodule, %{module: Sample, function: nil}}
assert_received {{:on_module, <<_::binary>>, :none}, %{module: Sample, function: nil}}
after
:code.purge(Sample)
:code.delete(Sample)
end
test "traces module attribute expansion" do
compile_string("""
defmodule TracersModuleAttribute do
@module URI
@module
end
""")
assert_received {{:alias_reference, [line: 3], URI}, %{file: "@module"}}
end
test "traces string interpolation" do
compile_string("""
arg = 1 + 2
"foo\#{arg}"
""")
assert_received {{:remote_macro, meta, Kernel, :to_string, 1}, _env}
assert meta[:from_interpolation]
end
test "traces bracket access" do
compile_string("""
foo = %{bar: 3}
foo[:bar]
""")
assert_received {{:remote_function, meta, Access, :get, 2}, _env}
assert meta[:from_brackets]
compile_string("""
defmodule TracerBracketAccess do
@foo %{bar: 3}
def a() do
@foo[:bar]
end
end
""")
assert_received {{:remote_function, meta, Access, :get, 2}, _env}
assert meta[:from_brackets]
compile_string("""
%{bar: 3}[:bar]
""")
assert_received {{:remote_function, meta, Access, :get, 2}, _env}
assert meta[:from_brackets]
end
test "traces on_load" do
compile_string("""
defmodule TracerOnLoad do
@on_load :init
def init, do: :ok
end
""")
assert_received {{:local_function, meta, :init, 0}, _}
assert meta[:line] == 1
end
def __before_compile__(_), do: :ok
def __after_compile__(_, _), do: :ok
def __after_verify__(_), do: :ok
def __on_definition__(_, _, _, _, _, _), do: :ok
test "traces compile time attributes" do
compile_string("""
defmodule TracerCompileAttributes do
@before_compile Kernel.TracersTest
@after_compile Kernel.TracersTest
@on_definition Kernel.TracersTest
@after_verify Kernel.TracersTest
def hello, do: :world
end
""")
assert_received {{:remote_function, meta, __MODULE__, :__before_compile__, 1}, _}
assert meta[:line] == 1
assert_received {{:remote_function, meta, __MODULE__, :__after_compile__, 2}, _}
assert meta[:line] == 1
assert_received {{:remote_function, meta, __MODULE__, :__after_verify__, 1}, _}
assert meta[:line] == 1
assert_received {{:remote_function, meta, __MODULE__, :__on_definition__, 6}, _}
assert meta[:line] == 6
end
test "traces super" do
compile_string("""
defmodule TracerOverridable do
def local(x), do: x
defoverridable [local: 1]
def local(x), do: super(x)
defmacro macro(x), do: x
defoverridable [macro: 1]
defmacro macro(x), do: super(x)
def capture(x), do: x
defoverridable [capture: 1]
def capture(x), do: tap(x, &super/1)
def capture_arg(x), do: x
defoverridable [capture_arg: 1]
def capture_arg(x), do: tap(x, &super(&1))
end
""")
assert_received {{:local_function, _, :"local (overridable 1)", 1}, _}
assert_received {{:local_function, _, :"macro (overridable 1)", 1}, _}
assert_received {{:local_function, _, :"capture (overridable 1)", 1}, _}
assert_received {{:local_function, _, :"capture_arg (overridable 1)", 1}, _}
refute_received {{:local_function, _, _, _}, _}
end
test "does not trace bind quoted twice" do
compile_string("""
quote bind_quoted: [foo: List.flatten([])] do
foo
end
""")
assert_received {{:remote_function, _, List, :flatten, 1}, _}
refute_received {{:remote_function, _, List, :flatten, 1}, _}
end
test "does not trace captures twice" do
compile_string("""
&List.flatten/1
""")
assert_received {{:remote_function, _, List, :flatten, 1}, _}
refute_received {{:remote_function, _, List, :flatten, 1}, _}
end
"""
# Make sure this module is compiled with column information
defmodule MacroWithColumn do
defmacro some_macro(list) do
quote do
Enum.map(unquote(list), fn str -> String.upcase(str) end)
end
end
end
"""
|> Code.string_to_quoted!(columns: true)
|> Code.compile_quoted()
test "traces quoted from macro expansion without column information" do
compile_string("""
require MacroWithColumn
MacroWithColumn.some_macro(["hello", "world", "!"])
""")
assert_received {{:alias_reference, meta, Enum}, _env}
refute meta[:column]
end
end