1Code.require_file("../../test_helper.exs", __DIR__)
2
3defmodule Mix.Tasks.Profile.CprofTest do
4  use MixTest.Case
5
6  import ExUnit.CaptureIO
7  alias Mix.Tasks.Profile.Cprof
8
9  @expr "Enum.each(1..5, &String.Chars.Integer.to_string/1)"
10
11  test "profiles evaluated expression", context do
12    in_tmp(context.test, fn ->
13      assert capture_io(fn ->
14               Cprof.run(["-e", @expr])
15             end) =~ ~r/String\.Chars\.Integer\.to_string\/1 *\d/
16    end)
17  end
18
19  test "profiles the script", context do
20    in_tmp(context.test, fn ->
21      profile_script_name = "profile_script.ex"
22
23      File.write!(profile_script_name, @expr)
24
25      assert capture_io(fn ->
26               Cprof.run([profile_script_name])
27             end) =~ ~r/String\.Chars\.Integer\.to_string\/1 *\d/
28    end)
29  end
30
31  test "filters based on limit", context do
32    in_tmp(context.test, fn ->
33      refute capture_io(fn ->
34               Cprof.run(["--limit", "5", "-e", @expr])
35             end) =~ ~r/:erlang\.trace_pattern\/3 *\d/
36    end)
37  end
38
39  test "filters based on module", context do
40    in_tmp(context.test, fn ->
41      refute capture_io(fn ->
42               Cprof.run(["--module", "Enum", "-e", @expr])
43             end) =~ ~r/String\.Chars\.Integer\.to_string\/1 *\d/
44    end)
45  end
46
47  test "Module matching", context do
48    in_tmp(context.test, fn ->
49      refute capture_io(fn ->
50               Cprof.run(["--matching", "Enum", "-e", @expr])
51             end) =~ ~r/String\.Chars\.Integer\.to_string\/1 *\d/
52    end)
53  end
54
55  test "Module.function matching", context do
56    in_tmp(context.test, fn ->
57      refute capture_io(fn ->
58               Cprof.run(["--matching", "Enum.each", "-e", @expr])
59             end) =~ ~r/anonymous fn\/3 in Enum\.each\/2 *\d/
60    end)
61  end
62
63  test "Module.function/arity matching", context do
64    in_tmp(context.test, fn ->
65      assert capture_io(fn ->
66               Cprof.run(["--matching", "Enum.each/8", "-e", @expr])
67             end) =~ ~r/Profile done over 0 matching functions/
68    end)
69  end
70
71  test "errors on missing files", context do
72    in_tmp(context.test, fn ->
73      msg = "No files matched pattern \"non-existent\" given to --require"
74
75      assert_raise Mix.Error, msg, fn ->
76        capture_io(fn -> Cprof.run(["-r", "non-existent"]) end)
77      end
78
79      assert_raise Mix.Error, msg, fn ->
80        capture_io(fn -> Cprof.run(["-pr", "non-existent"]) end)
81      end
82
83      assert_raise Mix.Error, "No such file: non-existent", fn ->
84        capture_io(fn -> Cprof.run(["non-existent"]) end)
85      end
86
87      File.mkdir_p!("lib")
88
89      assert_raise Mix.Error, "No such file: lib", fn ->
90        capture_io(fn -> Cprof.run(["lib"]) end)
91      end
92    end)
93  end
94
95  test "warmup", context do
96    in_tmp(context.test, fn ->
97      assert capture_io(fn ->
98               Cprof.run(["-e", @expr])
99             end) =~ "Warmup..."
100
101      refute capture_io(fn ->
102               Cprof.run(["-e", "Enum.each(1..5, fn(_) -> MapSet.new() end)", "--no-warmup"])
103             end) =~ "Warmup..."
104    end)
105  end
106end
107