mirror of
https://github.com/sbrow/thor.git
synced 2026-10-25 10:11:55 -04:00
155 lines
5.4 KiB
Odin
155 lines
5.4 KiB
Odin
#+test
|
|
package mustache
|
|
|
|
import "core:fmt"
|
|
import "core:os"
|
|
import "core:strings"
|
|
import "core:testing"
|
|
|
|
// tool_test_dirs makes a fresh in/out dir pair under the system temp dir and
|
|
// returns their paths (unique per name).
|
|
tool_test_dirs :: proc(name: string) -> (in_dir, out_dir: string) {
|
|
base, _ := os.temp_directory(context.temp_allocator)
|
|
in_dir = fmt.tprintf("%s/thor_tool_test/%s/in", base, name)
|
|
out_dir = fmt.tprintf("%s/thor_tool_test/%s/out", base, name)
|
|
os.make_directory_all(in_dir)
|
|
os.make_directory_all(out_dir)
|
|
return
|
|
}
|
|
|
|
// Tool_Test_Ctx carries the asset path as a context value (mustache resolves
|
|
// tag keys from the context, not from quoted literals).
|
|
Tool_Test_Ctx :: struct {
|
|
p: string,
|
|
}
|
|
|
|
@(test)
|
|
test_tool_unknown_tool :: proc(t: ^testing.T) {
|
|
reg: Tool_Registry // no commands configured
|
|
tpl, _ := parse(`{{ p | tool nope }}`)
|
|
defer delete_template(&tpl)
|
|
_, err := render(tpl, Tool_Test_Ctx{p = "/a.css"}, tools = ®)
|
|
testing.expect(t, err != nil, "unknown tool should be a hard error")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_unavailable_without_registry :: proc(t: ^testing.T) {
|
|
// No registry threaded through (tools == nil): the pipe must fail rather
|
|
// than silently do nothing.
|
|
tpl, _ := parse(`{{ p | tool anything }}`)
|
|
defer delete_template(&tpl)
|
|
_, err := render(tpl, Tool_Test_Ctx{p = "/a.css"})
|
|
testing.expect(t, err != nil, "tool pipe without a registry should error")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_arg_count :: proc(t: ^testing.T) {
|
|
reg: Tool_Registry
|
|
|
|
// Zero args.
|
|
tpl0, _ := parse(`{{ p | tool }}`)
|
|
defer delete_template(&tpl0)
|
|
_, err0 := render(tpl0, Tool_Test_Ctx{p = "/a.css"}, tools = ®)
|
|
testing.expect(t, err0 != nil, "tool with no name should error")
|
|
|
|
// Two args.
|
|
tpl2, _ := parse(`{{ p | tool one two }}`)
|
|
defer delete_template(&tpl2)
|
|
_, err2 := render(tpl2, Tool_Test_Ctx{p = "/a.css"}, tools = ®)
|
|
testing.expect(t, err2 != nil, "tool with two args should error")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_absolute_url_passthrough :: proc(t: ^testing.T) {
|
|
// A CDN URL has no local source; it should pass through untouched.
|
|
reg: Tool_Registry
|
|
url, err := run_tool(®, "anything", "https://cdn.example.com/x.css", 0)
|
|
testing.expect(t, err == nil, "absolute URL should not error")
|
|
testing.expect_value(t, url, "https://cdn.example.com/x.css")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_source_not_found :: proc(t: ^testing.T) {
|
|
in_dir, out_dir := tool_test_dirs("missing_src")
|
|
commands := make(map[string]string, context.temp_allocator)
|
|
commands["cp"] = "cp {{in}} {{out}}"
|
|
reg := Tool_Registry {
|
|
commands = commands,
|
|
input_dir = in_dir,
|
|
output_dir = out_dir,
|
|
}
|
|
|
|
_, err := run_tool(®, "cp", "/nope.css", 0)
|
|
testing.expect(t, err != nil, "missing source file should be a hard error")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_missing_binary :: proc(t: ^testing.T) {
|
|
in_dir, out_dir := tool_test_dirs("missing_bin")
|
|
_ = os.write_entire_file_from_string(fmt.tprintf("%s/a.css", in_dir), "body{}")
|
|
|
|
commands := make(map[string]string, context.temp_allocator)
|
|
commands["ghost"] = "thor-tool-does-not-exist-xyz {{in}} {{out}}"
|
|
reg := Tool_Registry {
|
|
commands = commands,
|
|
input_dir = in_dir,
|
|
output_dir = out_dir,
|
|
}
|
|
|
|
_, err := run_tool(®, "ghost", "/a.css", 0)
|
|
testing.expect(t, err != nil, "missing binary should be caught by PATH check")
|
|
}
|
|
|
|
@(test)
|
|
test_tool_runs :: proc(t: ^testing.T) {
|
|
when ODIN_OS != .Windows {
|
|
in_dir, out_dir := tool_test_dirs("runs")
|
|
os.make_directory_all(fmt.tprintf("%s/css", in_dir))
|
|
_ = os.write_entire_file_from_string(
|
|
fmt.tprintf("%s/css/main.css", in_dir),
|
|
"body { color: red }",
|
|
)
|
|
|
|
commands := make(map[string]string, context.temp_allocator)
|
|
commands["copyit"] = "cp {{in}} {{out}}"
|
|
reg := Tool_Registry {
|
|
commands = commands,
|
|
input_dir = in_dir,
|
|
output_dir = out_dir,
|
|
}
|
|
|
|
tpl, _ := parse(`{{ p | tool copyit }}`)
|
|
defer delete_template(&tpl)
|
|
result, err := render(tpl, Tool_Test_Ctx{p = "/css/main.css"}, tools = ®)
|
|
defer delete(result)
|
|
testing.expect(t, err == nil, "cp tool should succeed")
|
|
testing.expect_value(t, result, "/css/main.css")
|
|
|
|
// The tool wrote the output file.
|
|
written := fmt.tprintf("%s/css/main.css", out_dir)
|
|
data, rerr := os.read_entire_file_from_path(written, context.temp_allocator)
|
|
testing.expect(t, rerr == nil, "output file should exist")
|
|
testing.expect_value(t, string(data), "body { color: red }")
|
|
|
|
// The result was memoized; a second call for the same asset returns the
|
|
// same URL from the registry (mutated through the pointer).
|
|
url2, err2 := run_tool(®, "copyit", "/css/main.css", 0)
|
|
testing.expect(t, err2 == nil, "memoized call should not error")
|
|
testing.expect_value(t, url2, "/css/main.css")
|
|
testing.expect(t, len(reg.manifest) == 1, "result should be memoized")
|
|
}
|
|
}
|
|
|
|
@(test)
|
|
test_tool_minify_section :: proc(t: ^testing.T) {
|
|
// The command template is itself mustache: {{#minify}} should expand only
|
|
// when the registry has minify on. Verify via the rendered command string.
|
|
cmd, err := render_command("prog {{#minify}}--min{{/minify}} {{in}}", "/a", "/b", true, 0)
|
|
testing.expect(t, err == nil, "render_command should succeed (minify on)")
|
|
testing.expect(t, strings.contains(cmd, "--min"), "minify section should render when on")
|
|
|
|
cmd2, err2 := render_command("prog {{#minify}}--min{{/minify}} {{in}}", "/a", "/b", false, 0)
|
|
testing.expect(t, err2 == nil, "render_command should succeed (minify off)")
|
|
testing.expect(t, !strings.contains(cmd2, "--min"), "minify section should be empty when off")
|
|
}
|