test(01-04): cover tool, output, watch loop and workspace modules
- Non-TTY widgets/prompts, flag parsing, secret non-leak and malicious IDs - Real hello workspace rebuild latency line, debounce and ignored bin/tmp - scripts/check-phase1.sh runs vet/test/race across root, hello, base, greeter, optional
This commit is contained in:
@@ -263,6 +263,65 @@ func TestAddPluginRejectsPathTraversal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseManifestRejectsDuplicateModule(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "dupmod.yaml")
|
||||
write(t, path, "module: example.com/app\nbinary: app\nplugins:\n - id: a.b\n module: example.com/one\n - id: a.c\n module: example.com/one\n")
|
||||
if _, err := LoadManifest(path); err == nil || !strings.Contains(err.Error(), "example.com/one") {
|
||||
t.Fatalf("want duplicate module error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakePluginRejectsPathTraversalAndShellMeta(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
write(t, filepath.Join(dir, "summer.yaml"), "module: example.com/app\nbinary: app\nplugins:\n")
|
||||
write(t, filepath.Join(dir, "go.mod"), "module example.com/app\n\ngo 1.27.0\n")
|
||||
for _, id := range []string{
|
||||
"golem15.demo/../tmp",
|
||||
"golem15.demo;rm",
|
||||
`golem15.demo$(x)`,
|
||||
"golem15.demo`x`",
|
||||
"/tmp.evil",
|
||||
"..evil.plugin",
|
||||
} {
|
||||
if _, err := MakePlugin(t.Context(), dir, id); err == nil {
|
||||
t.Fatalf("id %q: want error", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuiltHelloFailsOnInvalidRequires(t *testing.T) {
|
||||
dir := copyHelloApp(t)
|
||||
path := filepath.Join(dir, "plugins", "greeter", "plugin.go")
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
patched := bytes.ReplaceAll(src, []byte(`return []string{"golem15.hello"}`), []byte(`return []string{"golem15.hello", "golem15.missing"}`))
|
||||
if bytes.Equal(src, patched) {
|
||||
t.Fatal("failed to patch greeter Requires")
|
||||
}
|
||||
if err := os.WriteFile(path, patched, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := App(t.Context(), dir, &buf); err != nil {
|
||||
t.Fatalf("build should succeed, got %v\n%s", err, buf.String())
|
||||
}
|
||||
bin := filepath.Join(dir, "bin", "hello")
|
||||
cmd := exec.CommandContext(t.Context(), bin, "greeter:hello")
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
t.Fatalf("expected non-zero exit for missing Requires, output:\n%s", out)
|
||||
}
|
||||
msg := string(out)
|
||||
if !strings.Contains(msg, "golem15.greeter") || !strings.Contains(msg, "golem15.missing") {
|
||||
t.Fatalf("error should name both plugin IDs, got %q", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseManifestRejectsUppercaseID(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "bad.yaml")
|
||||
|
||||
Reference in New Issue
Block a user