|
|
|
@ -1,5 +1,7 @@ |
|
|
|
|
defmodule Explorer.Chain.Statistics.ServerTest do |
|
|
|
|
use Explorer.DataCase |
|
|
|
|
use Explorer.DataCase, async: false |
|
|
|
|
|
|
|
|
|
import ExUnit.CaptureLog |
|
|
|
|
|
|
|
|
|
alias Explorer.Chain.Statistics |
|
|
|
|
alias Explorer.Chain.Statistics.Server |
|
|
|
@ -9,21 +11,28 @@ defmodule Explorer.Chain.Statistics.ServerTest do |
|
|
|
|
|
|
|
|
|
describe "child_spec/1" do |
|
|
|
|
test "it defines a child_spec/1 that works with supervisors" do |
|
|
|
|
assert {:ok, _} = start_supervised(Server) |
|
|
|
|
insert(:block) |
|
|
|
|
|
|
|
|
|
assert {:ok, pid} = start_supervised(Server) |
|
|
|
|
|
|
|
|
|
%Server{task: %Task{pid: pid}} = :sys.get_state(pid) |
|
|
|
|
ref = Process.monitor(pid) |
|
|
|
|
|
|
|
|
|
assert_receive {:DOWN, ^ref, :process, ^pid, _} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
describe "init/1" do |
|
|
|
|
test "returns a new chain when not told to refresh" do |
|
|
|
|
{:ok, statistics} = Server.init(refresh: false) |
|
|
|
|
empty_statistics = %Statistics{} |
|
|
|
|
|
|
|
|
|
assert statistics == %Statistics{} |
|
|
|
|
assert {:ok, %Server{statistics: ^empty_statistics}} = Server.init(refresh: false) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "returns a new chain when told to refresh" do |
|
|
|
|
{:ok, statistics} = Server.init(refresh: true) |
|
|
|
|
test "returns a new Statistics when told to refresh" do |
|
|
|
|
empty_statistics = %Statistics{} |
|
|
|
|
|
|
|
|
|
assert statistics == %Statistics{} |
|
|
|
|
assert {:ok, %Server{statistics: ^empty_statistics}} = Server.init(refresh: true) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "refreshes when told to refresh" do |
|
|
|
@ -34,57 +43,78 @@ defmodule Explorer.Chain.Statistics.ServerTest do |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
describe "handle_info/2" do |
|
|
|
|
test "returns the original chain when sent a :refresh message" do |
|
|
|
|
original = Statistics.fetch() |
|
|
|
|
setup :state |
|
|
|
|
|
|
|
|
|
test "returns the original statistics when sent a :refresh message", %{ |
|
|
|
|
state: %Server{statistics: statistics} = state |
|
|
|
|
} do |
|
|
|
|
assert {:noreply, %Server{statistics: ^statistics, task: task}} = Server.handle_info(:refresh, state) |
|
|
|
|
|
|
|
|
|
assert {:noreply, ^original} = Server.handle_info(:refresh, original) |
|
|
|
|
Task.await(task) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "launches an update when sent a :refresh message" do |
|
|
|
|
original = Statistics.fetch() |
|
|
|
|
{:ok, pid} = Server.start_link() |
|
|
|
|
chain = Server.fetch() |
|
|
|
|
:ok = GenServer.stop(pid) |
|
|
|
|
test "launches a Statistics.fetch Task update when sent a :refresh message", %{state: state} do |
|
|
|
|
assert {:noreply, %Server{task: %Task{} = task}} = Server.handle_info(:refresh, state) |
|
|
|
|
|
|
|
|
|
assert original.number == chain.number |
|
|
|
|
assert %Statistics{} = Task.await(task) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "does not reply when sent any other message" do |
|
|
|
|
assert {:noreply, _} = Server.handle_info(:ham, %Statistics{}) |
|
|
|
|
test "stores successful Task in state", %{state: state} do |
|
|
|
|
# so that `statistics` from Task will be different |
|
|
|
|
insert(:block) |
|
|
|
|
|
|
|
|
|
assert {:noreply, %Server{task: %Task{ref: ref}} = refresh_state} = Server.handle_info(:refresh, state) |
|
|
|
|
|
|
|
|
|
assert_receive {^ref, %Statistics{} = message_statistics} = message |
|
|
|
|
|
|
|
|
|
assert {:noreply, %Server{statistics: ^message_statistics, task: nil}} = |
|
|
|
|
Server.handle_info(message, refresh_state) |
|
|
|
|
|
|
|
|
|
refute message_statistics == state.statistics |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "logs crashed Task", %{state: state} do |
|
|
|
|
assert {:noreply, %Server{task: %Task{pid: pid, ref: ref}} = refresh_state} = Server.handle_info(:refresh, state) |
|
|
|
|
|
|
|
|
|
Process.exit(pid, :boom) |
|
|
|
|
|
|
|
|
|
assert_receive {:DOWN, ^ref, :process, ^pid, :boom} = message |
|
|
|
|
|
|
|
|
|
captured_log = |
|
|
|
|
capture_log(fn -> |
|
|
|
|
assert {:noreply, %Server{task: nil}} = Server.handle_info(message, refresh_state) |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
assert captured_log =~ "Explorer.Chain.Statistics.fetch failed and could not be cached: :boom" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
describe "handle_call/3" do |
|
|
|
|
test "replies with statistics when sent a :fetch message" do |
|
|
|
|
original = Statistics.fetch() |
|
|
|
|
state = %Server{statistics: original} |
|
|
|
|
|
|
|
|
|
assert {:reply, _, ^original} = Server.handle_call(:fetch, self(), original) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "does not reply when sent any other message" do |
|
|
|
|
assert {:noreply, _} = Server.handle_call(:ham, self(), %Statistics{}) |
|
|
|
|
assert {:reply, ^original, ^state} = Server.handle_call(:fetch, self(), state) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
describe "handle_cast/2" do |
|
|
|
|
test "schedules a refresh of the statistics when sent an update" do |
|
|
|
|
statistics = Statistics.fetch() |
|
|
|
|
describe "terminate/2" do |
|
|
|
|
setup :state |
|
|
|
|
|
|
|
|
|
Server.handle_cast({:update, statistics}, %Statistics{}) |
|
|
|
|
test "cleans up in-progress tasks when terminated", %{state: state} do |
|
|
|
|
assert {:noreply, %Server{task: %Task{pid: pid}} = refresh_state} = Server.handle_info(:refresh, state) |
|
|
|
|
|
|
|
|
|
assert_receive :refresh, 2_000 |
|
|
|
|
end |
|
|
|
|
second_ref = Process.monitor(pid) |
|
|
|
|
|
|
|
|
|
test "returns a noreply and the new incoming chain when sent an update" do |
|
|
|
|
original = Statistics.fetch() |
|
|
|
|
Server.terminate(:boom, refresh_state) |
|
|
|
|
|
|
|
|
|
assert {:noreply, ^original} = Server.handle_cast({:update, original}, %Statistics{}) |
|
|
|
|
assert_receive {:DOWN, ^second_ref, :process, ^pid, :shutdown} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "returns a noreply and the old chain when sent any other cast" do |
|
|
|
|
original = Statistics.fetch() |
|
|
|
|
defp state(_) do |
|
|
|
|
{:ok, state} = Server.init([]) |
|
|
|
|
|
|
|
|
|
assert {:noreply, ^original} = Server.handle_cast(:ham, original) |
|
|
|
|
end |
|
|
|
|
%{state: state} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|