Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:20
connection
connection-1.1.0-git.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File connection-1.1.0-git.patch of Package connection
diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b259b33..585e35f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,43 +1,48 @@ name: CI -on: [push, pull_request] +on: + pull_request: + push: + branches: + - master jobs: test: - name: Test - runs-on: ubuntu-latest - + name: Elixir ${{matrix.pair.elixir}} / OTP ${{matrix.pair.otp}} + runs-on: ubuntu-18.04 + env: + MIX_ENV: test strategy: fail-fast: false matrix: - pair: - - elixir: "1.7.4" - erlang: "19.3" - - elixir: "1.8.2" - erlang: "20.3" - - elixir: "1.9.4" - erlang: "20.3" - - elixir: "1.10.3" - erlang: "21.3" - - elixir: "1.10.3" - erlang: "22.3" - - elixir: "1.11.2" - erlang: "23.1" - + include: + - pair: + elixir: 1.7.4 + otp: 19.3.6.13 + - pair: + elixir: 1.13.3 + otp: 24.2.2 + lint: lint steps: - uses: actions/checkout@v2 - - name: Install OTP and Elixir - uses: actions/setup-elixir@v1 + - uses: erlef/setup-elixir@v1 with: - otp-version: ${{matrix.pair.erlang}} + otp-version: ${{matrix.pair.otp}} elixir-version: ${{matrix.pair.elixir}} - - name: Install dependencies - run: | - mix deps.get - mix deps.compile + - name: Install Dependencies + run: mix deps.get --only test + + - run: mix format --check-formatted + if: ${{ matrix.lint }} + + - run: mix deps.get && mix deps.unlock --check-unused + if: ${{ matrix.lint }} + + - run: mix deps.compile + + - run: mix compile --warnings-as-errors + if: ${{ matrix.lint }} - - name: Run tests - run: | - mix test + - run: mix test diff --git a/.gitignore b/.gitignore index 9607671..98f8244 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /_build /deps +/doc erl_crash.dump *.ez diff --git a/README.md b/README.md index 891d38b..02b3f13 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,17 @@ -Connection -========== +# Connection + +*Note:* with the inclusion of [`gen_statem`](https://www.erlang.org/doc/man/gen_statem.html) +in Erlang/OTP, this project is no longer necessary. See the following pull request as examples +of replacing `Connection` by `gen_statem` in existing projects: + + * https://github.com/elixir-ecto/postgrex/pull/643 + * https://github.com/elixir-ecto/postgrex/pull/644 + * https://github.com/elixir-ecto/db_connection/pull/275 + +We may release new versions if necessary to keep compatibility with Erlang/OTP and +Elixir but otherwise this package is no longer recommended for new projects. + +--- `Connection` behaviour for connection processes. The API is superset of the GenServer API. There are 2 additional callbacks `connect/2` and `disconnect/2`: @@ -43,6 +55,7 @@ GenServer API. There are 2 additional callbacks `connect/2` and `disconnect/2`: @callback terminate(any, any) :: any ``` + There is an example of a simple TCP connection process in `examples/tcp_connection/`. diff --git a/config/config.exs b/config/config.exs deleted file mode 100644 index d2d855e..0000000 --- a/config/config.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/lib/connection.ex b/lib/connection.ex index fcfc038..c9ea852 100644 --- a/lib/connection.ex +++ b/lib/connection.ex @@ -1,5 +1,5 @@ defmodule Connection do - @moduledoc """ + @moduledoc ~S""" A behaviour module for implementing connection processes. The `Connection` behaviour is a superset of the `GenServer` behaviour. The @@ -9,16 +9,17 @@ defmodule Connection do An example `Connection` process: defmodule TCPConnection do - use Connection - def start_link(host, port, opts, timeout \\\\ 5000) do + def start_link(host, port, opts, timeout \\ 5000) do Connection.start_link(__MODULE__, {host, port, opts, timeout}) end - def send(conn, data), do: Connection.call(conn, {:send, data}) + def send(conn, data) do + Connection.call(conn, {:send, data}) + end - def recv(conn, bytes, timeout \\\\ 3000) do + def recv(conn, bytes, timeout \\ 3000) do Connection.call(conn, {:recv, bytes, timeout}) end @@ -29,11 +30,11 @@ defmodule Connection do {:connect, :init, s} end - def connect(_, %{sock: nil, host: host, port: port, opts: opts, - timeout: timeout} = s) do + def connect(_, %{sock: nil, host: host, port: port, opts: opts, timeout: timeout} = s) do case :gen_tcp.connect(host, port, [active: false] ++ opts, timeout) do {:ok, sock} -> {:ok, %{s | sock: sock}} + {:error, _} -> {:backoff, 1000, s} end @@ -41,15 +42,19 @@ defmodule Connection do def disconnect(info, %{sock: sock} = s) do :ok = :gen_tcp.close(sock) + case info do {:close, from} -> Connection.reply(from, :ok) + {:error, :closed} -> :error_logger.format("Connection closed~n", []) + {:error, reason} -> reason = :inet.format_error(reason) :error_logger.format("Connection error: ~s~n", [reason]) end + {:connect, :reconnect, %{s | sock: nil}} end @@ -60,21 +65,26 @@ defmodule Connection do def handle_call({:send, data}, _, %{sock: sock} = s) do case :gen_tcp.send(sock, data) do :ok -> - {:reply, :ok, s} + {:reply, :ok, s} + {:error, _} = error -> {:disconnect, error, error, s} end end + def handle_call({:recv, bytes, timeout}, _, %{sock: sock} = s) do case :gen_tcp.recv(sock, bytes, timeout) do {:ok, _} = ok -> {:reply, ok, s} + {:error, :timeout} = timeout -> {:reply, timeout, s} + {:error, _} = error -> {:disconnect, error, error, s} end end + def handle_call(:close, from, s) do {:disconnect, {:close, from}, s} end @@ -145,11 +155,13 @@ defmodule Connection do entering the loop or calling `terminate/2`. """ @callback init(any) :: - {:ok, any} | {:ok, any, timeout | :hibernate} | - {:connect, any, any} | - {:backoff, timeout, any} | {:backoff, timeout, any, timeout | :hibernate} | - :ignore | {:stop, any} - + {:ok, any} + | {:ok, any, timeout | :hibernate} + | {:connect, any, any} + | {:backoff, timeout, any} + | {:backoff, timeout, any, timeout | :hibernate} + | :ignore + | {:stop, any} @doc """ Called when the process should try to connect. The first argument will either @@ -187,9 +199,11 @@ defmodule Connection do `terminate(reason, state)` before the process exits with reason `reason`. """ @callback connect(any, any) :: - {:ok, any} | {:ok, any, timeout | :hibernate} | - {:backoff, timeout, any} | {:backoff, timeout, any, timeout | :hibernate} | - {:stop, any, any} + {:ok, any} + | {:ok, any, timeout | :hibernate} + | {:backoff, timeout, any} + | {:backoff, timeout, any, timeout | :hibernate} + | {:stop, any, any} @doc """ Called when the process should disconnect. The first argument will either @@ -214,10 +228,12 @@ defmodule Connection do `terminate(reason, state)` before the process exits with reason `reason`. """ @callback disconnect(any, any) :: - {:connect, any, any} | - {:backoff, timeout, any} | {:backoff, timeout, any, timeout | :hibernate} | - {:noconnect, any} | {:noconnect, any, timeout | :hibernate} | - {:stop, any, any} + {:connect, any, any} + | {:backoff, timeout, any} + | {:backoff, timeout, any, timeout | :hibernate} + | {:noconnect, any} + | {:noconnect, any, timeout | :hibernate} + | {:stop, any, any} @doc """ Called when the process receives a call message sent by `call/3`. This @@ -237,11 +253,14 @@ defmodule Connection do or a later callback using `reply/2`. """ @callback handle_call(any, {pid, any}, any) :: - {:reply, any, any} | {:reply, any, any, timeout | :hibernate} | - {:noreply, any} | {:noreply, any, timeout | :hibernate} | - {:disconnect | :connect, any, any, any} | - {:disconnect | :connect, any, any} | - {:stop, any, any} | {:stop, any, any, any} + {:reply, any, any} + | {:reply, any, any, timeout | :hibernate} + | {:noreply, any} + | {:noreply, any, timeout | :hibernate} + | {:disconnect | :connect, any, any, any} + | {:disconnect | :connect, any, any} + | {:stop, any, any} + | {:stop, any, any, any} @doc """ Called when the process receives a cast message sent by `cast/3`. This @@ -254,9 +273,10 @@ defmodule Connection do except `disconnect/2` is called. """ @callback handle_cast(any, any) :: - {:noreply, any} | {:noreply, any, timeout | :hibernate} | - {:disconnect | :connect, any, any} | - {:stop, any, any} + {:noreply, any} + | {:noreply, any, timeout | :hibernate} + | {:disconnect | :connect, any, any} + | {:stop, any, any} @doc """ Called when the process receives a message that is not a call or cast. This @@ -269,9 +289,10 @@ defmodule Connection do except `disconnect/2` is called. """ @callback handle_info(any, any) :: - {:noreply, any} | {:noreply, any, timeout | :hibernate} | - {:disconnect | :connect, any, any} | - {:stop, any, any} + {:noreply, any} + | {:noreply, any, timeout | :hibernate} + | {:disconnect | :connect, any, any} + | {:stop, any, any} @doc """ This callback is the same as the `GenServer` equivalent and is used to change @@ -303,6 +324,7 @@ defmodule Connection do def handle_call(msg, _from, state) do # We do this to trick dialyzer to not complain about non-local returns. reason = {:bad_call, msg} + case :erlang.phash2(1, 1) do 0 -> exit(reason) 1 -> {:stop, reason, state} @@ -318,6 +340,7 @@ defmodule Connection do def handle_cast(msg, state) do # We do this to trick dialyzer to not complain about non-local returns. reason = {:bad_cast, msg} + case :erlang.phash2(1, 1) do 0 -> exit(reason) 1 -> {:stop, reason, state} @@ -337,6 +360,7 @@ defmodule Connection do @doc false def connect(info, state) do reason = {:bad_connect, info} + case :erlang.phash2(1, 1) do 0 -> exit(reason) 1 -> {:stop, reason, state} @@ -346,15 +370,21 @@ defmodule Connection do @doc false def disconnect(info, state) do reason = {:bad_disconnect, info} + case :erlang.phash2(1, 1) do 0 -> exit(reason) 1 -> {:stop, reason, state} end end - defoverridable [init: 1, handle_call: 3, handle_info: 2, - handle_cast: 2, terminate: 2, code_change: 3, - connect: 2, disconnect: 2] + defoverridable init: 1, + handle_call: 3, + handle_info: 2, + handle_cast: 2, + terminate: 2, + code_change: 3, + connect: 2, + disconnect: 2 end end @@ -370,7 +400,7 @@ defmodule Connection do See `GenServer.start_link/3` for more information. """ - @spec start_link(module, any, GenServer.options) :: GenServer.on_start + @spec start_link(module, any, GenServer.options()) :: GenServer.on_start() def start_link(mod, args, opts \\ []) do start(mod, args, opts, :link) end @@ -380,7 +410,7 @@ defmodule Connection do See `start_link/3` for more information. """ - @spec start(module, any, GenServer.options) :: GenServer.on_start + @spec start(module, any, GenServer.options()) :: GenServer.on_start() def start(mod, args, opts \\ []) do start(mod, args, opts, :nolink) end @@ -420,13 +450,16 @@ defmodule Connection do @doc false def init_it(starter, _, name, mod, args, opts) do Process.put(:"$initial_call", {mod, :init, 1}) + try do apply(mod, :init, [args]) catch :exit, reason -> init_stop(starter, name, reason) + :error, reason -> init_stop(starter, name, {reason, __STACKTRACE__}) + :throw, value -> reason = {{:nocatch, value}, __STACKTRACE__} init_stop(starter, name, reason) @@ -434,30 +467,38 @@ defmodule Connection do {:ok, mod_state} -> :proc_lib.init_ack(starter, {:ok, self()}) enter_loop(mod, nil, mod_state, name, opts, :infinity) + {:ok, mod_state, timeout} -> :proc_lib.init_ack(starter, {:ok, self()}) enter_loop(mod, nil, mod_state, name, opts, timeout) + {:connect, info, mod_state} -> :proc_lib.init_ack(starter, {:ok, self()}) enter_connect(mod, info, mod_state, name, opts) + {:backoff, backoff_timeout, mod_state} -> backoff = start_backoff(backoff_timeout) :proc_lib.init_ack(starter, {:ok, self()}) enter_loop(mod, backoff, mod_state, name, opts, :infinity) + {:backoff, backoff_timeout, mod_state, timeout} -> backoff = start_backoff(backoff_timeout) :proc_lib.init_ack(starter, {:ok, self()}) enter_loop(mod, backoff, mod_state, name, opts, timeout) + :ignore -> _ = unregister(name) :proc_lib.init_ack(starter, :ignore) exit(:normal) + {:stop, reason} -> init_stop(starter, name, reason) + other -> init_stop(starter, name, {:bad_return_value, other}) end end + ## :proc_lib callback @doc false @@ -465,15 +506,15 @@ defmodule Connection do args = [mod, backoff, mod_state, name, opts, :infinity] :proc_lib.hibernate(__MODULE__, :enter_loop, args) end + def enter_loop(mod, backoff, mod_state, name, opts, timeout) - when name === self() do - s = %Connection{mod: mod, backoff: backoff, mod_state: mod_state, - raise: nil} + when name === self() do + s = %Connection{mod: mod, backoff: backoff, mod_state: mod_state, raise: nil} :gen_server.enter_loop(__MODULE__, opts, s, timeout) end + def enter_loop(mod, backoff, mod_state, name, opts, timeout) do - s = %Connection{mod: mod, backoff: backoff, mod_state: mod_state, - raise: nil} + s = %Connection{mod: mod, backoff: backoff, mod_state: mod_state, raise: nil} :gen_server.enter_loop(__MODULE__, opts, s, name, timeout) end @@ -492,26 +533,36 @@ defmodule Connection do else {:noreply, mod_state} = noreply -> put_elem(noreply, 1, %{s | mod_state: mod_state}) + {:noreply, mod_state, _} = noreply -> put_elem(noreply, 1, %{s | mod_state: mod_state}) + {:reply, _, mod_state} = reply -> put_elem(reply, 2, %{s | mod_state: mod_state}) + {:reply, _, mod_state, _} = reply -> put_elem(reply, 2, %{s | mod_state: mod_state}) + {:connect, info, mod_state} -> connect(info, mod_state, s) + {:connect, info, reply, mod_state} -> reply(from, reply) connect(info, mod_state, s) + {:disconnect, info, mod_state} -> disconnect(info, mod_state, s) + {:disconnect, info, reply, mod_state} -> reply(from, reply) disconnect(info, mod_state, s) + {:stop, _, mod_state} = stop -> put_elem(stop, 2, %{s | mod_state: mod_state}) + {:stop, _, _, mod_state} = stop -> put_elem(stop, 3, %{s | mod_state: mod_state}) + other -> {:stop, {:bad_return_value, other}, %{s | mod_state: mod_state}} end @@ -523,10 +574,13 @@ defmodule Connection do end @doc false - def handle_info({:timeout, backoff, __MODULE__}, - %{backoff: backoff, mod_state: mod_state} = s) do + def handle_info( + {:timeout, backoff, __MODULE__}, + %{backoff: backoff, mod_state: mod_state} = s + ) do connect(:backoff, mod_state, %{s | backoff: nil}) end + def handle_info(msg, s) do handle_async(:handle_info, msg, s) end @@ -550,12 +604,13 @@ defmodule Connection do apply(mod, :format_status, [:normal, [pdict, mod_state]]) catch _, _ -> - [{:data, [{'State', mod_state}]}] + [{:data, [{~c"State", mod_state}]}] else mod_status -> mod_status end end + def format_status(:terminate, [pdict, %{mod: mod, mod_state: mod_state}]) do try do apply(mod, :format_status, [:terminate, [pdict, mod_state]]) @@ -572,8 +627,10 @@ defmodule Connection do def terminate(reason, %{mod: mod, mod_state: mod_state, raise: nil}) do apply(mod, :terminate, [reason, mod_state]) end + def terminate(stop, %{raise: {class, reason, stack}} = s) do %{mod: mod, mod_state: mod_state} = s + try do apply(mod, :terminate, [stop, mod_state]) catch @@ -582,8 +639,10 @@ defmodule Connection do else _ when stop in [:normal, :shutdown] -> :ok + _ when tuple_size(stop) == 2 and elem(stop, 0) == :shutdown -> :ok + _ -> :erlang.raise(class, reason, stack) end @@ -595,10 +654,13 @@ defmodule Connection do case Keyword.pop(options, :name) do {nil, opts} -> :gen.start(__MODULE__, link, mod, args, opts) + {atom, opts} when is_atom(atom) -> :gen.start(__MODULE__, link, {:local, atom}, mod, args, opts) + {{:global, _} = name, opts} -> :gen.start(__MODULE__, link, name, mod, args, opts) + {{:via, _, _} = name, opts} -> :gen.start(__MODULE__, link, name, mod, args, opts) end @@ -624,25 +686,32 @@ defmodule Connection do :exit, reason -> report_reason = {:EXIT, {reason, __STACKTRACE__}} enter_terminate(mod, mod_state, name, reason, report_reason) + :error, reason -> reason = {reason, __STACKTRACE__} enter_terminate(mod, mod_state, name, reason, {:EXIT, reason}) + :throw, value -> reason = {{:nocatch, value}, __STACKTRACE__} enter_terminate(mod, mod_state, name, reason, {:EXIT, reason}) else {:ok, mod_state} -> enter_loop(mod, nil, mod_state, name, opts, :infinity) + {:ok, mod_state, timeout} -> enter_loop(mod, nil, mod_state, name, opts, timeout) + {:backoff, backoff_timeout, mod_state} -> backoff = start_backoff(backoff_timeout) enter_loop(mod, backoff, mod_state, name, opts, :infinity) + {:backoff, backoff_timeout, mod_state, timeout} -> backoff = start_backoff(backoff_timeout) enter_loop(mod, backoff, mod_state, name, opts, timeout) + {:stop, reason, mod_state} -> enter_terminate(mod, mod_state, name, reason, {:stop, reason}) + other -> reason = {:bad_return_value, other} enter_terminate(mod, mod_state, name, reason, {:stop, reason}) @@ -656,9 +725,11 @@ defmodule Connection do :exit, reason -> report_reason = {:EXIT, {reason, __STACKTRACE__}} enter_stop(mod, mod_state, name, reason, report_reason) + :error, reason -> reason = {reason, __STACKTRACE__} enter_stop(mod, mod_state, name, reason, {:EXIT, reason}) + :throw, value -> reason = {{:nocatch, value}, __STACKTRACE__} enter_stop(mod, mod_state, name, reason, {:EXIT, reason}) @@ -670,17 +741,21 @@ defmodule Connection do defp enter_stop(_, _, _, :normal, {:stop, :normal}), do: exit(:normal) defp enter_stop(_, _, _, :shutdown, {:stop, :shutdown}), do: exit(:shutdown) - defp enter_stop(_, _, _, {:shutdown, reason} = shutdown, - {:stop, {:shutdown, reason}}) do - exit(shutdown) + + defp enter_stop(_, _, _, {:shutdown, reason} = shutdown, {:stop, {:shutdown, reason}}) do + exit(shutdown) end + defp enter_stop(mod, mod_state, name, reason, {_, reason2}) do s = %{mod: mod, backoff: nil, mod_state: mod_state} mod_state = format_status(:terminate, [Process.get(), s]) - format = '** Generic server ~p terminating \n' ++ - '** Last message in was ~p~n' ++ ## No last message - '** When Server state == ~p~n' ++ - '** Reason for termination == ~n** ~p~n' + ## No last message + format = + ~c"** Generic server ~p terminating \n" ++ + ~c"** Last message in was ~p~n" ++ + ~c"** When Server state == ~p~n" ++ + ~c"** Reason for termination == ~n** ~p~n" + args = [report_name(name), nil, mod_state, report_reason(reason2)] :error_logger.format(format, args) exit(reason) @@ -695,12 +770,15 @@ defmodule Connection do cond do :code.is_loaded(mod) === false -> {:"module could not be loaded", stack} + not function_exported?(mod, fun, length(args)) -> {:"function not exported", stack} + true -> reason end end + defp report_reason(reason) do reason end @@ -708,18 +786,22 @@ defmodule Connection do ## backoff helpers defp start_backoff(:infinity), do: nil + defp start_backoff(timeout) do :erlang.start_timer(timeout, self(), __MODULE__) end defp cancel_backoff(%{backoff: nil} = s), do: s + defp cancel_backoff(%{backoff: backoff} = s) do case :erlang.cancel_timer(backoff) do false -> flush_backoff(backoff) + _ -> :ok end + %{s | backoff: nil} end @@ -737,6 +819,7 @@ defmodule Connection do defp connect(info, mod_state, %{mod: mod} = s) do s = cancel_backoff(s) + try do apply(mod, :connect, [info, mod_state]) catch @@ -746,16 +829,21 @@ defmodule Connection do else {:ok, mod_state} -> {:noreply, %{s | mod_state: mod_state}} + {:ok, mod_state, timeout} -> {:noreply, %{s | mod_state: mod_state}, timeout} + {:backoff, backoff_timeout, mod_state} -> backoff = start_backoff(backoff_timeout) {:noreply, %{s | backoff: backoff, mod_state: mod_state}} + {:backoff, backoff_timeout, mod_state, timeout} -> backoff = start_backoff(backoff_timeout) {:noreply, %{s | backoff: backoff, mod_state: mod_state}, timeout} + {:stop, _, mod_state} = stop -> put_elem(stop, 2, %{s | mod_state: mod_state}) + other -> {:stop, {:bad_return_value, other}, %{s | mod_state: mod_state}} end @@ -763,6 +851,7 @@ defmodule Connection do defp disconnect(info, mod_state, %{mod: mod} = s) do s = cancel_backoff(s) + try do apply(mod, :disconnect, [info, mod_state]) catch @@ -772,18 +861,24 @@ defmodule Connection do else {:connect, info, mod_state} -> connect(info, mod_state, s) + {:noconnect, mod_state} -> {:noreply, %{s | mod_state: mod_state}} + {:noconnect, mod_state, timeout} -> {:noreply, %{s | mod_state: mod_state}, timeout} + {:backoff, backoff_timeout, mod_state} -> backoff = start_backoff(backoff_timeout) {:noreply, %{s | backoff: backoff, mod_state: mod_state}} + {:backoff, backoff_timeout, mod_state, timeout} -> backoff = start_backoff(backoff_timeout) {:noreply, %{s | backoff: backoff, mod_state: mod_state}, timeout} + {:stop, _, mod_state} = stop -> put_elem(stop, 2, %{s | mod_state: mod_state}) + other -> {:stop, {:bad_return_value, other}, %{s | mod_state: mod_state}} end @@ -797,13 +892,14 @@ defmodule Connection do defp callback_stop(:throw, value, stack, s) do callback_stop(:error, {:nocatch, value}, stack, s) end + defp callback_stop(class, reason, stack, s) do raise = {class, reason, stack} {:stop, stop_reason(class, reason, stack), %{s | raise: raise}} end defp stop_reason(:error, reason, stack), do: {reason, stack} - defp stop_reason(:exit, reason, _), do: reason + defp stop_reason(:exit, reason, _), do: reason defp handle_async(fun, msg, %{mod: mod, mod_state: mod_state} = s) do try do @@ -814,14 +910,19 @@ defmodule Connection do else {:noreply, mod_state} = noreply -> put_elem(noreply, 1, %{s | mod_state: mod_state}) + {:noreply, mod_state, _} = noreply -> put_elem(noreply, 1, %{s | mod_state: mod_state}) + {:connect, info, mod_state} -> connect(info, mod_state, s) + {:disconnect, info, mod_state} -> disconnect(info, mod_state, s) + {:stop, _, mod_state} = stop -> put_elem(stop, 2, %{s | mod_state: mod_state}) + other -> {:stop, {:bad_return_value, other}, %{s | mod_state: mod_state}} end diff --git a/mix.exs b/mix.exs index ffb0367..c7dcce4 100644 --- a/mix.exs +++ b/mix.exs @@ -8,8 +8,8 @@ defmodule Connection.Mixfile do app: :connection, version: @version, elixir: "~> 1.7", - build_embedded: Mix.env == :prod, - start_permanent: Mix.env == :prod, + build_embedded: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, description: description(), package: package(), docs: docs(), @@ -46,7 +46,7 @@ defmodule Connection.Mixfile do defp package do %{ licenses: ["Apache 2.0"], - links: %{"Github" => "https://github.com/elixir-ecto/connection"} + links: %{"GitHub" => "https://github.com/elixir-ecto/connection"} } end end diff --git a/mix.lock b/mix.lock index 5978754..e2a26ce 100644 --- a/mix.lock +++ b/mix.lock @@ -1,8 +1,8 @@ %{ - "earmark": {:hex, :earmark, "1.0.1", "2c2cd903bfdc3de3f189bd9a8d4569a075b88a8981ded9a0d95672f6e2b63141", [:mix], [], "hexpm", "db7b13d74a9edc54d3681762154d164d4a661cd27673cca80760344449877664"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"}, - "ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"}, - "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.30", "0b938aa5b9bafd455056440cdaa2a79197ca5e693830b4a982beada840513c5f", [:mix], [], "hexpm", "3b5385c2d36b0473d0b206927b841343d25adb14f95f0110062506b300cd5a1b"}, + "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, } diff --git a/test/connection_test.exs b/test/connection_test.exs index cb01033..664d442 100644 --- a/test/connection_test.exs +++ b/test/connection_test.exs @@ -10,23 +10,26 @@ defmodule ConnectionTest do assert Sample.init(:my_state) == {:ok, :my_state} assert catch_exit(Sample.connect(:my_info, nil)) == {:bad_connect, :my_info} + assert catch_exit(Sample.disconnect(:my_info, nil)) == - {:bad_disconnect, :my_info} + {:bad_disconnect, :my_info} + assert catch_exit(Sample.handle_call(:my_call, {self(), make_ref()}, nil)) == - {:bad_call, :my_call} + {:bad_call, :my_call} + assert catch_exit(Sample.handle_cast(:my_cast, nil)) == - {:bad_cast, :my_cast} + {:bad_cast, :my_cast} + assert Sample.handle_info(:my_msg, nil) == {:noreply, nil} assert Sample.terminate(:my_reason, nil) assert Sample.code_change(:vsn, :my_state, :extra) == {:ok, :my_state} - after :code.purge(Sample) :code.delete(Sample) end test "init {:ok, state}" do - fun = fn() -> {:ok, 1} end + fun = fn -> {:ok, 1} end assert {:ok, pid} = Connection.start_link(EvalConn, fun) assert Connection.call(pid, :state) === 1 end @@ -34,55 +37,66 @@ defmodule ConnectionTest do test "init {:ok, state, timeout}" do parent = self() - fun = fn() -> - timeout = fn() -> + fun = fn -> + timeout = fn -> send(parent, 1) {:noreply, 2} end + {:ok, timeout, 0} end + assert {:ok, _} = Connection.start_link(EvalConn, fun) assert_receive 1 - end test "init {:ok, state, :hibernate}" do - fun = fn() -> + fun = fn -> {:ok, 1, :hibernate} end + assert {:ok, pid} = Connection.start_link(EvalConn, fun) :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 1 end test "init {:backoff, timeout, state}" do parent = self() - fun = fn() -> - connect = fn() -> + + fun = fn -> + connect = fn -> send(parent, :backoff) {:ok, :backed_off} end + {:backoff, 0, connect} end + {:ok, _} = Connection.start_link(EvalConn, fun) assert_receive :backoff end test "init {:backoff, timeout, state, timeout}" do parent = self() - fun = fn() -> - timeout = fn() -> - connect = fn() -> + + fun = fn -> + timeout = fn -> + connect = fn -> send(parent, :backoff) {:ok, :backed_off} end + send(parent, :timeout) {:noreply, connect} end + {:backoff, 20, timeout, 0} end + {:ok, _} = Connection.start_link(EvalConn, fun) assert_receive :timeout assert_receive :backoff @@ -90,42 +104,51 @@ defmodule ConnectionTest do test "init {:backoff, timeout, state, :hibernate}" do parent = self() - fun = fn() -> - connect = fn() -> + + fun = fn -> + connect = fn -> send(parent, :backoff) {:ok, :backed_off} end + {:backoff, 150, connect, :hibernate} end + {:ok, pid} = Connection.start_link(EvalConn, fun) :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert_receive :backoff end test "init :ignore" do _ = Process.flag(:trap_exit, true) - fun = fn() -> :ignore end - assert Connection.start_link(EvalConn, fun, [name: EvalConn]) === :ignore + fun = fn -> :ignore end + assert Connection.start_link(EvalConn, fun, name: EvalConn) === :ignore assert Process.whereis(EvalConn) === nil assert_receive {:EXIT, _, :normal} end test "init {:stop, reason}" do _ = Process.flag(:trap_exit, true) - fun = fn() -> {:stop, :normal} end - assert Connection.start_link(EvalConn, fun, - [name: {:global, {EvalConn, :stop}}]) === {:error, :normal} + fun = fn -> {:stop, :normal} end + + assert Connection.start_link(EvalConn, fun, name: {:global, {EvalConn, :stop}}) === + {:error, :normal} + assert :global.whereis_name({EvalConn, :stop}) === :undefined assert_receive {:EXIT, _, :normal} end test "init exit" do _ = Process.flag(:trap_exit, true) - fun = fn() -> exit(:normal) end - assert Connection.start_link(EvalConn, fun, - [name: {:via, :global, {EvalConn, :exit}}]) === {:error, :normal} + fun = fn -> exit(:normal) end + + assert Connection.start_link(EvalConn, fun, name: {:via, :global, {EvalConn, :exit}}) === + {:error, :normal} + assert :global.whereis_name({EvalConn, :exit}) === :undefined assert_receive {:EXIT, _, :normal} end @@ -133,9 +156,11 @@ defmodule ConnectionTest do test "init error" do _ = Process.flag(:trap_exit, true) {:current_stacktrace, stack} = Process.info(self(), :current_stacktrace) - fun = fn() -> :erlang.raise(:error, :oops, stack) end - assert Connection.start_link(EvalConn, fun, - [name: {:global, {EvalConn, :error}}]) === {:error, {:oops, stack}} + fun = fn -> :erlang.raise(:error, :oops, stack) end + + assert Connection.start_link(EvalConn, fun, name: {:global, {EvalConn, :error}}) === + {:error, {:oops, stack}} + assert :global.whereis_name({EvalConn, :error}) === :undefined assert_receive {:EXIT, _, {:oops, ^stack}} end @@ -143,34 +168,40 @@ defmodule ConnectionTest do test "init throw" do _ = Process.flag(:trap_exit, true) {:current_stacktrace, stack} = Process.info(self(), :current_stacktrace) - fun = fn() -> :erlang.raise(:throw, :oops, stack) end - assert Connection.start_link(EvalConn, fun, - [name: {:global, {EvalConn, :throw}}]) === - {:error, {{:nocatch, :oops}, stack}} + fun = fn -> :erlang.raise(:throw, :oops, stack) end + + assert Connection.start_link(EvalConn, fun, name: {:global, {EvalConn, :throw}}) === + {:error, {{:nocatch, :oops}, stack}} + assert :global.whereis_name({EvalConn, :throw}) === :undefined assert_receive {:EXIT, _, {{:nocatch, :oops}, ^stack}} end test "connect {:ok, state}" do parent = self() - fun = fn() -> - connect = fn(n) -> + + fun = fn -> + connect = fn n -> send(parent, {:connect, n}) - {:ok, n+1} + {:ok, n + 1} end + {:connect, connect, 1} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} assert Connection.call(pid, :state) === 2 - fun = fn() -> - connect = fn() -> + fun = fn -> + connect = fn -> send(parent, {:connect, 1}) {:ok, 2} end + {:backoff, 0, connect} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} assert Connection.call(pid, :state) === 2 @@ -178,33 +209,42 @@ defmodule ConnectionTest do test "connect {:ok, state, timeout}" do parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - timeout = fn() -> - send(parent, {:timeout, n+1}) - {:noreply, n+2} + + timeout = fn -> + send(parent, {:timeout, n + 1}) + {:noreply, n + 2} end + {:ok, timeout, 0} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} assert_receive {:timeout, 2} assert Connection.call(pid, :state) === 3 - connect = fn() -> + connect = fn -> send(parent, {:connect, 1}) - timeout = fn() -> + + timeout = fn -> send(parent, {:timeout, 2}) {:noreply, 3} end + {:ok, timeout, 0} end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} assert_receive {:timeout, 2} @@ -213,249 +253,306 @@ defmodule ConnectionTest do test "connect {:ok, state, :hibernate}" do parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - {:ok, n+1, :hibernate} + {:ok, n + 1, :hibernate} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 - connect = fn() -> + connect = fn -> send(parent, {:connect, 1}) {:ok, 2, :hibernate} end - fun = fn() -> - {:backoff, 0 , connect} + + fun = fn -> + {:backoff, 0, connect} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:connect, 1} :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 end test "connect {:stop, {:shutdown, _}, state}" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end - {:stop, {:shutdown, terminate}, n+1} + + {:stop, {:shutdown, terminate}, n + 1} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:EXIT, ^pid, {:shutdown, _}} - Logger.flush() - end) == "" + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:EXIT, ^pid, {:shutdown, _}} + Logger.flush() + end) == "" - connect = fn() -> + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + {:stop, {:shutdown, terminate}, 2} end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:EXIT, ^pid, {:shutdown, _}} - Logger.flush() - end) == "" + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:EXIT, ^pid, {:shutdown, _}} + Logger.flush() + end) == "" end test "connect exit({:shutdown, _})" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + exit({:shutdown, terminate}) end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 1} - assert_receive {:EXIT, ^pid, {:shutdown, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*\(stop\) shutdown: #Function.*State: 1"sm - connect = fn() -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 1} + assert_receive {:EXIT, ^pid, {:shutdown, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*\(stop\) shutdown: #Function.*State: 1"sm + + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + exit({:shutdown, terminate}) end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, ^connect} - assert_receive {:EXIT, ^pid, {:shutdown, _}} - Logger.flush() - end) == "" + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, ^connect} + assert_receive {:EXIT, ^pid, {:shutdown, _}} + Logger.flush() + end) == "" end test "connect {:stop, {:abnormal, _}, state}" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end - {:stop, {:abnormal, terminate}, n+1} + + {:stop, {:abnormal, terminate}, n + 1} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:EXIT, ^pid, {:abnormal, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm - connect = fn() -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:EXIT, ^pid, {:abnormal, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm + + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + {:stop, {:abnormal, terminate}, 2} end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:EXIT, ^pid, {:abnormal, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:EXIT, ^pid, {:abnormal, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm end test "connect -> exit({:abnormal, _})" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + exit({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 1} - assert_receive {:EXIT, ^pid, {:abnormal, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 1"sm - connect = fn() -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 1} + assert_receive {:EXIT, ^pid, {:abnormal, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 1"sm + + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + exit({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, ^connect} - assert_receive {:EXIT, ^pid, {:abnormal, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: #Function"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, ^connect} + assert_receive {:EXIT, ^pid, {:abnormal, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: #Function"sm end test "connect -> throw({:abnormal, _})" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + throw({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 1} - assert_receive {:EXIT, ^pid, {{:nocatch, {:abnormal, _}}, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:nocatch, {:abnormal,.*State: 1"sm - connect = fn() -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 1} + assert_receive {:EXIT, ^pid, {{:nocatch, {:abnormal, _}}, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:nocatch, {:abnormal,.*State: 1"sm + + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + throw({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, ^connect} - assert_receive {:EXIT, ^pid, {{:nocatch, {:abnormal, _}}, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:nocatch, {:abnormal,.*State: #Function"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, ^connect} + assert_receive {:EXIT, ^pid, {{:nocatch, {:abnormal, _}}, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:nocatch, {:abnormal,.*State: #Function"sm end test "disconnect {:noconnect, state}" do parent = self() - disconnect = fn(n) -> - send(parent, {:disconnect, n}) - {:noconnect, n+1} - end - fun = fn() -> - timeout = fn() -> + + disconnect = fn n -> + send(parent, {:disconnect, n}) + {:noconnect, n + 1} + end + + fun = fn -> + timeout = fn -> send(parent, {:timeout, 1}) {:disconnect, disconnect, 2} end + {:ok, timeout, 0} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:timeout, 1} assert_receive {:disconnect, 2} @@ -464,21 +561,26 @@ defmodule ConnectionTest do test "disconnect {:noconnect, state, timeout}" do parent = self() - disconnect = fn(n) -> - timeout2 = fn() -> - send(parent, {:timeout, n+1}) - {:noreply, n+2} + + disconnect = fn n -> + timeout2 = fn -> + send(parent, {:timeout, n + 1}) + {:noreply, n + 2} end + send(parent, {:disconnect, n}) {:noconnect, timeout2, 0} end - fun = fn() -> - timeout = fn() -> + + fun = fn -> + timeout = fn -> send(parent, {:timeout, 1}) {:disconnect, disconnect, 2} end + {:ok, timeout, 0} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:timeout, 1} assert_receive {:disconnect, 2} @@ -488,180 +590,216 @@ defmodule ConnectionTest do test "disconnect {:noconnect, state, :hibernate}" do parent = self() - disconnect = fn(n) -> + + disconnect = fn n -> send(parent, {:disconnect, n}) - {:noconnect, n+1, :hibernate} + {:noconnect, n + 1, :hibernate} end - fun = fn() -> - timeout = fn() -> + + fun = fn -> + timeout = fn -> send(parent, {:timeout, 1}) {:disconnect, disconnect, 2} end + {:ok, timeout, 0} end + {:ok, pid} = Connection.start_link(EvalConn, fun) assert_receive {:timeout, 1} assert_receive {:disconnect, 2} :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 3 end test "disconnect {:stop, {:shutdown, _}, state}" do _ = Process.flag(:trap_exit, true) parent = self() - disconnect = fn(n) -> + + disconnect = fn n -> send(parent, {:disconnect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end - {:stop, {:shutdown, terminate}, n+1} + + {:stop, {:shutdown, terminate}, n + 1} end - fun = fn() -> - timeout = fn() -> + + fun = fn -> + timeout = fn -> send(parent, {:timeout, 1}) {:disconnect, disconnect, 2} end + {:ok, timeout, 0} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:timeout, 1} - assert_receive {:disconnect, 2} - assert_receive {:terminate, 3} - assert_receive {:EXIT, ^pid, {:shutdown, _}} - Logger.flush() - end) == "" + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:timeout, 1} + assert_receive {:disconnect, 2} + assert_receive {:terminate, 3} + assert_receive {:EXIT, ^pid, {:shutdown, _}} + Logger.flush() + end) == "" end test "disconnect -> exit({:abnormal, _})" do _ = Process.flag(:trap_exit, true) parent = self() - disconnect = fn(n) -> + + disconnect = fn n -> send(parent, {:disconnect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + exit({:abnormal, terminate}) end - fun = fn() -> - timeout = fn() -> + + fun = fn -> + timeout = fn -> send(parent, {:timeout, 1}) {:disconnect, disconnect, 2} end + {:ok, timeout, 0} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:timeout, 1} - assert_receive {:disconnect, 2} - assert_receive {:terminate, 2} - assert_receive {:EXIT, ^pid, {:abnormal, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:timeout, 1} + assert_receive {:disconnect, 2} + assert_receive {:terminate, 2} + assert_receive {:EXIT, ^pid, {:abnormal, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 2"sm end test "init -> connect -> :erlang.error({:abnormal, _})" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + + connect = fn n -> send(parent, {:connect, n}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + :erlang.error({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 1} - assert_receive {:EXIT, ^pid, {{:abnormal, _}, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 1"sm - connect = fn() -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 1} + assert_receive {:EXIT, ^pid, {{:abnormal, _}, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: 1"sm + + connect = fn -> send(parent, {:connect, 1}) - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) end + :erlang.error({:abnormal, terminate}) end - fun = fn() -> + + fun = fn -> {:backoff, 0, connect} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, ^connect} - assert_receive {:EXIT, ^pid, {{:abnormal, _}, _}} - Logger.flush() - end) =~ ~r"error.*GenServer.*{:abnormal,.*State: #Function"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, ^connect} + assert_receive {:EXIT, ^pid, {{:abnormal, _}, _}} + Logger.flush() + end) =~ ~r"error.*GenServer.*{:abnormal,.*State: #Function"sm end test "init -> connect -> terminate exit({:shutdown, _})" do _ = Process.flag(:trap_exit, true) parent = self() - connect = fn(n) -> + connect = fn n -> send(parent, {:connect, n}) - format_status = fn(m) -> + + format_status = fn m -> send(parent, {:format_status, m}) - m+1 + m + 1 end - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) Process.put(:format_status, format_status) exit({:shutdown, :terminate}) end - {:stop, {:shutdown, terminate}, n+1} + + {:stop, {:shutdown, terminate}, n + 1} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:format_status, 2} - assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} - Logger.flush() - end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 3"sm - connect = fn(n) -> + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:format_status, 2} + assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} + Logger.flush() + end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 3"sm + + connect = fn n -> send(parent, {:connect, n}) - format_status = fn(m) -> + + format_status = fn m -> send(parent, {:format_status, m}) exit(:oops) end - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) Process.put(:format_status, format_status) exit({:shutdown, :terminate}) end - {:stop, {:shutdown, terminate}, n+1} + + {:stop, {:shutdown, terminate}, n + 1} end - fun = fn() -> + + fun = fn -> {:connect, connect, 1} end - assert capture_io(:user, fn() -> - {:ok, pid} = Connection.start_link(EvalConn, fun) - assert_receive {:connect, 1} - assert_receive {:terminate, 2} - assert_receive {:format_status, 2} - assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} - Logger.flush() - end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 2"sm + + assert capture_io(:user, fn -> + {:ok, pid} = Connection.start_link(EvalConn, fun) + assert_receive {:connect, 1} + assert_receive {:terminate, 2} + assert_receive {:format_status, 2} + assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} + Logger.flush() + end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 2"sm end test "handle call {:reply, reply, state}" do {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(_, n) -> {:reply, n, n+1} end + fun = fn _, n -> {:reply, n, n + 1} end assert Connection.call(pid, fun) === 1 assert Connection.call(pid, :state) === 2 end @@ -670,13 +808,16 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(_, n) -> - timeout = fn() -> + + fun = fn _, n -> + timeout = fn -> send(parent, {:timeout, n}) - {:noreply, n+1} + {:noreply, n + 1} end + {:reply, n, timeout, 0} end + assert Connection.call(pid, fun) === 1 assert_receive {:timeout, 1} end @@ -684,10 +825,11 @@ defmodule ConnectionTest do test "handle call {:noreply, state}" do {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(from, n) -> + fun = fn from, n -> Connection.reply(from, n) - {:noreply, n+1} + {:noreply, n + 1} end + assert Connection.call(pid, fun) === 1 assert Connection.call(pid, :state) === 2 end @@ -697,14 +839,16 @@ defmodule ConnectionTest do parent = self() - fun = fn(from, n) -> - timeout = fn() -> + fun = fn from, n -> + timeout = fn -> send(parent, {:timeout, n}) - {:noreply, n+1} + {:noreply, n + 1} end + Connection.reply(from, n) {:noreply, timeout, 0} end + assert Connection.call(pid, fun) === 1 assert_receive {:timeout, 1} end @@ -712,25 +856,30 @@ defmodule ConnectionTest do test "handle call {:reply, reply, state, :hibernate}" do {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(_, n) -> {:reply, n, n+1, :hibernate} end + fun = fn _, n -> {:reply, n, n + 1, :hibernate} end assert Connection.call(pid, fun) === 1 :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 end test "handle call {:noreply, state, :hibernate}" do {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(from, n) -> + fun = fn from, n -> Connection.reply(from, n) - {:noreply, n+1, :hibernate} + {:noreply, n + 1, :hibernate} end + assert Connection.call(pid, fun) === 1 :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 end @@ -738,13 +887,16 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(_, n) -> - connect = fn(m) -> + + fun = fn _, n -> + connect = fn m -> send(parent, {:connect, m}) - {:ok, m+1} + {:ok, m + 1} end - {:connect, connect, n, n+1} + + {:connect, connect, n, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:connect, 2} end @@ -753,14 +905,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(from, n) -> - connect = fn(m) -> + + fun = fn from, n -> + connect = fn m -> send(parent, {:connect, m}) - {:ok, m+1} + {:ok, m + 1} end + Connection.reply(from, n) - {:connect, connect, n+1} + {:connect, connect, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:connect, 2} end @@ -769,13 +924,16 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(_, n) -> - disconnect = fn(m) -> + + fun = fn _, n -> + disconnect = fn m -> send(parent, {:disconnect, m}) - {:noconnect, m+1} + {:noconnect, m + 1} end - {:disconnect, disconnect, n, n+1} + + {:disconnect, disconnect, n, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:disconnect, 2} end @@ -784,14 +942,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(from, n) -> - disconnect = fn(m) -> + + fun = fn from, n -> + disconnect = fn m -> send(parent, {:disconnect, m}) - {:noconnect, m+1} + {:noconnect, m + 1} end + Connection.reply(from, n) - {:disconnect, disconnect, n+1} + {:disconnect, disconnect, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:disconnect, 2} end @@ -801,12 +962,15 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(_, n) -> - terminate = fn(m) -> + + fun = fn _, n -> + terminate = fn m -> send(parent, {:terminate, m}) end - {:stop, {:shutdown, terminate}, n, n+1} + + {:stop, {:shutdown, terminate}, n, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:terminate, 2} assert_receive {:EXIT, ^pid, {:shutdown, _}} @@ -817,13 +981,16 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(from, n) -> - terminate = fn(m) -> + + fun = fn from, n -> + terminate = fn m -> send(parent, {:terminate, m}) end + Connection.reply(from, n) - {:stop, {:shutdown, terminate}, n+1} + {:stop, {:shutdown, terminate}, n + 1} end + assert Connection.call(pid, fun) === 1 assert_receive {:terminate, 2} assert_receive {:EXIT, ^pid, {:shutdown, _}} @@ -833,10 +1000,12 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> + + fun = fn n -> send(parent, n) - {:noreply, n+1} + {:noreply, n + 1} end + assert Connection.cast(pid, fun) === :ok assert_receive 1 assert Connection.call(pid, :state) == 2 @@ -846,14 +1015,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - timeout = fn() -> - send(parent, {:timeout, n+1}) - {:noreply, n+1} + + fun = fn n -> + timeout = fn -> + send(parent, {:timeout, n + 1}) + {:noreply, n + 1} end + send(parent, n) {:noreply, timeout, 0} end + Connection.cast(pid, fun) assert_receive 1 assert_receive {:timeout, 2} @@ -863,15 +1035,19 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> + + fun = fn n -> send(parent, n) - {:noreply, n+1, :hibernate} + {:noreply, n + 1, :hibernate} end + Connection.cast(pid, fun) assert_receive 1 :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 end @@ -879,14 +1055,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - connect = fn(m) -> + + fun = fn n -> + connect = fn m -> send(parent, {:connect, m}) - {:ok, m+1} + {:ok, m + 1} end + send(parent, n) - {:connect, connect, n+1} + {:connect, connect, n + 1} end + Connection.cast(pid, fun) assert_receive 1 assert_receive {:connect, 2} @@ -896,14 +1075,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - disconnect = fn(m) -> + + fun = fn n -> + disconnect = fn m -> send(parent, {:disconnect, m}) - {:noconnect, m+1} + {:noconnect, m + 1} end + send(parent, n) - {:disconnect, disconnect, n+1} + {:disconnect, disconnect, n + 1} end + Connection.cast(pid, fun) assert_receive 1 assert_receive {:disconnect, 2} @@ -914,13 +1096,16 @@ defmodule ConnectionTest do _ = Process.flag(:trap_exit, true) parent = self() - fun = fn(n) -> - terminate = fn(m) -> + + fun = fn n -> + terminate = fn m -> send(parent, {:terminate, m}) end + send(parent, n) - {:stop, {:shutdown, terminate}, n+1} + {:stop, {:shutdown, terminate}, n + 1} end + Connection.cast(pid, fun) assert_receive 1 assert_receive {:terminate, 2} @@ -931,10 +1116,12 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> + + fun = fn n -> send(parent, n) - {:noreply, n+1} + {:noreply, n + 1} end + send(pid, fun) assert_receive 1 assert Connection.call(pid, :state) === 2 @@ -944,14 +1131,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - timeout = fn() -> - send(parent, {:timeout, n+1}) - {:noreply, n+1} + + fun = fn n -> + timeout = fn -> + send(parent, {:timeout, n + 1}) + {:noreply, n + 1} end + send(parent, n) {:noreply, timeout, 0} end + send(pid, fun) assert_receive 1 assert_receive {:timeout, 2} @@ -961,15 +1151,19 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> + + fun = fn n -> send(parent, n) - {:noreply, n+1, :hibernate} + {:noreply, n + 1, :hibernate} end + send(pid, fun) assert_receive 1 :timer.sleep(100) + assert Process.info(pid, :current_function) === - {:current_function, {:erlang, :hibernate, 3}} + {:current_function, {:erlang, :hibernate, 3}} + assert Connection.call(pid, :state) === 2 end @@ -977,14 +1171,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - connect = fn(m) -> + + fun = fn n -> + connect = fn m -> send(parent, {:connect, m}) - {:ok, m+1} + {:ok, m + 1} end + send(parent, n) - {:connect, connect, n+1} + {:connect, connect, n + 1} end + send(pid, fun) assert_receive 1 assert_receive {:connect, 2} @@ -994,14 +1191,17 @@ defmodule ConnectionTest do {:ok, pid} = Connection.start_link(EvalConn, 1) parent = self() - fun = fn(n) -> - disconnect = fn(m) -> + + fun = fn n -> + disconnect = fn m -> send(parent, {:disconnect, m}) - {:noconnect, m+1} + {:noconnect, m + 1} end + send(parent, n) - {:disconnect, disconnect, n+1} + {:disconnect, disconnect, n + 1} end + send(pid, fun) assert_receive 1 assert_receive {:disconnect, 2} @@ -1012,13 +1212,16 @@ defmodule ConnectionTest do _ = Process.flag(:trap_exit, true) parent = self() - fun = fn(n) -> - terminate = fn(m) -> + + fun = fn n -> + terminate = fn m -> send(parent, {:terminate, m}) end + send(parent, n) - {:stop, {:shutdown, terminate}, n+1} + {:stop, {:shutdown, terminate}, n + 1} end + send(pid, fun) assert_receive 1 assert_receive {:terminate, 2} @@ -1030,49 +1233,57 @@ defmodule ConnectionTest do parent = self() {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(n) -> - format_status = fn(m) -> + + fun = fn n -> + format_status = fn m -> send(parent, {:format_status, m}) - m+1 + m + 1 end - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) Process.put(:format_status, format_status) exit({:shutdown, :terminate}) end + send(parent, n) - {:stop, {:shutdown, terminate}, n+1} + {:stop, {:shutdown, terminate}, n + 1} end - assert capture_io(:user, fn() -> - send(pid, fun) - assert_receive 1 - assert_receive {:terminate, 2} - assert_receive {:format_status, 2} - assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} - Logger.flush() - end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 3"sm + + assert capture_io(:user, fn -> + send(pid, fun) + assert_receive 1 + assert_receive {:terminate, 2} + assert_receive {:format_status, 2} + assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} + Logger.flush() + end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 3"sm {:ok, pid} = Connection.start_link(EvalConn, 1) - fun = fn(n) -> - format_status = fn(m) -> + + fun = fn n -> + format_status = fn m -> send(parent, {:format_status, m}) exit(:oops) end - terminate = fn(m) -> + + terminate = fn m -> send(parent, {:terminate, m}) Process.put(:format_status, format_status) exit({:shutdown, :terminate}) end + send(parent, n) - {:stop, {:shutdown, terminate}, n+1} - end - assert capture_io(:user, fn() -> - send(pid, fun) - assert_receive 1 - assert_receive {:terminate, 2} - assert_receive {:format_status, 2} - assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} - Logger.flush() - end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 2"sm + {:stop, {:shutdown, terminate}, n + 1} + end + + assert capture_io(:user, fn -> + send(pid, fun) + assert_receive 1 + assert_receive {:terminate, 2} + assert_receive {:format_status, 2} + assert_receive {:EXIT, ^pid, {:shutdown, :terminate}} + Logger.flush() + end) =~ ~r"error.*GenServer.*\(stop\) shutdown: :terminate.*State: 2"sm end end
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor