Files
sow-tools/internal/dispatch/dispatch_test.go
T
archvillainette 93433e3f53
test-image / build-image (push) Successful in 44s
test / test (push) Successful in 1m20s
build-binaries / build-binaries (push) Successful in 2m0s
build-image / publish (push) Successful in 12s
Cross-Platform Crucible (#2)
Crucible groundwork for cross-platform compatibility.

Reviewed-on: #2
Reviewed-by: xtul <mpiasecki720@protonmail.com>
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
2026-06-16 13:52:19 +00:00

157 lines
4.5 KiB
Go

package dispatch
import (
"bytes"
"strings"
"testing"
)
func TestVersion(t *testing.T) {
var out, errw bytes.Buffer
for _, arg := range []string{"version", "-V", "--version"} {
out.Reset()
errw.Reset()
if code := run([]string{arg}, &out, &errw); code != exitOK {
t.Fatalf("%s: exit=%d want %d", arg, code, exitOK)
}
if !strings.HasPrefix(out.String(), "crucible ") {
t.Fatalf("%s: version line %q missing prefix", arg, out.String())
}
}
}
func TestHelpAndNoArgs(t *testing.T) {
var out, errw bytes.Buffer
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())
}
// 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)
}
}
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())
}
}
}
func TestUnknownBuilderFailsUsage(t *testing.T) {
var out, errw bytes.Buffer
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())
}
}
func TestUnwiredBuilderFailsClosed(t *testing.T) {
for _, b := range Registry {
if b.Wired {
continue
}
var out, errw bytes.Buffer
// Via dispatcher.
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())
}
// Via standalone shim path.
out.Reset()
errw.Reset()
if code := runBuilder(b.Name, nil, &out, &errw); code != exitUnwired {
t.Errorf("%s: exit=%d want %d (must fail closed)", b.Bin, code, exitUnwired)
}
}
}
func TestWiredBuilderRejectsBadInvocation(t *testing.T) {
for _, b := range Registry {
if !b.Wired {
continue
}
// No subcommand is a usage error (it must never silently delegate).
var out, errw bytes.Buffer
if code := runBuilder(b.Name, nil, &out, &errw); code != exitUsage {
t.Errorf("crucible %s (no subcommand): exit=%d want %d", b.Name, code, exitUsage)
}
// Unknown subcommand is a usage error, not a delegate.
out.Reset()
errw.Reset()
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())
}
}
}
func TestBuilderHelpIsOK(t *testing.T) {
for _, b := range Registry {
var out, errw bytes.Buffer
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)
}
}
}
// Every legacy command named in command-surface.md must have exactly one
// canonical home (Builder.Legacy), so the migrated surface has no gaps or
// ambiguous homes.
func TestLegacyCommandsHaveExactlyOneHome(t *testing.T) {
legacy := []string{
"build", "build-module", "extract", "validate", "compare",
"build-haks", "apply-hak-manifest",
"validate-topdata", "build-topdata", "build-top-package", "compare-topdata", "convert-topdata",
"build-wiki", "deploy-wiki",
}
for _, cmd := range legacy {
homes := 0
for _, b := range Registry {
for _, c := range b.Legacy {
if c == cmd {
homes++
}
}
}
if homes != 1 {
t.Errorf("legacy command %q has %d canonical homes, want 1", cmd, homes)
}
}
}
func TestMenuItemsSkipsUnwiredIncludesWired(t *testing.T) {
items := menuItems()
if len(items) == 0 {
t.Fatal("expected menu items")
}
sawModuleBuild := false
for _, it := range items {
if it.Args[0] == "depot" {
t.Errorf("unwired builder %q must not appear in the menu", it.Args[0])
}
if len(it.Args) == 2 && it.Args[0] == "module" && it.Args[1] == "build" {
sawModuleBuild = true
}
}
if !sawModuleBuild {
t.Error("expected 'module build' in the menu")
}
}