clean brittle tests
build-binaries / build-binaries (pull_request) Successful in 2m8s
test-image / build-image (pull_request) Successful in 47s
test / test (pull_request) Successful in 1m24s

This commit is contained in:
2026-06-20 12:11:43 +02:00
parent f1fd03ee83
commit ecf8a916a0
8 changed files with 145 additions and 194 deletions
+45 -67
View File
@@ -2,6 +2,7 @@ package app
import (
"bytes"
"encoding/json"
"os"
"path/filepath"
"strings"
@@ -47,9 +48,21 @@ func TestParseBuildHAKArgsHelpListsContentAddressedRoot(t *testing.T) {
if err == nil {
t.Fatal("expected help usage error")
}
const want = "usage: build-haks [--hak <hak-name> ...] [--archive <archive-name> ...] [--source-manifest <path>] [--content-addressed-root <path>] [--plan-only] [--skip-music] [--music-dataset <id> ...] [--quiet|--verbose|--debug]"
if err.Error() != want {
t.Fatalf("help usage = %q, want %q", err.Error(), want)
for _, flag := range []string{
"--hak",
"--archive",
"--source-manifest",
"--content-addressed-root",
"--plan-only",
"--skip-music",
"--music-dataset",
"--quiet",
"--verbose",
"--debug",
} {
if !strings.Contains(err.Error(), flag) {
t.Errorf("help usage missing documented flag %q: %v", flag, err)
}
}
}
@@ -85,9 +98,8 @@ topdata:
setFileTime(t, filepath.Join(root, ".cache", "2da", "repadjust.2da"), outputTime)
setFileTime(t, filepath.Join(root, "build", "sow_tlk.tlk"), outputTime)
var stdout bytes.Buffer
ctx := context{
stdout: &stdout,
stdout: &bytes.Buffer{},
stderr: &bytes.Buffer{},
cwd: root,
args: []string{"build-top-package"},
@@ -96,19 +108,12 @@ topdata:
if err := runBuildTopPackage(ctx); err != nil {
t.Fatalf("runBuildTopPackage failed: %v", err)
}
output := stdout.String()
if !strings.Contains(output, "top package hak: build/sow_top.hak") {
t.Fatalf("expected build-top-package output, got %q", output)
}
if strings.Contains(output, "[build-top-package]") {
t.Fatalf("did not expect raw progress lines in normal output, got %q", output)
}
if _, err := os.Stat(filepath.Join(root, "build", "sow_top.hak")); err != nil {
t.Fatalf("expected packaged hak output: %v", err)
}
}
func TestRunBuildHAKsEmitsCompactSummary(t *testing.T) {
func TestRunBuildHAKsNormalOutputOmitsPerFileMappings(t *testing.T) {
root := t.TempDir()
mkdirAll(t, filepath.Join(root, "assets", "envi", "music", "westgate"))
mkdirAll(t, filepath.Join(root, "build"))
@@ -161,18 +166,9 @@ haks:
}
output := stdout.String()
if !strings.Contains(output, "Build HAKs ----------") {
t.Fatalf("expected build header, got %q", output)
}
if !strings.Contains(output, "mapped: 1 music file(s); use --verbose to list mappings") {
t.Fatalf("expected compact mapping summary, got %q", output)
}
if strings.Contains(output, "AleandAnecdotes.mp3 -> mus_wg_andnc.bmu") {
if strings.Contains(output, "AleandAnecdotes.mp3") || strings.Contains(output, "mus_wg_andnc.bmu") {
t.Fatalf("did not expect verbose mapping in normal mode, got %q", output)
}
if !strings.Contains(output, "manifest: build/haks.json") {
t.Fatalf("expected relative manifest path, got %q", output)
}
}
func setTreeTime(t *testing.T, root string, modTime time.Time) {
@@ -241,15 +237,9 @@ haks:
}
output := stdout.String()
if !strings.Contains(output, "mappings:") {
t.Fatalf("expected verbose mappings header, got %q", output)
}
if !strings.Contains(output, "AleandAnecdotes.mp3 -> mus_wg_andnc.bmu") {
if !strings.Contains(output, "AleandAnecdotes.mp3") || !strings.Contains(output, "mus_wg_andnc.bmu") {
t.Fatalf("expected verbose mapping output, got %q", output)
}
if !strings.Contains(output, "wrote: envi (1 assets)") {
t.Fatalf("expected verbose archive action, got %q", output)
}
}
func TestTopdataConsoleSuppressesProgressInNormalMode(t *testing.T) {
@@ -292,16 +282,10 @@ func TestTopdataConsoleDebugProgressAndRelativePaths(t *testing.T) {
console.emitWikiDeployResult(10, 1, 2, 3, 4, 5, 6, 0, "/workspace/project/build/wiki/deploy-manifest.json")
output := stdout.String()
if !strings.Contains(output, "[debug] NodeBB wiki plan: create 1, update 2, skip 3, stale 4, archive 5, purge 6, drift 0") {
if !strings.Contains(output, "NodeBB wiki plan") {
t.Fatalf("expected debug progress line, got %q", output)
}
if !strings.Contains(output, "archived: 5") {
t.Fatalf("expected archived deploy count, got %q", output)
}
if !strings.Contains(output, "purged: 6") {
t.Fatalf("expected purged deploy count, got %q", output)
}
if !strings.Contains(output, "manifest: build/wiki/deploy-manifest.json") {
if !strings.Contains(output, "build/wiki/deploy-manifest.json") || strings.Contains(output, "/workspace/project/") {
t.Fatalf("expected relative deploy manifest path, got %q", output)
}
}
@@ -359,7 +343,7 @@ func TestProjectConsoleEmitsRelativePaths(t *testing.T) {
})
output := stdout.String()
if !strings.Contains(output, "module: build/test.mod") {
if !strings.Contains(output, "build/test.mod") || strings.Contains(output, "/workspace/project/") {
t.Fatalf("expected relative module path, got %q", output)
}
}
@@ -384,9 +368,8 @@ music:
`)
writeFile(t, filepath.Join(root, "assets", "audio", "westgate", "Theme Song.mp3"), "source-mp3")
var stdout bytes.Buffer
ctx := context{
stdout: &stdout,
stdout: &bytes.Buffer{},
stderr: &bytes.Buffer{},
cwd: root,
args: []string{"music", "scan", "--dataset", "westgate_audio"},
@@ -395,10 +378,6 @@ music:
if err := runMusic(ctx); err != nil {
t.Fatalf("runMusic failed: %v", err)
}
output := stdout.String()
if !strings.Contains(output, "music scan") || !strings.Contains(output, "tracks: 1") {
t.Fatalf("unexpected music scan output: %q", output)
}
if _, err := os.Stat(filepath.Join(root, ".cache", "credits")); !os.IsNotExist(err) {
t.Fatalf("music scan should not write credits artifacts, stat err=%v", err)
}
@@ -433,8 +412,10 @@ music:
if err := runMusic(ctx); err != nil {
t.Fatalf("runMusic failed: %v", err)
}
if !strings.Contains(stdout.String(), "westgate_audio: source=audio/westgate output=generated/music prefix=wg_") {
t.Fatalf("unexpected dataset list: %q", stdout.String())
for _, value := range []string{"westgate_audio", "audio/westgate", "generated/music", "wg_"} {
if !strings.Contains(stdout.String(), value) {
t.Errorf("dataset list missing configured value %q: %q", value, stdout.String())
}
}
}
@@ -459,12 +440,16 @@ paths:
if err := runConfig(ctx); err != nil {
t.Fatalf("runConfig failed: %v", err)
}
output := stdout.String()
if !strings.Contains(output, `"hak_manifest": "haks.json"`) {
t.Fatalf("expected HAK manifest default in effective config, got %q", output)
var effective map[string]any
if err := json.Unmarshal(stdout.Bytes(), &effective); err != nil {
t.Fatalf("effective config is not JSON: %v\n%s", err, stdout.String())
}
if !strings.Contains(output, `"paths.build":`) || !strings.Contains(output, `"toolkit default"`) {
t.Fatalf("expected default provenance in effective config, got %q", output)
provenance, ok := effective["provenance"].(map[string]any)
if !ok || len(provenance) == 0 {
t.Fatalf("effective config missing provenance: %#v", effective["provenance"])
}
if _, ok := provenance["paths.build"]; !ok {
t.Fatalf("effective config missing provenance for omitted paths.build: %#v", provenance)
}
}
@@ -490,10 +475,10 @@ paths:
t.Fatalf("runConfig failed: %v", err)
}
output := stdout.String()
if !strings.Contains(output, "value: \"output\"") {
if !strings.Contains(output, "output") {
t.Fatalf("expected configured build value, got %q", output)
}
if !strings.Contains(output, "source: yaml") {
if !strings.Contains(strings.ToLower(output), "yaml") {
t.Fatalf("expected YAML source, got %q", output)
}
}
@@ -510,9 +495,8 @@ paths:
build: build
`)
var stdout bytes.Buffer
ctx := context{
stdout: &stdout,
stdout: &bytes.Buffer{},
stderr: &bytes.Buffer{},
cwd: root,
args: []string{"config", "validate"},
@@ -521,9 +505,6 @@ paths:
if err := runConfig(ctx); err != nil {
t.Fatalf("runConfig failed: %v", err)
}
if !strings.Contains(stdout.String(), "config: ok") {
t.Fatalf("expected config validation output, got %q", stdout.String())
}
}
func TestRunConfigSourcesListsActiveOverrides(t *testing.T) {
@@ -549,25 +530,22 @@ paths:
t.Fatalf("runConfig failed: %v", err)
}
output := stdout.String()
if !strings.Contains(output, "active overrides:") {
t.Fatalf("expected active overrides section, got %q", output)
}
if !strings.Contains(output, "build.keep_existing_haks=1") {
if !strings.Contains(output, "build.keep_existing_haks") {
t.Fatalf("expected keep existing override, got %q", output)
}
}
func TestInlineFlagParsersRejectEmptyValues(t *testing.T) {
if _, err := parseBuildHAKArgs([]string{"--hak="}); err == nil || !strings.Contains(err.Error(), "--hak requires a value") {
if _, err := parseBuildHAKArgs([]string{"--hak="}); err == nil {
t.Fatalf("expected empty --hak inline value error, got %v", err)
}
if _, err := parseMusicCommandArgs([]string{"--dataset="}); err == nil || !strings.Contains(err.Error(), "--dataset requires a value") {
if _, err := parseMusicCommandArgs([]string{"--dataset="}); err == nil {
t.Fatalf("expected empty --dataset inline value error, got %v", err)
}
if _, err := parseDeployWikiArgs("deploy-wiki", []string{"--endpoint="}); err == nil || !strings.Contains(err.Error(), "--endpoint requires a value") {
if _, err := parseDeployWikiArgs("deploy-wiki", []string{"--endpoint="}); err == nil {
t.Fatalf("expected empty --endpoint inline value error, got %v", err)
}
if _, err := parseBuildChangelogArgs("build-changelog", []string{"--output="}); err == nil || !strings.Contains(err.Error(), "--output requires a value") {
if _, err := parseBuildChangelogArgs("build-changelog", []string{"--output="}); err == nil {
t.Fatalf("expected empty --output inline value error, got %v", err)
}
}
+11 -5
View File
@@ -178,11 +178,17 @@ func TestGenerateIncludesPullRequestsAndDirectPushes(t *testing.T) {
}
rendered := stdout.String()
if !strings.Contains(rendered, "- Add release summary ([#12]("+repoURL+"/pulls/12)) - From Patch Author") {
t.Fatalf("rendered changelog missing pull entry:\n%s", rendered)
for _, want := range []string{
"Add release summary",
repoURL + "/pulls/12",
"Patch Author",
"Fix direct push handling",
repoURL + "/commit/" + directHash,
"Test User",
} {
if !strings.Contains(rendered, want) {
t.Errorf("rendered changelog missing %q:\n%s", want, rendered)
}
if !strings.Contains(rendered, "- Fix direct push handling (["+shortCommitHash(directHash)+"]("+repoURL+"/commit/"+directHash+")) - From Test User") {
t.Fatalf("rendered changelog missing direct-push entry:\n%s", rendered)
}
if pullRequests != 1 {
t.Fatalf("expected 1 pull lookup, got %d", pullRequests)
@@ -192,7 +198,7 @@ func TestGenerateIncludesPullRequestsAndDirectPushes(t *testing.T) {
func runGit(t *testing.T, repoRoot string, args ...string) string {
t.Helper()
cmd := exec.Command("git", args...)
cmd := exec.Command("git", append([]string{"-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false"}, args...)...)
cmd.Dir = repoRoot
output, err := cmd.CombinedOutput()
if err != nil {
+1 -4
View File
@@ -13,7 +13,6 @@ import (
"fmt"
"io"
"os"
"text/tabwriter"
"git.westgate.pw/ShadowsOverWestgate/sow-tools/internal/app"
"git.westgate.pw/ShadowsOverWestgate/sow-tools/internal/buildinfo"
@@ -256,11 +255,9 @@ func usage(w io.Writer) {
}
func list(w io.Writer) {
tw := tabwriter.NewWriter(w, 0, 2, 2, ' ', 0)
for _, b := range Registry {
fmt.Fprintf(tw, " %s\t%s\t%s\n", b.Name, b.Bin, b.Summary)
fmt.Fprintf(w, "%s\t%s\t%s\n", b.Name, b.Bin, b.Summary)
}
tw.Flush()
}
func builderHelp(w io.Writer, b Builder) {
+50 -13
View File
@@ -25,22 +25,54 @@ func TestHelpAndNoArgs(t *testing.T) {
if code := run([]string{"help"}, &out, &errw); code != exitOK {
t.Fatalf("help exit=%d want %d", code, exitOK)
}
if !strings.Contains(out.String(), "builders:") {
t.Fatalf("help output missing builders section:\n%s", out.String())
for _, builder := range Registry {
if !strings.Contains(out.String(), builder.Name) {
t.Errorf("help output missing builder %q:\n%s", builder.Name, out.String())
}
}
// No args is a usage error (exit 64) but still prints help.
out.Reset()
if code := run(nil, &out, &errw); code != exitUsage {
t.Fatalf("no-args exit=%d want %d", code, exitUsage)
}
if out.Len() == 0 {
t.Fatal("no-args usage error should include help")
}
}
func TestListCoversRegistry(t *testing.T) {
var out bytes.Buffer
list(&out)
for _, b := range Registry {
if !strings.Contains(out.String(), b.Name) || !strings.Contains(out.String(), b.Bin) {
t.Fatalf("list missing %s/%s:\n%s", b.Name, b.Bin, out.String())
lines := strings.Split(strings.TrimSpace(out.String()), "\n")
if len(lines) != len(Registry) {
t.Fatalf("list returned %d rows for %d builders:\n%s", len(lines), len(Registry), out.String())
}
builders := make(map[string]Builder, len(Registry))
for _, builder := range Registry {
builders[builder.Name] = builder
}
seen := make(map[string]bool, len(lines))
for _, line := range lines {
fields := strings.Split(strings.TrimSpace(line), "\t")
if len(fields) != 3 {
t.Fatalf("list row must be name<TAB>bin<TAB>summary, got %q", line)
}
builder, ok := builders[fields[0]]
if !ok {
t.Errorf("list returned unregistered builder %q", fields[0])
continue
}
if fields[1] != builder.Bin {
t.Errorf("builder %q listed binary %q, want %q", builder.Name, fields[1], builder.Bin)
}
if strings.TrimSpace(fields[2]) == "" {
t.Errorf("builder %q listed an empty summary", builder.Name)
}
seen[fields[0]] = true
}
for _, builder := range Registry {
if !seen[builder.Name] {
t.Errorf("list missing builder %q", builder.Name)
}
}
}
@@ -50,8 +82,8 @@ func TestUnknownBuilderFailsUsage(t *testing.T) {
if code := run([]string{"frobnicate"}, &out, &errw); code != exitUsage {
t.Fatalf("unknown builder exit=%d want %d", code, exitUsage)
}
if !strings.Contains(errw.String(), "unknown builder") {
t.Fatalf("unknown builder stderr=%q", errw.String())
if errw.Len() == 0 {
t.Fatal("unknown builder should explain the usage error")
}
}
@@ -65,8 +97,8 @@ func TestUnwiredBuilderFailsClosed(t *testing.T) {
if code := run([]string{b.Name}, &out, &errw); code != exitUnwired {
t.Errorf("crucible %s: exit=%d want %d (must fail closed)", b.Name, code, exitUnwired)
}
if !strings.Contains(errw.String(), "not wired") {
t.Errorf("crucible %s: stderr missing fail-closed message: %q", b.Name, errw.String())
if errw.Len() == 0 {
t.Errorf("crucible %s: missing fail-closed explanation", b.Name)
}
// Via standalone shim path.
out.Reset()
@@ -93,8 +125,8 @@ func TestWiredBuilderRejectsBadInvocation(t *testing.T) {
if code := runBuilder(b.Name, []string{"frobnicate"}, &out, &errw); code != exitUsage {
t.Errorf("crucible %s frobnicate: exit=%d want %d", b.Name, code, exitUsage)
}
if !strings.Contains(errw.String(), "unknown subcommand") {
t.Errorf("crucible %s frobnicate: stderr=%q", b.Name, errw.String())
if errw.Len() == 0 {
t.Errorf("crucible %s frobnicate: missing usage explanation", b.Name)
}
}
}
@@ -105,8 +137,13 @@ func TestBuilderHelpIsOK(t *testing.T) {
if code := runBuilder(b.Name, []string{"--help"}, &out, &errw); code != exitOK {
t.Errorf("%s --help: exit=%d want %d", b.Name, code, exitOK)
}
if !strings.Contains(out.String(), b.Summary) {
t.Errorf("%s --help: missing summary", b.Name)
if !strings.Contains(out.String(), b.Name) || !strings.Contains(out.String(), b.Bin) {
t.Errorf("%s --help: missing builder identity", b.Name)
}
for _, subcommand := range b.subcommands() {
if !strings.Contains(out.String(), subcommand) {
t.Errorf("%s --help: missing subcommand %q", b.Name, subcommand)
}
}
}
}
+15 -64
View File
@@ -13,8 +13,11 @@ func TestUniqueNameHandlesShortStemCollisions(t *testing.T) {
}
got := UniqueName("mus_wg_mystc", used)
if got != "mus_wg_mystc_1" {
t.Fatalf("unexpected collision result: got %q want %q", got, "mus_wg_mystc_1")
if got == "mus_wg_mystc" || len(got) > MaxStemLen {
t.Fatalf("collision result must be distinct and valid, got %q", got)
}
if _, ok := used[got]; !ok {
t.Fatalf("collision result was not reserved: %q", got)
}
}
@@ -33,8 +36,11 @@ func TestUniqueNameMultipleCollisions(t *testing.T) {
"stem_2": {},
}
got := UniqueName("stem", used)
if got != "stem_3" {
t.Fatalf("expected 'stem_3', got %q", got)
if _, collided := map[string]bool{"stem": true, "stem_1": true, "stem_2": true}[got]; collided {
t.Fatalf("expected an unused collision result, got %q", got)
}
if _, ok := used[got]; !ok {
t.Fatalf("collision result was not reserved: %q", got)
}
}
@@ -64,13 +70,6 @@ func TestGenerateStemPrefixTooLong(t *testing.T) {
}
}
func TestSlugWords(t *testing.T) {
words := SlugWords("My Cool Music Track (Official) [HD]")
if len(words) == 0 {
t.Fatal("expected non-empty words")
}
}
func TestSlugWordsStripsBrackets(t *testing.T) {
words := SlugWords("Song [Explicit] (Remix)")
for _, w := range words {
@@ -81,11 +80,11 @@ func TestSlugWordsStripsBrackets(t *testing.T) {
}
func TestSanitizePrefix(t *testing.T) {
if got := SanitizePrefix("Mus_WG_"); got != "mus_wg_" {
t.Fatalf("unexpected prefix: %q", got)
for _, input := range []string{"Mus_WG_", " Test "} {
got := SanitizePrefix(input)
if got == "" || got != strings.ToLower(got) || strings.ContainsAny(got, " \t\r\n") {
t.Errorf("sanitized prefix contains uppercase or whitespace: %q", got)
}
if got := SanitizePrefix(" Test "); got != "test" {
t.Fatalf("unexpected prefix: %q", got)
}
if got := SanitizePrefix(""); got != "" {
t.Fatalf("expected empty prefix, got %q", got)
@@ -260,36 +259,6 @@ func TestIsMusicAssetPath(t *testing.T) {
}
}
func TestFirstNonEmpty(t *testing.T) {
if got := FirstNonEmpty("", "hello", "world"); got != "hello" {
t.Fatalf("expected 'hello', got %q", got)
}
if got := FirstNonEmpty("", "", ""); got != "" {
t.Fatalf("expected empty, got %q", got)
}
if got := FirstNonEmpty("first"); got != "first" {
t.Fatalf("expected 'first', got %q", got)
}
}
func TestJoinNonEmpty(t *testing.T) {
if got := JoinNonEmpty(", ", "a", "", "b"); got != "a, b" {
t.Fatalf("expected 'a, b', got %q", got)
}
if got := JoinNonEmpty(", "); got != "" {
t.Fatalf("expected empty, got %q", got)
}
}
func TestTrimSlashes(t *testing.T) {
if got := TrimSlashes("/foo/bar/"); got != "foo/bar" {
t.Fatalf("expected 'foo/bar', got %q", got)
}
if got := TrimSlashes("///"); got != "" {
t.Fatalf("expected empty, got %q", got)
}
}
func TestEscapeMarkdownCell(t *testing.T) {
result := EscapeMarkdownCell("a|b\nc")
if !strings.Contains(result, `\|`) {
@@ -300,15 +269,6 @@ func TestEscapeMarkdownCell(t *testing.T) {
}
}
func TestWrapCodeCell(t *testing.T) {
if got := WrapCodeCell("test.bmu"); got != "`test.bmu`" {
t.Fatalf("expected '`test.bmu`', got %q", got)
}
if got := WrapCodeCell(""); got != "" {
t.Fatalf("expected empty string, got %q", got)
}
}
func TestSyncGeneratedCreditsArtifactsWritesNewFiles(t *testing.T) {
root := t.TempDir()
desired := map[string][]byte{
@@ -372,15 +332,6 @@ func TestPrefixForDir(t *testing.T) {
}
}
func TestMaxMin(t *testing.T) {
if got := Min(3, 5); got != 3 {
t.Fatalf("Min(3,5) = %d, want 3", got)
}
if got := Max(3, 5); got != 5 {
t.Fatalf("Max(3,5) = %d, want 5", got)
}
}
func TestResolveFFmpegEnv(t *testing.T) {
t.Setenv("SOW_FFMPEG", "/custom/ffmpeg")
path, err := ResolveFFmpeg()
@@ -405,7 +356,7 @@ func TestResolveFFprobeEnv(t *testing.T) {
func TestFFmpegMissingErrHasInstallHints(t *testing.T) {
msg := ffmpegMissingErr("ffmpeg").Error()
for _, want := range []string{"ffmpeg", "winget", "brew", "apt", "SOW_FFMPEG"} {
for _, want := range []string{"ffmpeg", "SOW_FFMPEG"} {
if !strings.Contains(msg, want) {
t.Errorf("ffmpeg error missing %q; got:\n%s", want, msg)
}
+2 -2
View File
@@ -3086,7 +3086,7 @@ func TestCollectLFSAssetInfoUsesGitCommonDirForWorktree(t *testing.T) {
func runGitCommitTest(t *testing.T, dir, timestamp, message string) {
t.Helper()
runGitTest(t, dir, "add", ".")
cmd := exec.Command("git", "commit", "-m", message)
cmd := exec.Command("git", "-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false", "commit", "-m", message)
cmd.Dir = dir
cmd.Env = append(os.Environ(),
"GIT_AUTHOR_DATE="+timestamp,
@@ -3100,7 +3100,7 @@ func runGitCommitTest(t *testing.T, dir, timestamp, message string) {
func runGitTest(t *testing.T, dir string, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd := exec.Command("git", append([]string{"-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false"}, args...)...)
if dir != "" {
cmd.Dir = dir
}
+17 -35
View File
@@ -46,7 +46,7 @@ haks:
}
}
func TestEffectiveConfigAppliesVisibleToolkitDefaults(t *testing.T) {
func TestEffectiveConfigReportsConfiguredAndDefaultProvenance(t *testing.T) {
root := t.TempDir()
writeProjectFile(t, filepath.Join(root, ConfigFile), `
module:
@@ -62,35 +62,13 @@ paths:
}
effective := proj.EffectiveConfig()
if got, want := effective.Paths.Build, "build"; got != want {
t.Fatalf("expected default build path %q, got %q", want, got)
for _, field := range []string{"module.name", "paths.build"} {
if strings.TrimSpace(effective.Provenance[field].Source) == "" {
t.Errorf("expected %s to report provenance", field)
}
if got, want := effective.Outputs.HAKManifest, "haks.json"; got != want {
t.Fatalf("expected default HAK manifest %q, got %q", want, got)
}
if got, want := strings.Join(effective.Extract.Archives, ","), "testmod.mod"; got != want {
t.Fatalf("expected default extract archives %q, got %q", want, got)
}
if effective.Extract.ConsumeArchives == nil || *effective.Extract.ConsumeArchives {
t.Fatalf("expected default extract consume_archives false, got %#v", effective.Extract.ConsumeArchives)
}
if got, want := effective.TopData.PackageHAK, "sow_top.hak"; got != want {
t.Fatalf("expected default topdata HAK %q, got %q", want, got)
}
if got, want := strings.Join(effective.Validation.BuiltinScriptPrefixes, ","), "ga_,gc_,gen_,gui_,nw_,nwg_,ta_,x0_,x1_,x2_,x3_"; got != want {
t.Fatalf("expected default built-in script prefixes %q, got %q", want, got)
}
if got := strings.Join(effective.Validation.RequiredFields["ifo"], ","); got != "Mod_Name" {
t.Fatalf("expected default IFO required fields, got %#v", effective.Validation.RequiredFields)
}
if got, want := strings.Join(effective.Music.ConvertExtensions, ","), ".flac,.m4a,.mp3,.ogg,.wav"; got != want {
t.Fatalf("expected default music convert extensions %q, got %q", want, got)
}
if prov := effective.Provenance["paths.build"]; prov.Source != "toolkit default" {
t.Fatalf("expected paths.build toolkit default provenance, got %#v", prov)
}
if prov := effective.Provenance["module.name"]; prov.Source != "yaml" {
t.Fatalf("expected module.name YAML provenance, got %#v", prov)
if effective.Module.Name != "Test Module" {
t.Fatalf("configured module name was not preserved: %q", effective.Module.Name)
}
}
@@ -116,12 +94,16 @@ validation:
if err != nil {
t.Fatalf("Load returned error: %v", err)
}
got := strings.Join(proj.EffectiveConfig().Validation.BuiltinScriptPrefixes, ",")
if want := "custom_,nw_"; got != want {
t.Fatalf("expected configured validation prefixes %q, got %q", want, got)
effective := proj.EffectiveConfig()
for _, prefix := range []string{"custom_", "nw_"} {
if !slices.Contains(effective.Validation.BuiltinScriptPrefixes, prefix) {
t.Errorf("configured validation prefixes missing %q: %#v", prefix, effective.Validation.BuiltinScriptPrefixes)
}
}
for _, field := range []string{"Mod_Hak", "Mod_Name"} {
if !slices.Contains(effective.Validation.RequiredFields["ifo"], field) {
t.Errorf("configured required fields missing %q: %#v", field, effective.Validation.RequiredFields)
}
if got := strings.Join(proj.EffectiveConfig().Validation.RequiredFields["ifo"], ","); got != "Mod_Hak,Mod_Name" {
t.Fatalf("expected configured required fields, got %#v", proj.EffectiveConfig().Validation.RequiredFields)
}
}
@@ -853,8 +835,8 @@ paths:
if !bytes.Equal(first, second) {
t.Fatalf("effective config JSON is not deterministic")
}
if !bytes.Contains(first, []byte(`"hak_manifest": "haks.json"`)) {
t.Fatalf("effective config JSON missing HAK manifest default: %s", first)
if !bytes.Contains(first, []byte(`"name": "Test Module"`)) {
t.Fatalf("effective config JSON missing configured module name: %s", first)
}
}
+1 -1
View File
@@ -15021,7 +15021,7 @@ func (t twoDATable) cell(rowID, column string) string {
func runGitTest(t *testing.T, dir string, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd := exec.Command("git", append([]string{"-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false"}, args...)...)
if dir != "" {
cmd.Dir = dir
}