package docsite import ( "strings" "testing" ) // knownFenceLangs is what a fence in this corpus may declare. Adding a // language here is a deliberate act: an undeclared or unknown fence is // invisible to every content gate that reads fences, so it is a way to // smuggle a wrong command past review. var knownFenceLangs = map[string]bool{ "sh": true, "bash": true, "console": true, "json": true, "go": true, "yaml": true, "toml": true, "ini": true, "text": true, "http": true, // python, for the callback verifier on scan-callbacks.md. The page ships // a second implementation on purpose: most people writing a webhook // verifier against this platform are not writing Go, and the one mistake // that page exists to prevent (hex secret, raw-byte key) is the one they // make in whatever language they are in. "python": true, } func TestFenceLanguagesAreDeclared(t *testing.T) { site, err := Load(root) if err != nil { t.Fatalf("load: %v", err) } for _, p := range site.Pages() { for _, f := range p.Fences { if f.Lang == "" { t.Errorf("%s.md:%d: fence declares no language", p.Slug, f.Line) continue } if !knownFenceLangs[f.Lang] { t.Errorf("%s.md:%d: unknown fence language %q — add it to knownFenceLangs if it is real", p.Slug, f.Line, f.Lang) } } } } // TestTestdataFencesDeclareLanguages runs the same rule against the // testdata corpus, so the gate above is proven to work on a corpus that // exists before docs/site does. func TestTestdataFencesDeclareLanguages(t *testing.T) { site, err := Load(testCorpus) if err != nil { t.Fatalf("load: %v", err) } for _, p := range site.Pages() { for _, f := range p.Fences { if f.Lang == "" { t.Errorf("%s: testdata corpus has an undeclared fence at line %d", p.Slug, f.Line) } } } } // TestFencedCarlosCommandsAreReal checks the examples, not just the // prose. A renamed verb leaves every fence containing it copy-pasteable // and wrong, and nothing else in this package would notice. func TestFencedCarlosCommandsAreReal(t *testing.T) { site, err := Load(root) if err != nil { t.Fatalf("load: %v", err) } cmds, err := TopLevelCommands(mainFile) if err != nil { t.Fatalf("scan: %v", err) } real := map[string]bool{} for _, c := range cmds { real[c] = true } for _, p := range site.Pages() { for _, f := range p.Fences { for _, verb := range fencedCarlosVerbs(f.Body) { if !real[verb] { t.Errorf("%s.md:%d: example runs `carlos %s`, which is not a command", p.Slug, f.Line, verb) } } } } } // fencedCarlosVerbs returns the word after each "carlos" in a fence // body. It skips lines where "carlos" is not the command being run — // a path like /opt/carlos/carlos, or prose inside a comment. func fencedCarlosVerbs(body string) []string { var out []string for _, line := range strings.Split(body, "\n") { line = strings.TrimSpace(line) line = strings.TrimPrefix(line, "$ ") // Treat # as starting a comment only when it is at index 0 or // preceded by a space or tab. A # with a non-space before it // (like a URL fragment) is not a comment. if i := strings.Index(line, "#"); i >= 0 && (i == 0 || line[i-1] == ' ' || line[i-1] == '\t') { line = strings.TrimSpace(line[:i]) } fields := strings.Fields(line) for i, f := range fields { // Bare "carlos", or the binary called by an absolute path — // runbooks on a box invoke /opt/carlos/carlos, and those // examples go stale the same way. if f != "carlos" && !strings.HasSuffix(f, "/carlos") { continue } if i+1 >= len(fields) { continue } next := fields[i+1] if strings.HasPrefix(next, "-") { continue } if next == "\\" { continue } out = append(out, next) } } return out } // TestFencedCarlosVerbsIgnoresNoise pins the parsing, because a // permissive extractor turns the gate above into one that finds // nothing. func TestFencedCarlosVerbsIgnoresNoise(t *testing.T) { body := strings.Join([]string{ "carlos ship --app hello ./dist", "$ carlos promote --app hello abc123 edge", "/opt/carlos/carlos adopt", "# run carlos deploy afterwards", "carlos -h", "echo carlos", }, "\n") got := fencedCarlosVerbs(body) want := []string{"ship", "promote", "adopt"} if len(got) != len(want) { t.Fatalf("got %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("got %v, want %v", got, want) } } } // TestFencedCarlosVerbsCompoundLines verifies the extractor finds // multiple carlos invocations on a single line (Finding 1 fix). func TestFencedCarlosVerbsCompoundLines(t *testing.T) { body := "carlos ship --app hello ./dist && carlos promote --app hello abc123 edge" got := fencedCarlosVerbs(body) want := []string{"ship", "promote"} if len(got) != len(want) { t.Fatalf("got %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("got %v, want %v", got, want) } } } // TestFencedCarlosVerbsURLFragment verifies the extractor does not // mistake URL fragments for comments (Finding 2 fix). func TestFencedCarlosVerbsURLFragment(t *testing.T) { body := "curl -s https://carlosframework.com/docs/#cli && carlos ship --app website ./dist" got := fencedCarlosVerbs(body) want := []string{"ship"} if len(got) != len(want) { t.Fatalf("got %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("got %v, want %v", got, want) } } } // TestFencedCarlosVerbsBackslashContinuation verifies the extractor // does not extract backslash as a verb in line-continued invocations // (Finding 3 fix). func TestFencedCarlosVerbsBackslashContinuation(t *testing.T) { body := "carlos \\" got := fencedCarlosVerbs(body) want := []string{} if len(got) != len(want) { t.Fatalf("got %v, want %v", got, want) } }