Skip to content

Commit

Permalink
state machine tests
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorv-2204 committed Nov 8, 2022
1 parent 7916727 commit c0f69d0
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 51 deletions.
106 changes: 65 additions & 41 deletions lib/archethic/self_repair/notifier/repair_worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,82 +15,106 @@ defmodule Archethic.SelfRepair.Notifier.RepairWorker do
def init(args) do
Registry.register(Notifier.Impl.registry_name(), args.genesis_address, [])
Logger.debug("RepairWorker: Repair Started", address: args.genesis_address)
IO.inspect(label: "--")

{:ok, _next_state = :repair_started,
_data = %{
IO.inspect(binding(), label: "0-> init")

{:ok, :repair,
%{
genesis_address: args.genesis_address,
addresses: [args.last_address]
}, _actions = [{:next_event, :internal, :sync_chain}]}
}, [{:next_event, :internal, :start_repair}]}
end

def handle_event(
_event_type = :internal,
_event_content = :sync_chain,
_last_state = :repair_started,
server_data = %{
addresses: address_list
}
) do
IO.inspect(label: "---")
def handle_event(:enter, :repair, :repair, _) do
IO.inspect(binding(), label: "1 repair -> repair")

[repair_addr | new_address_list] = address_list
{:ok, _} = Notifier.Impl.repair_chain(repair_addr, server_data.genesis_address)
:keep_state_and_data
end

def handle_event(:internal, :start_repair, :repair, data = %{addresses: address_list}) do
IO.inspect(binding(), label: "2 :start_repair")

Logger.debug("RepairWorker: Repair sync_chain state")
new_data = repair_task(data)

actions = [{:next_event, :internal, :process_update_requests}]
{:keep_state, %{server_data | addresses: new_address_list}, actions}
{:next_state, :idle, new_data, []}
end

# state enter callback
# goes from old state to new state
def handle_event(
_enter = :enter,
_old_state = :repair_started,
_next_state = :repair_started,
_server_data
) do
Logger.debug("RepairWorker: state Loops")
IO.inspect(label: "----")
def handle_event(:enter, :repair, :idle, _data) do
IO.inspect(binding(), label: "4 :handle_event(:enter, :repair, :idle, _data)")

:keep_state_and_data
end

def handle_event(:internal, :process_update_requests, :repair_started, server_data) do
IO.inspect(label: "-----")
def handle_event(:info, {:DOWN, _, :process, pid, :normal}, :idle, data) do
IO.inspect(binding(), label: "5 :down event -> :idle")

{_, data} = Map.pop(data, pid)

{:next_state, :ack_req, data, [{:next_event, :internal, :process_update_requests}]}
end

case server_data.addresses do
def handle_event(
:internal,
:process_update_requests,
:ack_req,
data = %{addresses: address_list}
) do
case address_list do
[] ->
Logger.debug("Done processing Requests", server_data: server_data)
IO.inspect(label: "--------")
Logger.debug("Done processing Requests", server_data: data)
IO.inspect(binding(), label: "10: terminateing")

:stop

x when is_list(x) ->
Logger.debug("RepairWorker: process_update_requests")

{:keep_state_and_data, [{:next_event, :internal, :sync_chain}]}
new_data = repair_task(data)
IO.inspect(binding(), label: "6: :process_update_requests,:ack_req")
{:next_state, :idle, new_data, []}
end
end

def handle_event(:enter, :idle, :ack_req, _) do
:keep_state_and_data
end

def handle_event(:enter, :ack_req, :idle, _) do
:keep_state_and_data
end

def handle_event(
:cast,
{:update_request,
%{
last_address: address
}},
_,
server_data = %{
data = %{
addresses: address_list
}
) do
Logger.debug("RepairWorker: update request", server_data: server_data)
IO.inspect(binding(), label: "update request")

{:keep_state, %{server_data | addresses: [address | address_list]}, []}
{:keep_state, %{data | addresses: [address | address_list]}, []}
end

def terminate(_Reason, _State, server_data) do
Registry.unregister(Notifier.Impl.registry_name(), server_data.genesis_address)
def handle_event(:info, {_, {:ok, _}}, _s, _data) do
IO.inspect(label: "--- nil")
:keep_state_and_data
end

def repair_task(data = %{addresses: address_list, genesis_address: genesis_address}) do
[repair_addr | new_address_list] = address_list

%Task{
pid: pid
} =
Task.async(fn ->
IO.inspect(binding(), label: "3: repair_task")
{:ok, _} = Notifier.Impl.repair_chain(repair_addr, genesis_address)
end)

data
|> Map.put(:addresses, new_address_list)
|> Map.put(pid, nil)
end
end
49 changes: 39 additions & 10 deletions test/archethic/self_repair/notifier/repair_worker_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ defmodule Archethic.SelfRepair.Notifier.RepairWorkerTest do
use ArchethicCase

alias Archethic.SelfRepair.Notifier.RepairWorker
alias Archethic.SelfRepair.Notifier.Impl, as: NotifierImpl

import Mox

@registry_name Archethic.SelfRepair.Notifier.Impl.registry_name()
describe "RepairWorker FSM Behaviour" do
setup do
case Process.whereis(@registry_name) do
Expand All @@ -19,23 +20,51 @@ defmodule Archethic.SelfRepair.Notifier.RepairWorkerTest do
:ok
end

test "State-Event Behaviour" do
opts = %{genesis_address: "chainA_genesis_address", last_address: "chainA_last_address"}
test "Expected behaviour Repair worker" do
gen_addr = "gen_addr"
last_Addr = "last_Addr"
opts = %{genesis_address: gen_addr, last_address: last_Addr}

MockDB
|> stub(
:transaction_exists?,
fn _ ->
IO.inspect("processsleep")
Process.sleep(1500)
false
Process.sleep(50)
true
end
)

pid = start_supervised!({RepairWorker, opts})
Registry.lookup(@)
:sys.get_state(pid)
|> IO.inspect(label: "=======")
{:ok, pid} = RepairWorker.start_link(opts)

assert {:idle, %{:addresses => [], :genesis_address => "gen_addr"}} = :sys.get_state(pid)

assert [{^pid, _}] = Registry.lookup(@registry_name, gen_addr)

Enum.each(1..3, fn x ->
NotifierImpl.update_worker(
%{genesis_address: gen_addr, last_address: "txn" <> "#{x}"},
pid
)
end)

assert {:idle, %{:addresses => ["txn3", "txn2", "txn1"], :genesis_address => "gen_addr"}} =
:sys.get_state(pid)

Process.sleep(200)

assert {:idle, %{:addresses => [], :genesis_address => "gen_addr"}} = :sys.get_state(pid)

Process.sleep(100)
assert [] = Registry.lookup(@registry_name, gen_addr)
end

test "should continue even if repair chain crashes" do
gen_addr = "aa"
last_Addr = "bb"
opts = %{genesis_address: gen_addr, last_address: last_Addr}

{:ok, pid} = RepairWorker.start_link(opts)
assert {:idle, %{:addresses => [], :genesis_address => "aa"}} = :sys.get_state(pid)
end
end
end

0 comments on commit c0f69d0

Please sign in to comment.