defmodule CljElixir.CompilerTest do use ExUnit.Case, async: true describe "compile_string/2" do test "returns {:ok, ast} for valid source" do # This test exercises the full pipeline. It requires Reader and Transformer # to be implemented. Until then, it verifies the Compiler module compiles # and the function heads are correct. source = "(+ 1 2)" case CljElixir.Compiler.compile_string(source) do {:ok, _ast} -> :ok {:error, diagnostics} -> # Expected when Reader/Transformer are not yet implemented assert is_list(diagnostics) end end test "returns {:error, diagnostics} for missing file" do {:error, diagnostics} = CljElixir.Compiler.compile_file("/nonexistent/path.clje") assert is_list(diagnostics) assert length(diagnostics) > 0 [diag | _] = diagnostics assert diag.severity == :error assert diag.message =~ "could not read file" end test "passes file option through" do source = "(+ 1 2)" opts = [file: "test.clje"] case CljElixir.Compiler.compile_string(source, opts) do {:ok, _ast} -> :ok {:error, _diagnostics} -> :ok end end end describe "eval_string/2" do test "returns {:ok, result, bindings} or {:error, diagnostics}" do source = "(+ 1 2)" case CljElixir.Compiler.eval_string(source) do {:ok, result, bindings} -> assert result == 3 assert is_list(bindings) {:error, diagnostics} -> # Expected when Reader/Transformer are not yet implemented assert is_list(diagnostics) end end end describe "compile_to_beam/2" do test "returns {:ok, modules} or {:error, diagnostics}" do source = ~S""" (defmodule TestBeamCompile (defn hello [] :world)) """ case CljElixir.Compiler.compile_to_beam(source) do {:ok, modules} -> assert is_list(modules) assert Enum.any?(modules, fn {mod, _binary} -> mod == TestBeamCompile end) {:error, diagnostics} -> # Expected when Reader/Transformer are not yet implemented assert is_list(diagnostics) end end end describe "compile_file/2" do test "reads file and compiles" do # Write a temp file tmp_dir = System.tmp_dir!() path = Path.join(tmp_dir, "test_compile_#{System.unique_integer([:positive])}.clje") File.write!(path, "(+ 1 2)") try do case CljElixir.Compiler.compile_file(path) do {:ok, _ast} -> :ok {:error, _diagnostics} -> :ok end after File.rm(path) end end test "returns error for nonexistent file" do {:error, [diag | _]} = CljElixir.Compiler.compile_file("/does/not/exist.clje") assert diag.severity == :error assert diag.message =~ "could not read file" end end describe "eval_file/2" do test "reads file, compiles, and evaluates" do tmp_dir = System.tmp_dir!() path = Path.join(tmp_dir, "test_eval_#{System.unique_integer([:positive])}.clje") File.write!(path, "(+ 1 2)") try do case CljElixir.Compiler.eval_file(path) do {:ok, 3, _bindings} -> :ok {:ok, _result, _bindings} -> :ok {:error, _diagnostics} -> :ok end after File.rm(path) end end end describe "compile_file_to_beam/2" do test "compiles file and writes .beam output" do tmp_dir = System.tmp_dir!() source_path = Path.join(tmp_dir, "test_beam_#{System.unique_integer([:positive])}.clje") output_dir = Path.join(tmp_dir, "beam_output_#{System.unique_integer([:positive])}") File.write!(source_path, ~S""" (defmodule TestBeamOutput (defn greet [] "hi")) """) try do case CljElixir.Compiler.compile_file_to_beam(source_path, output_dir: output_dir) do {:ok, modules} -> assert is_list(modules) # Check .beam files were written beam_files = Path.wildcard(Path.join(output_dir, "*.beam")) assert length(beam_files) > 0 {:error, _diagnostics} -> # Expected when Reader/Transformer are not yet implemented :ok end after File.rm(source_path) File.rm_rf(output_dir) end end end end