diff --git a/lib/trinity/scheduler/simulation_supervisor.ex b/lib/trinity/scheduler/simulation_supervisor.ex index 3226faf..87560ce 100644 --- a/lib/trinity/scheduler/simulation_supervisor.ex +++ b/lib/trinity/scheduler/simulation_supervisor.ex @@ -123,38 +123,10 @@ defmodule Trinity.Scheduler.SimulationSupervisor do end defp end_simulation(%State{} = state, reason) do - %{sim: sim, parent_pid: parent_pid, ref: ref, result: result} = state - - %Simulation{log: log, log_atomic: log_atomic} = sim - hash = :atomics.get(log_atomic, 1) - - require Logger - Logger.info """ - Simulation complete - Hash: #{print_hash(hash)} - Log: - - #{print_log(log)} - """ - + %{parent_pid: parent_pid, ref: ref, result: result} = state send parent_pid, {ref, reason, result} end - defp print_hash(hash) do - :crypto.hash(:sha256, <>) - |> Base.encode32() - |> String.slice(0, 8) - end - - defp print_log(log) do - :ets.tab2list(log) - |> Enum.take(-10) - |> Enum.reduce("", fn {i, msg}, acc -> - i_pad = String.pad_leading(Integer.to_string(i), 2) - acc <> i_pad <> ": " <> msg <> "\n" - end) - end - defp spawn_sim_child(%Simulation{} = sim, fun) do # TODO: larger range? child_seed = Enum.random(1..1_000_000) diff --git a/lib/trinity/sim_logger.ex b/lib/trinity/sim_logger.ex index 596562e..834ff72 100644 --- a/lib/trinity/sim_logger.ex +++ b/lib/trinity/sim_logger.ex @@ -4,6 +4,39 @@ defmodule Trinity.SimLogger do @spec get_sim :: Simulation.t | nil defp get_sim, do: Process.get(simulation_key()) + @spec get_hash :: non_neg_integer + def get_hash do + %{log_atomic: log_atomic} = get_sim() + :atomics.get(log_atomic, 1) + end + + @spec log_head(non_neg_integer) :: [String.t] + def log_head(count) do + scan_log(1, count) + end + + @spec log_tail(non_neg_integer) :: [String.t] + def log_tail(count) do + %{log_atomic: log_atomic} = get_sim() + last_i = :atomics.get(log_atomic, 2) + scan_log(last_i - count, count) + end + + @spec scan_log(non_neg_integer, non_neg_integer) :: [String.t] + def scan_log(i, count) do + %{log: log} = get_sim() + do_scan_log(log, i + count, count, []) + end + + defp do_scan_log(_log, _i, 0, acc) do + acc + end + + defp do_scan_log(log, i, count, acc) do + [{_i, message}] = :ets.lookup(log, i) + do_scan_log(log, i - 1, count - 1, [message | acc]) + end + defmacro debug(message) do key = simulation_key() diff --git a/test/trinity_test.exs b/test/trinity_test.exs index 834c6f7..6195728 100644 --- a/test/trinity_test.exs +++ b/test/trinity_test.exs @@ -53,7 +53,7 @@ defmodule TrinityTest do end test "scheduler" do - result = Sim.run_simulation(fn -> + message = Sim.run_simulation(fn -> nodes = [:n1, :n2, :n3] pids = Enum.map(nodes, fn node -> @@ -99,8 +99,20 @@ defmodule TrinityTest do Scheduler.yield(1000) #dbg Scheduler.dump(), limit: :infinity :success + + hash = SimLogger.get_hash() + tail = SimLogger.log_tail(10) + """ + Simulation complete. + + Hash: #{hash} + + Log tail: + #{Enum.join(tail, "\n")} + """ end, seed: 101) - assert result == :success + require Logger + Logger.info(message) end end