repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

13.6 KB · 367 lines · Go Raw History
  1package main
  2
  3import (
  4	"strings"
  5	"testing"
  6)
  7
  8func TestCodeBlocksReadsFilesAndFences(t *testing.T) {
  9	md := "Here it is.\n\n**app.py**\n\n```python\nprint(1)\n```\n\n## Run it\n\n```sh\npython app.py\n```\n"
 10	blocks := codeBlocks(md)
 11	if len(blocks) != 2 {
 12		t.Fatalf("want 2 blocks, got %d", len(blocks))
 13	}
 14	if blocks[0].File != "app.py" || blocks[0].Lang != "python" || blocks[0].Code != "print(1)" {
 15		t.Errorf("first block wrong: %+v", blocks[0])
 16	}
 17	// The bold line above the second one is a heading and not a file name.
 18	if blocks[1].File != "" || blocks[1].Lang != "sh" {
 19		t.Errorf("second block wrong: %+v", blocks[1])
 20	}
 21	for _, b := range blocks {
 22		if !b.Closed {
 23			t.Errorf("block %q should be closed", b.Lang)
 24		}
 25	}
 26}
 27
 28func TestCodeBlocksSpotsATruncatedOne(t *testing.T) {
 29	blocks := codeBlocks("```go\nfunc main() {\n")
 30	if len(blocks) != 1 || blocks[0].Closed {
 31		t.Fatalf("an unclosed fence should come back open: %+v", blocks)
 32	}
 33	checks := checkCode(blocks)
 34	if len(checks) != 1 || checks[0].OK {
 35		t.Fatalf("a truncated block should fail: %+v", checks)
 36	}
 37	if !checks[0].Truncated {
 38		t.Error("a block that ran out of room should be marked truncated")
 39	}
 40	// Running out of room is not something a second search fixes.
 41	if codeFailed(checks, nil) {
 42		t.Error("truncation should not trigger a re-search")
 43	}
 44}
 45
 46func TestStripCodeCitationsLeavesIndexesAlone(t *testing.T) {
 47	md := "Reads the file [2].\n\n```python\nrows = data[0]  # [3]\nprint(rows) [4]\n```\n\nAnd that is it [5].\n"
 48	got := stripCodeCitations(md)
 49	if !strings.Contains(got, "rows = data[0]") {
 50		t.Error("an array index inside code was removed")
 51	}
 52	if strings.Contains(got, "print(rows) [4]") {
 53		t.Error("a trailing citation inside code survived")
 54	}
 55	if !strings.Contains(got, "Reads the file [2].") || !strings.Contains(got, "that is it [5].") {
 56		t.Error("prose citations were removed")
 57	}
 58}
 59
 60func TestProseOnlyDropsTheCode(t *testing.T) {
 61	md := "One sentence [1].\n\n```python\nassert x == 1\n```\n\nAnother [2].\n"
 62	got := proseOnly(md)
 63	if strings.Contains(got, "assert") {
 64		t.Errorf("code survived into the prose: %q", got)
 65	}
 66	if !strings.Contains(got, "One sentence [1].") || !strings.Contains(got, "Another [2].") {
 67		t.Errorf("prose was lost: %q", got)
 68	}
 69}
 70
 71func TestTidyCitationsSkipsCode(t *testing.T) {
 72	md := "```python\nprint(a[0], b[0], c[0])\n```\n"
 73	if got := tidyCitations(md); got != md {
 74		t.Errorf("code was rewritten:\n%s", got)
 75	}
 76}
 77
 78func TestRenderDoesNotLinkifyInsideCode(t *testing.T) {
 79	html := renderMarkdown("Prose [1].\n\n```python\nx = rows[0]\n```\n")
 80	if strings.Contains(html, `data-passage="0"`) {
 81		t.Errorf("an index in a code block became a citation link:\n%s", html)
 82	}
 83	if !strings.Contains(html, `data-passage="1"`) {
 84		t.Errorf("the prose citation was not linked:\n%s", html)
 85	}
 86}
 87
 88func TestGoSyntaxCatchesABrokenFile(t *testing.T) {
 89	good := CodeBlock{Lang: "go", Closed: true, Code: "package main\n\nfunc main() {\n\tprintln(\"hi\")\n}\n"}
 90	if note := inspect(good); note != "" {
 91		t.Errorf("good Go was rejected: %s", note)
 92	}
 93	// A snippet with no package clause is still valid Go to show somebody.
 94	snippet := CodeBlock{Lang: "go", Closed: true, Code: "func add(a, b int) int { return a + b }"}
 95	if note := inspect(snippet); note != "" {
 96		t.Errorf("a snippet was rejected: %s", note)
 97	}
 98	bad := CodeBlock{Lang: "go", Closed: true, Code: "package main\n\nfunc main() {\n\tprintln(\"hi\"\n}\n"}
 99	if note := inspect(bad); note == "" {
100		t.Error("a missing paren was not caught")
101	}
102}
103
104func TestBalanceIgnoresBracketsInStringsAndComments(t *testing.T) {
105	code := strings.Join([]string{
106		`# a comment with an unmatched ) in it`,
107		`msg = "a string with ( and [ inside"`,
108		`other = 'and ) here'`,
109		`doc = """`,
110		`  a docstring with { unmatched`,
111		`"""`,
112		`print(msg)`,
113	}, "\n")
114	if note := balance(code, pythonScan); note != "" {
115		t.Errorf("false alarm on valid Python: %s", note)
116	}
117}
118
119func TestBalanceCatchesARealUnclosedBracket(t *testing.T) {
120	if note := balance("def f():\n    return g(1, 2\n", pythonScan); note == "" {
121		t.Error("an unclosed call was not caught")
122	}
123	if note := balance("x = 1)\n", pythonScan); !strings.Contains(note, "closes nothing") {
124		t.Errorf("a stray close was not caught, got %q", note)
125	}
126}
127
128func TestPythonIndentCatchesMixedWhitespace(t *testing.T) {
129	if note := pythonIndent("def f():\n    return 1\n\ndef g():\n\treturn 2\n"); note == "" {
130		t.Error("mixed tabs and spaces were not caught")
131	}
132	if note := pythonIndent("def f():\n    return 1\n"); note != "" {
133		t.Errorf("consistent spaces were flagged: %s", note)
134	}
135}
136
137func TestDockerfileSyntax(t *testing.T) {
138	ok := "# comment\nARG VERSION=1\nFROM ollama/ollama:latest\nENV OLLAMA_HOST=0.0.0.0\nRUN apt-get update \\\n    && apt-get install -y curl\nEXPOSE 11434\n"
139	if note := dockerfileSyntax(ok); note != "" {
140		t.Errorf("a good Dockerfile was rejected: %s", note)
141	}
142	if note := dockerfileSyntax("RUN echo hi\n"); note == "" {
143		t.Error("an instruction before FROM was allowed")
144	}
145	if note := dockerfileSyntax("FROM alpine\nINSTALL curl\n"); !strings.Contains(note, "INSTALL") {
146		t.Errorf("an invented instruction was allowed, got %q", note)
147	}
148	if note := dockerfileSyntax("# just a comment\n"); note == "" {
149		t.Error("a Dockerfile with no FROM was allowed")
150	}
151}
152
153func TestHTMLBalance(t *testing.T) {
154	page := `<!doctype html><html><head><meta charset="utf-8"><title>x</title></head>` +
155		`<body><div class="map"><p>hello<br><img src="a.png"></div><script>var a = 1;</script></body></html>`
156	if note := htmlBalance(page); note != "" {
157		t.Errorf("a good page was rejected: %s", note)
158	}
159	if note := htmlBalance("<html><body><div>stopped here"); note == "" {
160		t.Error("a truncated page was not caught")
161	}
162}
163
164func TestPlaceholderDetection(t *testing.T) {
165	cases := map[string]bool{
166		"def f():\n    ...\n":                              true,
167		"# rest of the code here\n":                        true,
168		"app.run()  # TODO: implement caching\n":           true,
169		"headers = {}  # your code here\n":                 true,
170		"# This is a conceptual example of the command.\n": true,
171		"# In a real environment, this would invoke it.\n": true,
172		"x = data[...]\n":                                  false,
173		"print('this has an ellipsis in a string ...')\n":  false,
174	}
175	for code, want := range cases {
176		if got := placeholderIn(code) != ""; got != want {
177			t.Errorf("placeholderIn(%q) = %v, want %v", code, got, want)
178		}
179	}
180}
181
182func TestNormalLangFallsBackToTheFileName(t *testing.T) {
183	if got := normalLang("", "server.py"); got != "python" {
184		t.Errorf("got %q", got)
185	}
186	if got := normalLang("", "Dockerfile"); got != "dockerfile" {
187		t.Errorf("got %q", got)
188	}
189	if got := normalLang("yml", ""); got != "yaml" {
190		t.Errorf("got %q", got)
191	}
192}
193
194func TestCodeWarningsOnlyNamesFailures(t *testing.T) {
195	checks := []CodeCheck{
196		{File: "app.py", Lang: "python", OK: true, Note: "brackets balance"},
197		{File: "", Lang: "go", OK: false, Note: "does not parse: 3:1 expected }"},
198	}
199	warns := codeWarnings(checks)
200	if len(warns) != 1 {
201		t.Fatalf("want one warning, got %v", warns)
202	}
203	if !strings.Contains(warns[0], "the go block") {
204		t.Errorf("an unnamed block should be described by its language, got %q", warns[0])
205	}
206}
207
208func TestCodeWeightPrefersPagesWithCode(t *testing.T) {
209	docs := &Page{Site: "docs.docker.com", Markdown: "text\n```sh\ndocker run\n```\n"}
210	blog := &Page{Site: "someblog.example", Markdown: "no code here at all"}
211	if codeWeight(docs) <= codeWeight(blog) {
212		t.Errorf("docs page scored %d, blog scored %d", codeWeight(docs), codeWeight(blog))
213	}
214}
215
216func TestFileNameWithAPrefix(t *testing.T) {
217	blocks := codeBlocks("**File: world-heat-map.html**\n\n```html\n<p>hi</p>\n```\n")
218	if len(blocks) != 1 || blocks[0].File != "world-heat-map.html" {
219		t.Fatalf("got %+v", blocks)
220	}
221}
222
223func TestFileInComment(t *testing.T) {
224	blocks := codeBlocks("```python\n# restic_daily_backup.py\nimport os\n```\n")
225	if len(blocks) != 1 || blocks[0].File != "restic_daily_backup.py" {
226		t.Fatalf("a file name in a leading comment was not picked up: %+v", blocks)
227	}
228	// The comment goes with it, so the line count matches what the reader sees.
229	if blocks[0].Code != "import os" {
230		t.Errorf("the comment was left in the code: %q", blocks[0].Code)
231	}
232	// A first line that is a real comment is not a file name.
233	plain := codeBlocks("```python\n# read the config\nimport os\n```\n")
234	if plain[0].File != "" {
235		t.Errorf("a comment was read as a file name: %q", plain[0].File)
236	}
237}
238
239func TestDropMetaTakesTheOpenerAndLeavesTheCode(t *testing.T) {
240	md := "This response provides a Dockerfile to run Ollama, citing the relevant passages.\n\n```dockerfile\nFROM ollama/ollama\n```\n"
241	got := dropMeta(md)
242	if strings.Contains(got, "This response") {
243		t.Errorf("meta sentence survived:\n%s", got)
244	}
245	if !strings.Contains(got, "FROM ollama/ollama") {
246		t.Errorf("code was lost:\n%s", got)
247	}
248	// A sentence mid-line goes without taking the useful half with it.
249	mixed := dropMeta("Flask serves the cache. This answer uses two files.")
250	if mixed != "Flask serves the cache." {
251		t.Errorf("got %q", mixed)
252	}
253}
254
255func TestDropMissingFieldsSkipsCode(t *testing.T) {
256	md := "```python\nvalue = \"not provided\"\n```\n"
257	if got := dropMissingFields(md); !strings.Contains(got, "not provided") {
258		t.Errorf("a code line was dropped:\n%s", got)
259	}
260	if got := dropMissingFields("Total Time: Not specified\n"); got != "" {
261		t.Errorf("a missing field line survived: %q", got)
262	}
263}
264
265func TestUnusedConstants(t *testing.T) {
266	dead := []CodeBlock{{Lang: "python", File: "api.py", Closed: true,
267		Code: "CACHE_AGE = 3600\nPORT = 5000\n\ndef main():\n    app.run(port=PORT)\n"}}
268	warns := unusedConstants(dead)
269	if len(warns) != 1 || !strings.Contains(warns[0], "CACHE_AGE") {
270		t.Fatalf("want one warning about CACHE_AGE, got %v", warns)
271	}
272}
273
274// The failure this was written for: a package name with a dot in it is not a
275// sentence boundary, and treating it as one opened an answer mid-word.
276func TestDropMetaDoesNotSplitOnADottedName(t *testing.T) {
277	in := "This response creates an HTML page using the `leaflet.webgl-temperature-map` library. It includes sample data."
278	got := dropMeta(in)
279	if got != "It includes sample data." {
280		t.Errorf("got %q", got)
281	}
282}
283
284// The failure that produced a complete looking page whose tooltip showed a
285// hardcoded 50: the model argued with its sources in a comment and then wrote
286// a stand-in value.
287func TestMetaInCodeFailsTheBlock(t *testing.T) {
288	code := strings.Join([]string{
289		"// The provided text does not explicitly define a getValue method,",
290		"// so we simulate a value for the purpose of the demo.",
291		"var simulatedValue = 50;",
292	}, "\n")
293	if note := metaInCode(code); note == "" {
294		t.Error("a comment reasoning about the sources was not caught")
295	}
296	if note := metaInCode("// cache the result so the page does not refetch\n"); note != "" {
297		t.Errorf("an ordinary comment was flagged: %s", note)
298	}
299}
300
301func TestStripCodeCitationsCleansComments(t *testing.T) {
302	md := "```js\n// see the docs [1] for the rest\nvar x = [1];\nvar y = data[12];\n```\n"
303	got := stripCodeCitations(md)
304	if strings.Contains(got, "docs [1]") {
305		t.Error("a citation in a comment survived")
306	}
307	if !strings.Contains(got, "var x = [1];") || !strings.Contains(got, "data[12]") {
308		t.Errorf("real code was rewritten:\n%s", got)
309	}
310}
311
312// The page that came back looking finished and rendered blank, because it
313// called into a library nothing on the page had loaded.
314func TestMissingLibrary(t *testing.T) {
315	invented := `<html><body><div id="map"></div><script>const map = new SatMeteo.Map({zoom: 2});</script></body></html>`
316	if note := missingLibrary(invented); note == "" {
317		t.Error("a call into a library that is never loaded was not caught")
318	}
319	loaded := `<html><body><script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>` +
320		`<script>const map = L.map('map');</script></body></html>`
321	if note := missingLibrary(loaded); note != "" {
322		t.Errorf("a page that loads its library was flagged: %s", note)
323	}
324	plain := `<html><body><script>const box = document.getElementById('x'); box.textContent = JSON.stringify({a: 1});` +
325		`const d = new Date(); const canvas = new Image();</script></body></html>`
326	if note := missingLibrary(plain); note != "" {
327		t.Errorf("a page using only browser globals was flagged: %s", note)
328	}
329	own := `<html><body><script>class Chart { draw() {} } const c = new Chart(); c.draw();</script></body></html>`
330	if note := missingLibrary(own); note != "" {
331		t.Errorf("a page defining its own class was flagged: %s", note)
332	}
333}
334
335// The connection string that came back as f"DRIVER={IBMDB} ...", where IBMDB
336// is a name the file never sets.
337func TestUndefinedInFString(t *testing.T) {
338	bad := "conn = ibm_db.connect(f\"DRIVER={IBMDB} HOST={DB_HOST}\")\nDB_HOST = 'localhost'\n"
339	if note := undefinedInFString(bad); note == "" || !strings.Contains(note, "IBMDB") {
340		t.Errorf("got %q", note)
341	}
342	good := "name = 'world'\nprint(f'hello {name}')\n"
343	if note := undefinedInFString(good); note != "" {
344		t.Errorf("a defined name was flagged: %s", note)
345	}
346	// An expression inside the braces is left alone, since it has too many
347	// ways to be legal.
348	expr := "print(f'{row.value:.1f} and {items[0]}')\n"
349	if note := undefinedInFString(expr); note != "" {
350		t.Errorf("an expression was flagged: %s", note)
351	}
352}
353
354func TestLiftFileComments(t *testing.T) {
355	md := "```python\n# app.py\nimport os\n```\n\n```sh\n# install it first\npip install flask\n```\n"
356	got := liftFileComments(md)
357	if strings.Contains(got, "# app.py") {
358		t.Errorf("the file name comment was kept:\n%s", got)
359	}
360	if !strings.Contains(got, "# install it first") {
361		t.Errorf("an ordinary first comment was removed:\n%s", got)
362	}
363	if !strings.Contains(got, "import os") {
364		t.Errorf("code was lost:\n%s", got)
365	}
366}