check-dupes, clean-dupes, check-mdl, fix-mdl, convert, upscale, compile behind a single runner indirection, mirroring internal/depot's Run shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
package assets
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestCompileDrivesEngineAndReplacesInPlace(t *testing.T) {
|
|
home := t.TempDir()
|
|
userData := filepath.Join(home, ".local", "share", "Neverwinter Nights")
|
|
dev := filepath.Join(userData, "development")
|
|
mc := filepath.Join(userData, "modelcompiler")
|
|
for _, d := range []string{dev, mc} {
|
|
if err := os.MkdirAll(d, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
// Fake nwmain binary for discovery via --nwn.
|
|
binDir := t.TempDir()
|
|
nwmain := filepath.Join(binDir, "nwmain-linux")
|
|
if err := os.WriteFile(nwmain, []byte("#!/bin/sh\n"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
getenv := func(k string) string {
|
|
switch k {
|
|
case "HOME":
|
|
return home
|
|
case "DISPLAY":
|
|
return ":0" // pretend a display exists so no xvfb wrap is needed
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Stub the engine: writes a binary compiled model into modelcompiler/.
|
|
orig := runner
|
|
defer func() { runner = orig }()
|
|
runner = func(dir string, env []string, name string, args ...string) ([]byte, error) {
|
|
// args: compilemodel <stem>
|
|
stem := args[len(args)-1]
|
|
compiled := filepath.Join(mc, stem+".mdl")
|
|
return nil, os.WriteFile(compiled, []byte("\x00\x00compiled"), 0o644)
|
|
}
|
|
|
|
// Source tree with one ASCII model whose names already match its stem.
|
|
srcDir := t.TempDir()
|
|
src := filepath.Join(srcDir, "foo.mdl")
|
|
body := "newmodel foo\nbeginmodelgeom foo\n node dummy foo\n parent null\n endnode\nendmodelgeom foo\ndonemodel foo\n"
|
|
if err := os.WriteFile(src, []byte(body), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
code := runCompile([]string{"--nwn", nwmain, srcDir}, &stdout, &stderr, getenv)
|
|
if code != exitOK {
|
|
t.Fatalf("compile exit = %d\n%s", code, stderr.String())
|
|
}
|
|
// The source is now binary (the compiled artifact moved back over it).
|
|
data, err := os.ReadFile(src)
|
|
if err != nil {
|
|
t.Fatalf("compiled model missing: %v", err)
|
|
}
|
|
if string(data) != "\x00\x00compiled" {
|
|
t.Fatalf("source not replaced by compiled binary: %q", data)
|
|
}
|
|
}
|
|
|
|
func TestCompileAbortsOnNameMismatch(t *testing.T) {
|
|
home := t.TempDir()
|
|
if err := os.MkdirAll(filepath.Join(home, ".local", "share", "Neverwinter Nights", "development"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
binDir := t.TempDir()
|
|
nwmain := filepath.Join(binDir, "nwmain-linux")
|
|
if err := os.WriteFile(nwmain, []byte("#!/bin/sh\n"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
getenv := func(k string) string {
|
|
if k == "HOME" {
|
|
return home
|
|
}
|
|
if k == "DISPLAY" {
|
|
return ":0"
|
|
}
|
|
return ""
|
|
}
|
|
orig := runner
|
|
defer func() { runner = orig }()
|
|
engineCalled := false
|
|
runner = func(string, []string, string, ...string) ([]byte, error) {
|
|
engineCalled = true
|
|
return nil, nil
|
|
}
|
|
|
|
srcDir := t.TempDir()
|
|
// Internal name "wrong" != stem "foo": must abort before touching the engine.
|
|
if err := os.WriteFile(filepath.Join(srcDir, "foo.mdl"),
|
|
[]byte("newmodel wrong\ndonemodel wrong\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var stdout, stderr bytes.Buffer
|
|
if code := runCompile([]string{"--nwn", nwmain, srcDir}, &stdout, &stderr, getenv); code != exitFail {
|
|
t.Fatalf("mismatch exit = %d, want %d", code, exitFail)
|
|
}
|
|
if engineCalled {
|
|
t.Fatal("engine should not run for a name-mismatched model")
|
|
}
|
|
}
|