1Code.require_file("../../test_helper.exs", __DIR__)
2
3defmodule Mix.Tasks.App.StartTest do
4  use MixTest.Case
5
6  defmodule AppStartSample do
7    def project do
8      [app: :app_start_sample, version: "0.1.0"]
9    end
10
11    def application do
12      [applications: [:logger]]
13    end
14  end
15
16  test "compiles and starts the project" do
17    in_fixture("no_mixfile", fn ->
18      Mix.Project.push(AppStartSample)
19
20      assert_raise Mix.Error, fn ->
21        Mix.Task.run("app.start", ["--no-compile"])
22      end
23
24      refute List.keyfind(Application.started_applications(), :logger, 0)
25      Application.start(:logger)
26
27      Mix.Task.reenable("app.config")
28      Mix.Task.reenable("app.start")
29      Mix.Task.run("app.start", ["--no-start"])
30      assert File.regular?("_build/dev/lib/app_start_sample/ebin/Elixir.A.beam")
31      assert File.regular?("_build/dev/lib/app_start_sample/ebin/app_start_sample.app")
32
33      assert :code.is_loaded(A)
34      refute List.keyfind(Application.started_applications(), :app_start_sample, 0)
35      assert List.keyfind(Application.started_applications(), :logger, 0)
36      purge([A])
37
38      Mix.Task.reenable("app.config")
39      Mix.Task.reenable("app.start")
40      Mix.Task.run("app.start", [])
41      refute :code.is_loaded(A)
42      assert List.keyfind(Application.started_applications(), :app_start_sample, 0)
43      assert List.keyfind(Application.started_applications(), :logger, 0)
44    end)
45  end
46
47  describe "unit tests" do
48    test "start does nothing if no apps are given" do
49      assert Mix.Tasks.App.Start.start([], :temporary) == :ok
50    end
51
52    test "allows type to be configured" do
53      assert Mix.Tasks.App.Start.type([], permanent: true) == :permanent
54      assert Mix.Tasks.App.Start.type([], temporary: true) == :temporary
55      assert Mix.Tasks.App.Start.type([start_permanent: true], []) == :permanent
56      assert Mix.Tasks.App.Start.type([], []) == :temporary
57    end
58
59    defmodule ReturnSample do
60      def project do
61        [app: :return_sample, version: "0.1.0"]
62      end
63
64      def application do
65        Process.get(:application_definition)
66      end
67    end
68
69    defmodule ReturnApp do
70      use Application
71
72      def start(_type, return), do: return
73    end
74
75    test "start points to report on error", context do
76      in_tmp(context.test, fn ->
77        Mix.Project.push(ReturnSample)
78
79        Process.put(:application_definition, mod: {ReturnApp, {:error, :bye}})
80        Mix.Tasks.Compile.run([])
81
82        message =
83          "Could not start application return_sample: " <>
84            "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, {:error, :bye}) " <>
85            "returned an error: :bye"
86
87        assert_raise Mix.Error, message, fn ->
88          Mix.Tasks.App.Start.start([:return_sample], :temporary)
89        end
90      end)
91    end
92
93    test "start points to report on exception error", context do
94      in_tmp(context.test, fn ->
95        Mix.Project.push(ReturnSample)
96
97        mod = {ReturnApp, {:error, {:badarg, [{ReturnApp, :start, 2, []}]}}}
98        Process.put(:application_definition, mod: mod)
99        Mix.Tasks.Compile.run([])
100
101        message =
102          "Could not start application return_sample: " <>
103            "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, {:error, {:badarg, [{Mix.Tasks.App.StartTest.ReturnApp, :start, 2, []}]}}) " <>
104            "returned an error: an exception was raised:\n" <>
105            "    ** (ArgumentError) argument error\n" <>
106            "        Mix.Tasks.App.StartTest.ReturnApp.start/2"
107
108        assert_raise Mix.Error, message, fn ->
109          Mix.Tasks.App.Start.start([:return_sample], :temporary)
110        end
111      end)
112    end
113
114    test "start points to report on bad return", context do
115      in_tmp(context.test, fn ->
116        Mix.Project.push(ReturnSample)
117
118        Process.put(:application_definition, mod: {ReturnApp, :bad})
119        Mix.Tasks.Compile.run([])
120
121        message =
122          "Could not start application return_sample: " <>
123            "Mix.Tasks.App.StartTest.ReturnApp.start(:normal, :bad) " <>
124            "returned a bad value: :bad"
125
126        assert_raise Mix.Error, message, fn ->
127          Mix.Tasks.App.Start.start([:return_sample], :temporary)
128        end
129      end)
130    end
131
132    defmodule ExitSample do
133      def project do
134        [app: :exit_sample, version: "0.1.0"]
135      end
136
137      def application do
138        Process.get(:application_definition)
139      end
140    end
141
142    defmodule ExitApp do
143      use Application
144
145      def start(_type, reason), do: exit(reason)
146    end
147
148    test "start points to report on exit", context do
149      in_tmp(context.test, fn ->
150        Mix.Project.push(ExitSample)
151
152        Process.put(:application_definition, mod: {ExitApp, :bye})
153        Mix.Tasks.Compile.run([])
154
155        message =
156          "Could not start application exit_sample: exited in: " <>
157            "Mix.Tasks.App.StartTest.ExitApp.start(:normal, :bye)\n" <> "    ** (EXIT) :bye"
158
159        assert_raise Mix.Error, message, fn ->
160          Mix.Tasks.App.Start.start([:exit_sample], :temporary)
161        end
162      end)
163    end
164
165    test "start points to report on normal exit", context do
166      in_tmp(context.test, fn ->
167        Mix.Project.push(ExitSample)
168
169        Process.put(:application_definition, mod: {ExitApp, :normal})
170        Mix.Tasks.Compile.run([])
171
172        message =
173          "Could not start application exit_sample: exited in: " <>
174            "Mix.Tasks.App.StartTest.ExitApp.start(:normal, :normal)\n" <> "    ** (EXIT) normal"
175
176        assert_raise Mix.Error, message, fn ->
177          Mix.Tasks.App.Start.start([:exit_sample], :temporary)
178        end
179      end)
180    end
181  end
182end
183