Current section

Files

Jump to
helen test remote remote_test.exs
Raw

test/remote/remote_test.exs

defmodule RemoteTest do
@moduledoc false
use ExUnit.Case, async: true
import ExUnit.CaptureLog
use Timex
alias TimeSupport
def host(num),
do: "ruth.remote" <> String.pad_leading(Integer.to_string(num), 3, "0")
def name(num),
do: "remote" <> String.pad_leading(Integer.to_string(num), 3, "0")
def ext(num),
do: %{
host: host(num),
type: "remote_runtime",
mtime: TimeSupport.unix_now(:second),
async: false
}
def runtime(m) do
runtime_map = %{
type: "remote_runtime",
batt_mv: 3800,
bssid: "11:22:33:44:55:66",
ap_rssi: -45,
ap_pri_chan: 6,
heap_min: 100 * 1024,
heap_free: 101 * 1024,
uptime_ms: 15_000
}
Map.merge(m, runtime_map)
end
def boot(m) do
boot_map = %{
type: "boot",
hw: "esp32",
vsn: "12345678",
proj: "ruth",
idf: "idf-3.3",
sha: "0123456789abcdef",
bdate: "04-16-2019",
btime: "14:01:02",
mword: "0x123456",
svsn: 813,
reset_reason: "software reset",
async: false
}
Map.merge(m, boot_map)
end
setup_all do
ext(99) |> Map.put(:log, false) |> boot() |> Remote.external_update()
:ok
end
test "process well formed external remote update" do
res = ext(1) |> runtime() |> Remote.external_update()
assert res === :ok
end
test "process external update of type 'boot'" do
eu = ext(16)
initial_mtime = Map.get(eu, :mtime)
later_mtime = Map.get(eu, :mtime) + 30
res =
eu
|> boot()
|> Map.merge(%{mtime: later_mtime, log: false})
|> Remote.external_update()
rem = Remote.get_by(host: host(16))
assert res === :ok
assert Timex.to_unix(rem.last_start_at) >= initial_mtime
end
test "can create a changeset from an external update" do
eu = ext(19) |> boot() |> Map.merge(%{log: false})
Remote.external_update(eu)
rem = Remote.get_by(name: host(19))
changes = %{reset_reason: "esp_restart()", name: rem.name}
cs = Remote.changeset(rem, changes)
assert cs.valid? === true
end
test "process external update of type 'remote_runtime'" do
res =
ext(17)
|> Map.put_new(:type, "remote_runtime")
|> Remote.external_update()
assert res === :ok
end
test "process poorly formed external remote update" do
fun = fn -> %{host: host(1), type: "boot"} |> Remote.external_update() end
msg = capture_log(fun)
# assert msg =~ host(1)
assert msg =~ "unknown" or msg =~ "bad map"
end
test "external update logs remote startup message" do
fun = fn ->
Map.put(ext(4), :log, true) |> boot() |> Remote.external_update()
end
msg = capture_log(fun)
assert msg =~ name(4)
assert msg =~ "BOOT"
end
test "mark as seen (default threshold)" do
ext(6) |> Remote.external_update()
before_mark = Remote.get_by(host: host(6))
Remote.mark_as_seen(host(1), TimeSupport.unix_now(:second))
after_mark = Remote.get_by(host: host(6))
assert before_mark.last_seen_at === after_mark.last_seen_at
end
@tag long_running: true
test "mark as seen (zero threshold)" do
ext(5) |> Remote.external_update()
before_mark = Remote.get_by(host: host(5))
:timer.sleep(1001)
Remote.mark_as_seen(host(5), TimeSupport.unix_now(:second), 0)
after_mark = Remote.get_by(host: host(5))
assert Timex.compare(after_mark.last_seen_at, before_mark.last_seen_at) == 1
end
test "change a name" do
ext(2) |> Remote.external_update()
res = Remote.change_name(host(2), name(2))
%Remote{name: name} = Remote.get_by(name: name(2))
assert res === :ok and name === name(2)
end
test "change a name (name in use)" do
ext(1) |> Remote.external_update()
Remote.change_name(host(1), name(1))
res = Remote.change_name(host(2), name(1))
assert res === :name_in_use
end
test "change a name (by id)" do
n = 13
ext(n) |> Remote.external_update()
r = Remote.get_by(host: host(n))
res = Remote.change_name(r.id, name(n))
assert res === name(n)
end
test "get_by(name: name)" do
ext(3) |> Remote.external_update()
Remote.change_name(host(3), name(3))
%Remote{name: name} = Remote.get_by(name: name(3))
assert name === name(3)
end
test "get_by(name: name, only: [:last_seen_at, :last_start_at])" do
ext(3) |> Remote.external_update()
result = Remote.get_by(host: host(3), only: [:last_seen_at, :last_start_at])
seen =
if is_map(result), do: Map.get(result, :last_seen_at, nil), else: result
start =
if is_map(result), do: Map.get(result, :last_start_at, nil), else: result
refute is_nil(seen) and is_nil(start)
end
test "get_by(name: name, only: :last_seen_at)" do
ext(3) |> Remote.external_update()
result = Remote.get_by(host: host(3), only: :last_seen_at)
last =
if is_map(result), do: Map.get(result, :last_seen_at, nil), else: result
refute is_nil(last)
end
test "get_by(id: id)" do
num = 14
host = host(num)
ext(num) |> Remote.external_update()
rem1 = Remote.get_by(host: host)
rem2 = Remote.get_by(id: rem1.id)
assert rem1.id === rem2.id
end
test "get_by bad params" do
msg = capture_log(fn -> Remote.get_by(foo: "foo") end)
assert(msg =~ "bad arg")
end
test "all Remotes" do
ext(1) |> Remote.external_update()
remotes = Remote.all()
is_remote = if Enum.empty?(remotes), do: nil, else: %Remote{} = hd(remotes)
assert is_list(remotes) and is_remote
end
test "remote_list(:all)" do
ota_list = Remote.remote_list(:all)
first = [ota_list] |> List.flatten() |> hd
assert is_list(ota_list)
assert %{name: _, host: _} = first
end
test "remote_list(integer)" do
num = 14
host = host(num)
ext(num) |> Remote.external_update()
rem1 = Remote.get_by(host: host)
ota_list = Remote.remote_list(rem1.id)
first = [ota_list] |> List.flatten() |> hd()
assert is_list(ota_list)
assert %{name: _, host: _} = first
end
test "remote_list(name)" do
num = 14
host = host(num)
ext(num) |> Remote.external_update()
rem1 = Remote.get_by(host: host)
ota_list = Remote.remote_list(rem1.name)
first = [ota_list] |> List.flatten() |> hd()
assert is_list(ota_list)
assert %{name: _, host: _} = first
end
test "remote_list(host)" do
num = 18
host = host(num)
ext(num) |> Remote.external_update()
ota_list = Remote.remote_list(host)
first = [ota_list] |> List.flatten() |> hd()
assert is_list(ota_list)
assert %{name: _, host: _} = first
end
test "remote_list(list_of_hosts)" do
host_ids = [14, 15, 16, 17]
hosts =
for id <- host_ids do
ext(id) |> Remote.external_update()
host(id)
end
ota_list = Remote.remote_list(hosts)
first = [ota_list] |> List.flatten() |> hd()
assert is_list(ota_list)
assert %{name: _, host: _} = first
assert 4 == length(ota_list)
end
@tag :ota
test "OTA update (unsupported)" do
msg =
capture_log(fn ->
Remote.ota_update(:bad, log: true)
end)
assert msg =~ "can't do ota for"
end
@tag :ota
test "OTA update (main)" do
n = 16
ext(n) |> boot() |> Map.put(:log, false) |> Remote.external_update()
rem = Remote.get_by(host: host(n))
list = Remote.ota_update(rem.host, reboot_delay_ms: 1000, log: false)
assert is_list(list)
refute Enum.empty?(list)
assert {_name, _host, :ok} = hd(list)
end
@tag :ota
test "OTA update (log message)" do
n = 17
ext(n) |> boot() |> Map.put(:log, false) |> Remote.external_update()
rem = Remote.get_by(host: host(n))
msg =
capture_log(fn ->
Remote.ota_update(rem.host, reboot_delay_ms: 1000, log: true)
end)
assert msg =~ "sent ota https to"
assert msg =~ "17"
end
test "remote restart" do
n = 12
ext(n) |> boot() |> Map.put(:log, false) |> Remote.external_update()
rem = Remote.get_by(host: host(n))
list = Remote.restart(rem.host, reboot_delay_ms: 0, log: false)
assert is_list(list)
refute Enum.empty?(list)
assert {_name, _host, :ok} = hd(list)
end
test "can deprecate a Remote" do
n = 15
ext(n) |> Remote.external_update()
rem = Remote.get_by(host: host(n))
{rc, res} = Remote.deprecate(rem.id)
assert rc == :ok and String.contains?(res.name, "~")
end
end