defmodule ProxmoxAgent.Diagnostics.WriterTest do use ExUnit.Case, async: false alias ProxmoxAgent.Diagnostics.Writer setup do dir = Path.join(System.tmp_dir!(), "writer-#{System.unique_integer([:positive])}") File.mkdir_p!(dir) {:ok, pid} = Writer.start_link(dir: dir) on_exit(fn -> if Process.alive?(pid), do: GenServer.stop(pid) File.rm_rf(dir) end) %{dir: dir, pid: pid} end test "handle_cast :command appends a formatted entry to commands.log", %{dir: dir, pid: pid} do GenServer.cast(pid, {:command, "zpool", ["list", "-j"], {:ok, "hello body"}, 1_234}) :ok = GenServer.call(pid, :flush) body = File.read!(Path.join(dir, "commands.log")) assert body =~ "$ zpool list -j" assert body =~ "exit=0" assert body =~ "duration=1ms" assert body =~ "size=10" assert body =~ "hello body" assert body =~ "=====\n" end test "handle_cast :command records errors in place of exit", %{dir: dir, pid: pid} do GenServer.cast(pid, {:command, "zpool", ["list"], {:error, {:enoent, "zpool"}}, 300}) :ok = GenServer.call(pid, :flush) body = File.read!(Path.join(dir, "commands.log")) assert body =~ "error={:enoent, \"zpool\"}" assert body =~ "duration=0ms" refute body =~ "exit=" end test "handle_cast :command formats non-zero exit results", %{dir: dir, pid: pid} do GenServer.cast(pid, {:command, "/bin/sh", ["-c", "exit 7"], {:error, {:nonzero_exit, 7, "oops"}}, 500}) :ok = GenServer.call(pid, :flush) body = File.read!(Path.join(dir, "commands.log")) assert body =~ "exit=7" assert body =~ "size=4" assert body =~ "oops" end test "handle_cast :sample appends pretty-printed JSON to samples.log", %{dir: dir, pid: pid} do GenServer.cast(pid, {:sample, "fast", %{"host" => %{"load1" => 0.1}}}) :ok = GenServer.call(pid, :flush) body = File.read!(Path.join(dir, "samples.log")) assert body =~ "kind=fast" assert body =~ "\"host\"" assert body =~ "\"load1\"" assert body =~ "=====\n" end test "multiple casts serialize and do not interleave", %{dir: dir, pid: pid} do for i <- 1..50 do GenServer.cast(pid, {:command, "cmd#{i}", [], {:ok, "body#{i}"}, 1}) end :ok = GenServer.call(pid, :flush) body = File.read!(Path.join(dir, "commands.log")) # Every body1..body50 must appear exactly once, in order. for i <- 1..50 do assert body =~ "body#{i}" end end test "terminate closes handles cleanly", %{pid: pid} do ref = Process.monitor(pid) GenServer.stop(pid, :normal) assert_receive {:DOWN, ^ref, :process, ^pid, :normal}, 1000 end end