package run // Tests for --append-system-prompt value resolution (mirrors pi): each value is // either a path to an existing file whose contents are appended, or literal // text when it is not an existing file. A value that names an unreadable file // (a real I/O error other than not-exist) is surfaced rather than silently // appended verbatim. import ( "os" "path/filepath" "testing" ) // TestResolveAppendInstructionsEmpty verifies no values yields no appends. func TestResolveAppendInstructionsEmpty(t *testing.T) { out, err := resolveAppendInstructions(nil) if err != nil { t.Fatalf("resolveAppendInstructions: %v", err) } if out != nil { t.Errorf("expected nil for no values, got %#v", out) } } // TestResolveAppendInstructionsLiteral verifies a value that is not an existing // file is treated as literal text and passed through verbatim. func TestResolveAppendInstructionsLiteral(t *testing.T) { out, err := resolveAppendInstructions([]string{"be concise and helpful"}) if err != nil { t.Fatalf("resolveAppendInstructions: %v", err) } if len(out) != 1 || out[0] != "be concise and helpful" { t.Errorf("literal text must pass through verbatim, got %#v", out) } } // TestResolveAppendInstructionsFile verifies a value that names an existing // file has its contents read and appended. func TestResolveAppendInstructionsFile(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "guidance.txt") if err := os.WriteFile(path, []byte("FILE GUIDANCE"), 0o644); err != nil { t.Fatalf("write temp file: %v", err) } out, err := resolveAppendInstructions([]string{path, "literal tail"}) if err != nil { t.Fatalf("resolveAppendInstructions: %v", err) } if len(out) != 2 { t.Fatalf("expected 2 resolved values, got %#v", out) } if out[0] != "FILE GUIDANCE" { t.Errorf("existing file must be read into the append, got %q", out[0]) } if out[1] != "literal tail" { t.Errorf("literal value must pass through verbatim, got %q", out[1]) } } // TestResolveAppendInstructionsUnreadableFile verifies a value that looks like a // path but points at an unreadable file (here, a directory) surfaces an error // rather than being appended verbatim. A directory is used because os.Stat // succeeds on it (so it is not treated as literal text) while os.ReadFile fails. func TestResolveAppendInstructionsUnreadableFile(t *testing.T) { dir := t.TempDir() // A directory: Stat succeeds and IsDir() is true, so it is treated as literal // text — assert that. Then create an actually-unreadable regular file to hit // the read-error path. if out, err := resolveAppendInstructions([]string{dir}); err != nil { t.Fatalf("a directory should be treated as literal text, got error: %v", err) } else if len(out) != 1 || out[0] != dir { t.Errorf("a directory path must pass through as literal text, got %#v", out) } unreadable := filepath.Join(dir, "secret.txt") if err := os.WriteFile(unreadable, []byte("nope"), 0o000); err != nil { t.Fatalf("write temp file: %v", err) } // Root can read 0o000 files, so skip the read-error assertion when running as // root (common in CI containers) — the path would succeed instead of erroring. if os.Geteuid() == 0 { t.Skip("running as root: 0o000 file is still readable, cannot exercise read-error path") } if _, err := resolveAppendInstructions([]string{unreadable}); err == nil { t.Error("an unreadable append file must surface an error, got nil") } }