Created
August 26, 2020 00:19
-
-
Save rranelli/36f5b1e384fd3bb0df29afaef6e59870 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ControlPlane.CircuitBreakerTest do | |
use ExUnit.Case | |
import ExUnit.Callbacks | |
alias ControlPlane.CircuitBreaker | |
defmodule Worker do | |
use GenServer | |
def start_link(args \\ %{}), | |
do: GenServer.start_link(__MODULE__, args) | |
@impl true | |
def init(init_args) do | |
init_args[:test_pid] && send(init_args[:test_pid], {:worker_pid, self()}) | |
init_args[:boom!] && raise "boom!" | |
(msg = init_args[:receive]) && assert_receive ^msg | |
{:ok, init_args} | |
end | |
@impl true | |
def handle_info(:boom!, _state), do: raise("boom!") | |
end | |
test "worker is stopped on `break!/1` and can be restarted" do | |
start_supervised!({CircuitBreaker, Worker}) | |
assert CircuitBreaker.available?(Worker) | |
assert :ok = CircuitBreaker.break!(Worker) | |
assert CircuitBreaker.unavailable?(Worker) | |
assert :ok = CircuitBreaker.restart(Worker) | |
assert CircuitBreaker.available?(Worker) | |
end | |
test "circuit breaker startup fails if the worker startup fails" do | |
assert {:error, reason} = start_supervised({CircuitBreaker, {Worker, boom!: true}}) | |
assert {{:shutdown, {:failed_to_start_child, :worker, _exception}}, _child} = reason | |
end | |
test "circuit breaker automatically restarts a failed child" do | |
_pid = start_supervised!({CircuitBreaker, {Worker, [[test_pid: self()]]}}) | |
# First, we'll get notified from the worker with its identity | |
assert_receive {:worker_pid, worker_pid} | |
ref = Process.monitor(worker_pid) | |
# Now, we abnormally terminate the worker ... | |
send(worker_pid, :boom!) | |
# ... which should notify us of its death via `monitor` ... | |
assert_receive {:DOWN, ^ref, :process, ^worker_pid, _reason} | |
# ... Meaning the subsystem is now unavailable | |
:timer.sleep(100) | |
assert CircuitBreaker.unavailable?(Worker) | |
# After a little while, the worker will be restarted ... | |
assert_receive {:worker_pid, new_worker_pid} | |
when new_worker_pid != worker_pid, | |
2_000 | |
# Meaning the subsystem is now *available* | |
:timer.sleep(100) | |
assert CircuitBreaker.available?(Worker) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment