parent
bd31796d40
commit
75c88fac85
@ -0,0 +1,65 @@ |
|||||||
|
defmodule EthereumJSONRPC.RequestCoordinatorTest do |
||||||
|
use ExUnit.Case |
||||||
|
use EthereumJSONRPC.Case |
||||||
|
|
||||||
|
alias EthereumJSONRPC.RollingWindow |
||||||
|
alias EthereumJSONRPC.RequestCoordinator |
||||||
|
|
||||||
|
import Mox |
||||||
|
|
||||||
|
setup :set_mox_global |
||||||
|
setup :verify_on_exit! |
||||||
|
|
||||||
|
defp sleep_time(timeouts) do |
||||||
|
wait_per_timeout = |
||||||
|
:ethereum_jsonrpc |
||||||
|
|> Application.get_env(RequestCoordinator) |
||||||
|
|> Keyword.fetch!(:wait_per_timeout) |
||||||
|
|
||||||
|
timeouts * wait_per_timeout |
||||||
|
end |
||||||
|
|
||||||
|
setup do |
||||||
|
table = Application.get_env(:ethereum_jsonrpc, EthereumJSONRPC.RequestCoordinator)[:rolling_window_opts][:table] |
||||||
|
|
||||||
|
:ets.delete_all_objects(table) |
||||||
|
|
||||||
|
%{table: table} |
||||||
|
end |
||||||
|
|
||||||
|
test "rolling window increments on timeout", %{table: table} do |
||||||
|
expect(EthereumJSONRPC.Mox, :json_rpc, fn _, _ -> {:error, :timeout} end) |
||||||
|
|
||||||
|
RequestCoordinator.perform(%{}, EthereumJSONRPC.Mox, [], :timer.minutes(60)) |
||||||
|
|
||||||
|
assert RollingWindow.count(table, :timeout) == 1 |
||||||
|
end |
||||||
|
|
||||||
|
test "waits the configured amount of time per failure", %{table: table} do |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
RollingWindow.inc(table, :timeout) |
||||||
|
|
||||||
|
test_process = self() |
||||||
|
|
||||||
|
expect(EthereumJSONRPC.Mox, :json_rpc, fn _, _ -> |
||||||
|
send(test_process, :called_json_rpc) |
||||||
|
end) |
||||||
|
|
||||||
|
# Calculate expected sleep time as if there were one less failure, allowing |
||||||
|
# a margin of error between the refute_receive, assert_receive, and actual |
||||||
|
# call. |
||||||
|
wait_time = sleep_time(5) |
||||||
|
|
||||||
|
Task.async(fn -> |
||||||
|
RequestCoordinator.perform(%{}, EthereumJSONRPC.Mox, [], :timer.minutes(60)) |
||||||
|
end) |
||||||
|
|
||||||
|
refute_receive(:called_json_rpc, wait_time) |
||||||
|
|
||||||
|
assert_receive(:called_json_rpc, wait_time) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,102 @@ |
|||||||
|
defmodule EthereumJSONRPC.RollingWindowTest do |
||||||
|
use ExUnit.Case, async: true |
||||||
|
use EthereumJSONRPC.Case |
||||||
|
|
||||||
|
alias EthereumJSONRPC.RollingWindow |
||||||
|
|
||||||
|
@table :table |
||||||
|
|
||||||
|
setup do |
||||||
|
# We set `window_length` to a large time frame so that we can sweep manually to simulate |
||||||
|
# time passing |
||||||
|
RollingWindow.start_link([table: @table, window_length: :timer.minutes(120), window_count: 3], name: RollingWindow) |
||||||
|
|
||||||
|
:ok |
||||||
|
end |
||||||
|
|
||||||
|
defp sweep do |
||||||
|
GenServer.call(RollingWindow, :sweep) |
||||||
|
end |
||||||
|
|
||||||
|
test "when no increments have happened, inspect returns an empty list" do |
||||||
|
assert RollingWindow.inspect(@table, :foobar) == [] |
||||||
|
end |
||||||
|
|
||||||
|
test "when no increments hafve happened, count returns 0" do |
||||||
|
assert RollingWindow.count(@table, :foobar) == 0 |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened, inspect returns the count for that window" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.inspect(@table, :foobar) == [1] |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened, count returns the count for that window" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.count(@table, :foobar) == 1 |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened in multiple windows, inspect returns the count for both windows" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.inspect(@table, :foobar) == [1, 1] |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened in multiple windows, count returns the sum of both windows" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.count(@table, :foobar) == 2 |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened in multiple windows, with an empty window in between, inspect shows that empty window" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.inspect(@table, :foobar) == [1, 0, 1] |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened in multiple windows, with an empty window in between, count still sums all windows" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.count(@table, :foobar) == 2 |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened, but has been swept <window_count> times, it no longer appears in inspect" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.inspect(@table, :foobar) == [1, 1, 0] |
||||||
|
end |
||||||
|
|
||||||
|
test "when an increment has happened, but has been swept <window_count> times, it no longer is included in count" do |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
sweep() |
||||||
|
RollingWindow.inc(@table, :foobar) |
||||||
|
|
||||||
|
assert RollingWindow.count(@table, :foobar) == 2 |
||||||
|
end |
||||||
|
|
||||||
|
test "sweeping schedules another sweep" do |
||||||
|
{:ok, state} = RollingWindow.init(table: :anything, window_length: 1, window_count: 1) |
||||||
|
RollingWindow.handle_info(:sweep, state) |
||||||
|
assert_receive(:sweep) |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue