Files
Adam d8719b6d48 Phases 1-7: Complete CljElixir compiler through Malli schema adapter
Bootstrap compiler (reader, analyzer, transformer, compiler, Mix plugin),
core protocols (16 protocols for Map/List/Tuple/BitString), PersistentVector
(bit-partitioned trie), domain tools (clojurify/elixirify), BEAM concurrency
(receive, spawn, GenServer), control flow & macros (threading, try/catch,
destructuring, defmacro with quasiquote/auto-gensym), and Malli schema
adapter (m/=> specs, auto @type, recursive schemas, cross-references).

537 compiler tests + 55 Malli unit tests + 15 integration tests = 607 total.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:38:22 -04:00

134 lines
3.4 KiB
Elixir

defmodule CljElixir.Phase5Test do
use ExUnit.Case, async: false
# Helper to compile and evaluate CljElixir code
defp eval!(source) do
case CljElixir.Compiler.eval_string(source) do
{:ok, result, _bindings} -> result
{:error, errors} -> raise "CljElixir eval error: #{inspect(errors)}"
end
end
# ==========================================================================
# GenServer integration
# ==========================================================================
describe "GenServer - simple counter" do
test "define and use a counter GenServer" do
eval!("""
(defmodule TestCounter
(use GenServer)
(defn init [initial]
#el[:ok initial])
(defn handle-call
([:get _from state]
#el[:reply state state])
([:increment _from state]
#el[:reply :ok (+ state 1)])))
""")
{:ok, pid} = GenServer.start_link(TestCounter, 0)
assert GenServer.call(pid, :get) == 0
assert GenServer.call(pid, :increment) == :ok
assert GenServer.call(pid, :get) == 1
GenServer.stop(pid)
end
end
describe "GenServer - handle_cast" do
test "cast resets state" do
eval!("""
(defmodule TestCaster
(use GenServer)
(defn init [initial]
#el[:ok initial])
(defn handle-call
([:get _from state]
#el[:reply state state]))
(defn handle-cast
([:reset _state]
#el[:noreply 0])))
""")
{:ok, pid} = GenServer.start_link(TestCaster, 42)
assert GenServer.call(pid, :get) == 42
GenServer.cast(pid, :reset)
Process.sleep(50)
assert GenServer.call(pid, :get) == 0
GenServer.stop(pid)
end
end
describe "GenServer - handle_info" do
test "handle-info receives plain messages" do
eval!("""
(defmodule TestInfoHandler
(use GenServer)
(defn init [initial]
#el[:ok initial])
(defn handle-call
([:get _from state]
#el[:reply state state]))
(defn handle-info
([:bump state]
#el[:noreply (+ state 1)])))
""")
{:ok, pid} = GenServer.start_link(TestInfoHandler, 0)
send(pid, :bump)
Process.sleep(50)
assert GenServer.call(pid, :get) == 1
GenServer.stop(pid)
end
end
# ==========================================================================
# ChatRoom pattern: spawn + send + receive loop
# ==========================================================================
describe "ChatRoom pattern" do
test "spawn + send + receive loop" do
eval!("""
(defmodule TestChatLoop
(defn loop [state]
(receive
[:ping pid]
(do
(send pid #el[:pong state])
(TestChatLoop/loop (+ state 1)))
[:get pid]
(do
(send pid #el[:count state])
(TestChatLoop/loop state))
:stop
:stopped
:after 5000
:timeout)))
""")
pid = spawn(fn -> TestChatLoop.loop(0) end)
send(pid, {:ping, self()})
assert_receive {:pong, 0}, 1000
send(pid, {:ping, self()})
assert_receive {:pong, 1}, 1000
send(pid, {:get, self()})
assert_receive {:count, 2}, 1000
send(pid, :stop)
Process.sleep(50)
refute Process.alive?(pid)
end
end
end