121 lines
3.0 KiB
Elixir
121 lines
3.0 KiB
Elixir
defmodule VMTest do
|
|
use ExUnit.Case
|
|
doctest Day5
|
|
|
|
def run(prog, io \\ []) do
|
|
parent = self()
|
|
|
|
pid =
|
|
spawn(fn ->
|
|
Day5.run(prog, parent)
|
|
end)
|
|
|
|
handle_io(pid, io)
|
|
|
|
receive do
|
|
{:halt, ^pid, memory} ->
|
|
{:halt, memory}
|
|
|
|
{:ok, ^pid, memory} ->
|
|
{:ok, memory}
|
|
|
|
msg ->
|
|
IO.inspect(msg)
|
|
end
|
|
end
|
|
|
|
def handle_io(_, []), do: :ok
|
|
|
|
def handle_io(pid, [head | rest]) do
|
|
case head do
|
|
{:in, input} ->
|
|
receive do
|
|
{:in, ^pid} -> send(pid, {:in, input})
|
|
end
|
|
|
|
{:out, expected} ->
|
|
receive do
|
|
{:out, ^pid, output} -> assert output == expected
|
|
end
|
|
end
|
|
|
|
handle_io(pid, rest)
|
|
end
|
|
|
|
test "exits" do
|
|
assert run([]) == {:ok, []}
|
|
end
|
|
|
|
test "halts" do
|
|
assert run([99]) == {:halt, [99]}
|
|
end
|
|
|
|
test "basic position mode instructions" do
|
|
assert run([1, 3, 2, 3]) == {:ok, [1, 3, 2, 5]}
|
|
assert run([2, 3, 2, 3]) == {:ok, [2, 3, 2, 6]}
|
|
end
|
|
|
|
test "basic immediate mode instructions" do
|
|
assert run([1101, 1, 2, 0]) == {:ok, [3, 1, 2, 0]}
|
|
assert run([1102, 4, 2, 0]) == {:ok, [8, 4, 2, 0]}
|
|
end
|
|
|
|
test "receives input" do
|
|
assert run([3, 1], in: 1234) == {:ok, [3, 1234]}
|
|
end
|
|
|
|
test "produces output" do
|
|
assert run([104, 77], out: 77) == {:ok, [104, 77]}
|
|
assert run([4, 0], out: 4) == {:ok, [4, 0]}
|
|
end
|
|
|
|
test "jump if non-zero" do
|
|
prog = [1105, 1, 4, 99, 1101, 1, 2, 7]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 7, 3)}
|
|
prog = [1105, 0, 4, 99, 1101, 1, 2, 7]
|
|
assert run(prog) == {:halt, prog}
|
|
|
|
prog = [1005, 0, 4, 99, 1101, 1, 2, 7]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 7, 3)}
|
|
|
|
prog = [5, 0, 9, 99, 1101, 1, 2, 7, 99, 4]
|
|
assert run(prog) == {:halt, List.replace_at(prog, 7, 3)}
|
|
end
|
|
|
|
test "jump if zero" do
|
|
prog = [1106, 0, 4, 99, 1101, 1, 2, 7]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 7, 3)}
|
|
prog = [1106, 42, 4, 99, 1101, 1, 2, 7]
|
|
assert run(prog) == {:halt, prog}
|
|
|
|
prog = [1006, 9, 4, 99, 1101, 1, 2, 7, 99, 0]
|
|
assert run(prog) == {:halt, List.replace_at(prog, 7, 3)}
|
|
prog = [6, 9, 10, 99, 1101, 1, 2, 7, 99, 0, 4]
|
|
assert run(prog) == {:halt, List.replace_at(prog, 7, 3)}
|
|
end
|
|
|
|
test "compare less than" do
|
|
prog = [1107, 3, 8, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
prog = [1107, 12, 8, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 0)}
|
|
|
|
prog = [1007, 3, 8, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
prog = [7, 3, 0, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
end
|
|
|
|
test "compare equal to" do
|
|
prog = [1108, 4, 4, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
prog = [1108, 5, 4, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 0)}
|
|
|
|
prog = [1008, 0, 1008, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
prog = [8, 2, 2, 3]
|
|
assert run(prog) == {:ok, List.replace_at(prog, 3, 1)}
|
|
end
|
|
end
|