1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
Code.require_file("../../test_helper.exs", __DIR__)
defmodule Mix.Tasks.Compile.ErlangTest do
use MixTest.Case
import ExUnit.CaptureIO
defmacro position(line, column), do: {line, column}
setup config do
erlc_options = Map.get(config, :erlc_options, [])
Mix.ProjectStack.post_config(erlc_options: erlc_options)
Mix.Project.push(MixTest.Case.Sample)
:ok
end
@tag erlc_options: [{:d, ~c"foo", ~c"bar"}]
test "raises on invalid erlc_options" do
in_fixture("compile_erlang", fn ->
assert_raise Mix.Error, ~r"Compiling Erlang file '.*' failed", fn ->
capture_io(fn ->
Mix.Tasks.Compile.Erlang.run([])
end)
end
end)
end
test "compiles and cleans src/b.erl and src/c.erl" do
in_fixture("compile_erlang", fn ->
assert Mix.Tasks.Compile.Erlang.run(["--verbose"]) == {:ok, []}
assert_received {:mix_shell, :info, ["Compiled src/b.erl"]}
assert_received {:mix_shell, :info, ["Compiled src/c.erl"]}
assert File.regular?("_build/dev/lib/sample/ebin/b.beam")
assert File.regular?("_build/dev/lib/sample/ebin/c.beam")
assert Mix.Tasks.Compile.Erlang.run(["--verbose"]) == {:noop, []}
refute_received {:mix_shell, :info, ["Compiled src/b.erl"]}
assert Mix.Tasks.Compile.Erlang.run(["--force", "--verbose"]) == {:ok, []}
assert_received {:mix_shell, :info, ["Compiled src/b.erl"]}
assert_received {:mix_shell, :info, ["Compiled src/c.erl"]}
assert Mix.Tasks.Compile.Erlang.clean()
refute File.regular?("_build/dev/lib/sample/ebin/b.beam")
refute File.regular?("_build/dev/lib/sample/ebin/c.beam")
end)
end
test "removes old artifact files" do
in_fixture("compile_erlang", fn ->
assert Mix.Tasks.Compile.Erlang.run([]) == {:ok, []}
assert File.regular?("_build/dev/lib/sample/ebin/b.beam")
File.rm!("src/b.erl")
assert Mix.Tasks.Compile.Erlang.run([]) == {:ok, []}
refute File.regular?("_build/dev/lib/sample/ebin/b.beam")
end)
end
test "compilation purges the module" do
in_fixture("compile_erlang", fn ->
# Create the first version of the module.
defmodule :purge_test do
def version, do: :v1
end
assert :v1 == :purge_test.version()
# Create the second version of the module (this time as Erlang source).
File.write!("src/purge_test.erl", """
-module(purge_test).
-export([version/0]).
version() -> v2.
""")
assert Mix.Tasks.Compile.Erlang.run([]) == {:ok, []}
# If the module was not purged on recompilation, this would fail.
assert :v2 == :purge_test.version()
end)
end
test "continues even if one file fails to compile" do
in_fixture("compile_erlang", fn ->
file = Path.absname("src/zzz.erl")
File.write!(file, """
-module(zzz).
def zzz(), do: b
""")
capture_io(fn ->
assert {:error, [diagnostic]} = Mix.Tasks.Compile.Erlang.run([])
assert %Mix.Task.Compiler.Diagnostic{
compiler_name: "erl_parse",
file: ^file,
message: "syntax error before: zzz",
position: position(2, 5),
severity: :error
} = diagnostic
end)
assert File.regular?("_build/dev/lib/sample/ebin/b.beam")
assert File.regular?("_build/dev/lib/sample/ebin/c.beam")
end)
end
test "saves warnings between builds" do
in_fixture("compile_erlang", fn ->
file = Path.absname("src/has_warning.erl")
File.write!(file, """
-module(has_warning).
my_fn() -> ok.
""")
capture_io(fn ->
assert {:ok, [diagnostic]} = Mix.Tasks.Compile.Erlang.run([])
assert %Mix.Task.Compiler.Diagnostic{
file: ^file,
compiler_name: "erl_lint",
message: "function my_fn/0 is unused",
position: position(2, 1),
severity: :warning
} = diagnostic
# Should return warning without recompiling file
assert {:noop, [^diagnostic]} = Mix.Tasks.Compile.Erlang.run(["--verbose"])
refute_received {:mix_shell, :info, ["Compiled src/has_warning.erl"]}
# Should not return warning after changing file
File.write!(file, """
-module(has_warning).
-export([my_fn/0]).
my_fn() -> ok.
""")
ensure_touched(file)
assert {:ok, []} = Mix.Tasks.Compile.Erlang.run([])
end)
end)
end
test "prints warnings from stale files with --all-warnings" do
in_fixture("compile_erlang", fn ->
file = Path.absname("src/has_warning.erl")
File.write!(file, """
-module(has_warning).
my_fn() -> ok.
""")
capture_io(fn -> Mix.Tasks.Compile.Erlang.run([]) end)
output =
capture_io(fn ->
assert {:noop, _} = Mix.Tasks.Compile.Erlang.run(["--all-warnings"])
end)
assert output =~ ~r"src/has_warning.erl:2:(1:)? warning: function my_fn/0 is unused\n"
# Should not print old warnings after fixing
File.write!(file, """
-module(has_warning).
""")
ensure_touched(file)
output =
capture_io(fn ->
Mix.Tasks.Compile.Erlang.run(["--all-warnings"])
end)
assert output == ""
end)
end
@tag erlc_options: [{:warnings_as_errors, true}]
test "adds :debug_info to erlc_options by default" do
in_fixture("compile_erlang", fn ->
Mix.Tasks.Compile.Erlang.run([])
binary = File.read!("_build/dev/lib/sample/ebin/b.beam")
{:ok, {_, [debug_info: {:debug_info_v1, _, {debug_info, _}}]}} =
:beam_lib.chunks(binary, [:debug_info])
assert debug_info != :none
end)
end
end
|