1Code.require_file("../test_helper.exs", __DIR__) 2 3defmodule Kernel.TracersTest do 4 use ExUnit.Case 5 6 import Code, only: [compile_string: 1] 7 8 def trace(event, %Macro.Env{} = env) do 9 send(self(), {event, env}) 10 :ok 11 end 12 13 setup_all do 14 Code.put_compiler_option(:tracers, [__MODULE__]) 15 Code.put_compiler_option(:parser_options, columns: true) 16 17 on_exit(fn -> 18 Code.put_compiler_option(:tracers, []) 19 Code.put_compiler_option(:parser_options, []) 20 end) 21 end 22 23 test "traces start and stop" do 24 compile_string(""" 25 Foo 26 """) 27 28 assert_receive {:start, %{lexical_tracker: pid}} when is_pid(pid) 29 assert_receive {:stop, %{lexical_tracker: pid}} when is_pid(pid) 30 end 31 32 test "traces alias references" do 33 compile_string(""" 34 Foo 35 """) 36 37 assert_receive {{:alias_reference, meta, Foo}, _} 38 assert meta[:line] == 1 39 assert meta[:column] == 1 40 end 41 42 test "traces aliases" do 43 compile_string(""" 44 alias Hello.World 45 World 46 47 alias Foo, as: Bar, warn: true 48 Bar 49 """) 50 51 assert_receive {{:alias, meta, Hello.World, World, []}, _} 52 assert meta[:line] == 1 53 assert meta[:column] == 1 54 assert_receive {{:alias_expansion, meta, World, Hello.World}, _} 55 assert meta[:line] == 2 56 assert meta[:column] == 1 57 58 assert_receive {{:alias, meta, Foo, Bar, [as: Bar, warn: true]}, _} 59 assert meta[:line] == 4 60 assert meta[:column] == 1 61 assert_receive {{:alias_expansion, meta, Bar, Foo}, _} 62 assert meta[:line] == 5 63 assert meta[:column] == 1 64 end 65 66 test "traces imports" do 67 compile_string(""" 68 import Integer, only: [is_odd: 1, parse: 1] 69 true = is_odd(1) 70 {1, ""} = parse("1") 71 """) 72 73 assert_receive {{:import, meta, Integer, only: [is_odd: 1, parse: 1]}, _} 74 assert meta[:line] == 1 75 assert meta[:column] == 1 76 77 assert_receive {{:imported_macro, meta, Integer, :is_odd, 1}, _} 78 assert meta[:line] == 2 79 assert meta[:column] == 8 80 81 assert_receive {{:imported_function, meta, Integer, :parse, 1}, _} 82 assert meta[:line] == 3 83 assert meta[:column] == 11 84 end 85 86 test "traces structs" do 87 compile_string(""" 88 %URI{path: "/"} 89 """) 90 91 assert_receive {{:struct_expansion, meta, URI, [:path]}, _} 92 assert meta[:line] == 1 93 assert meta[:column] == 1 94 end 95 96 test "traces remote" do 97 compile_string(""" 98 require Integer 99 true = Integer.is_odd(1) 100 {1, ""} = Integer.parse("1") 101 """) 102 103 assert_receive {{:remote_macro, meta, Integer, :is_odd, 1}, _} 104 assert meta[:line] == 2 105 assert meta[:column] == 16 106 107 assert_receive {{:remote_function, meta, Integer, :parse, 1}, _} 108 assert meta[:line] == 3 109 assert meta[:column] == 19 110 end 111 112 test "traces remote via captures" do 113 compile_string(""" 114 require Integer 115 &Integer.is_odd/1 116 &Integer.parse/1 117 """) 118 119 assert_receive {{:remote_macro, meta, Integer, :is_odd, 1}, _} 120 assert meta[:line] == 2 121 assert meta[:column] == 1 122 123 assert_receive {{:remote_function, meta, Integer, :parse, 1}, _} 124 assert meta[:line] == 3 125 assert meta[:column] == 1 126 end 127 128 test "traces locals" do 129 compile_string(""" 130 defmodule Sample do 131 defmacro foo(arg), do: arg 132 def bar(arg), do: arg 133 def baz(arg), do: foo(arg) + bar(arg) 134 end 135 """) 136 137 assert_receive {{:local_macro, meta, :foo, 1}, _} 138 assert meta[:line] == 4 139 assert meta[:column] == 21 140 141 assert_receive {{:local_function, meta, :bar, 1}, _} 142 assert meta[:line] == 4 143 assert meta[:column] == 32 144 after 145 :code.purge(Sample) 146 :code.delete(Sample) 147 end 148 149 test "traces locals with capture" do 150 compile_string(""" 151 defmodule Sample do 152 defmacro foo(arg), do: arg 153 def bar(arg), do: arg 154 def baz(_), do: {&foo/1, &bar/1} 155 end 156 """) 157 158 assert_receive {{:local_macro, meta, :foo, 1}, _} 159 assert meta[:line] == 4 160 assert meta[:column] == 20 161 162 assert_receive {{:local_function, meta, :bar, 1}, _} 163 assert meta[:line] == 4 164 assert meta[:column] == 28 165 after 166 :code.purge(Sample) 167 :code.delete(Sample) 168 end 169 170 test "traces modules" do 171 compile_string(""" 172 defmodule Sample do 173 :ok 174 end 175 """) 176 177 assert_receive {{:on_module, <<_::binary>>, :none}, %{module: Sample, function: nil}} 178 after 179 :code.purge(Sample) 180 :code.delete(Sample) 181 end 182end 183