hugo_smoke_test.go - hugo - [fork] hugo port for 9front
(HTM) git clone https://git.drkhsh.at/hugo.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
hugo_smoke_test.go (15315B)
---
1 // Copyright 2024 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package hugolib
15
16 import (
17 "fmt"
18 "math/rand"
19 "testing"
20
21 "github.com/bep/logg"
22 qt "github.com/frankban/quicktest"
23 )
24
25 // The most basic build test.
26 func TestHello(t *testing.T) {
27 files := `
28 -- hugo.toml --
29 title = "Hello"
30 baseURL="https://example.org"
31 disableKinds = ["term", "taxonomy", "section", "page"]
32 -- content/p1.md --
33 ---
34 title: Page
35 ---
36 -- layouts/index.html --
37 Home: {{ .Title }}
38 `
39
40 b := NewIntegrationTestBuilder(
41 IntegrationTestConfig{
42 T: t,
43 TxtarString: files,
44 // LogLevel: logg.LevelTrace,
45 },
46 ).Build()
47
48 b.Assert(b.H.Log.LoggCount(logg.LevelWarn), qt.Equals, 0)
49 b.AssertFileContent("public/index.html", `Hello`)
50 }
51
52 func TestSmokeOutputFormats(t *testing.T) {
53 t.Parallel()
54
55 files := `
56 -- hugo.toml --
57 baseURL = "https://example.com/"
58 defaultContentLanguage = "en"
59 disableKinds = ["term", "taxonomy", "robotsTXT", "sitemap"]
60 [outputs]
61 home = ["html", "rss"]
62 section = ["html", "rss"]
63 page = ["html"]
64 -- content/p1.md --
65 ---
66 title: Page
67 ---
68 Page.
69
70 -- layouts/_default/list.html --
71 List: {{ .Title }}|{{ .RelPermalink}}|{{ range .OutputFormats }}{{ .Name }}: {{ .RelPermalink }}|{{ end }}$
72 -- layouts/_default/list.xml --
73 List xml: {{ .Title }}|{{ .RelPermalink}}|{{ range .OutputFormats }}{{ .Name }}: {{ .RelPermalink }}|{{ end }}$
74 -- layouts/_default/single.html --
75 Single: {{ .Title }}|{{ .RelPermalink}}|{{ range .OutputFormats }}{{ .Name }}: {{ .RelPermalink }}|{{ end }}$
76
77 `
78
79 for i := 0; i < 2; i++ {
80 b := Test(t, files)
81 b.AssertFileContent("public/index.html", `List: |/|html: /|rss: /index.xml|$`)
82 b.AssertFileContent("public/index.xml", `List xml: |/|html: /|rss: /index.xml|$`)
83 b.AssertFileContent("public/p1/index.html", `Single: Page|/p1/|html: /p1/|$`)
84 b.AssertFileExists("public/p1/index.xml", false)
85 }
86 }
87
88 func TestSmoke(t *testing.T) {
89 t.Parallel()
90
91 // Basic test cases.
92 // OK translations
93 // OK page collections
94 // OK next, prev in section
95 // OK GetPage
96 // OK Pagination
97 // OK RenderString with shortcode
98 // OK cascade
99 // OK site last mod, section last mod.
100 // OK main sections
101 // OK taxonomies
102 // OK GetTerms
103 // OK Resource page
104 // OK Resource txt
105
106 const files = `
107 -- hugo.toml --
108 baseURL = "https://example.com"
109 title = "Smoke Site"
110 rssLimit = 3
111 defaultContentLanguage = "en"
112 defaultContentLanguageInSubdir = true
113 enableRobotsTXT = true
114
115 [pagination]
116 pagerSize = 1
117
118 [taxonomies]
119 category = 'categories'
120 tag = 'tags'
121
122 [languages]
123 [languages.en]
124 weight = 1
125 title = "In English"
126 [languages.no]
127 weight = 2
128 title = "På norsk"
129
130 [params]
131 hugo = "Rules!"
132
133 [outputs]
134 home = ["html", "json", "rss"]
135 -- layouts/index.html --
136 Home: {{ .Lang}}|{{ .Kind }}|{{ .RelPermalink }}|{{ .Title }}|{{ .Content }}|Len Resources: {{ len .Resources }}|HTML
137 Resources: {{ range .Resources }}{{ .ResourceType }}|{{ .RelPermalink }}|{{ .MediaType }} - {{ end }}|
138 Site last mod: {{ site.Lastmod.Format "2006-02-01" }}|
139 Home last mod: {{ .Lastmod.Format "2006-02-01" }}|
140 Len Translations: {{ len .Translations }}|
141 Len home.RegularPagesRecursive: {{ len .RegularPagesRecursive }}|
142 RegularPagesRecursive: {{ range .RegularPagesRecursive }}{{ .RelPermalink }}|{{ end }}@
143 Len site.RegularPages: {{ len site.RegularPages }}|
144 Len site.Pages: {{ len site.Pages }}|
145 Len site.AllPages: {{ len site.AllPages }}|
146 GetPage: {{ with .Site.GetPage "posts/p1" }}{{ .RelPermalink }}|{{ .Title }}{{ end }}|
147 RenderString with shortcode: {{ .RenderString "{{% hello %}}" }}|
148 Paginate: {{ .Paginator.PageNumber }}/{{ .Paginator.TotalPages }}|
149 -- layouts/index.json --
150 Home:{{ .Lang}}|{{ .Kind }}|{{ .RelPermalink }}|{{ .Title }}|{{ .Content }}|Len Resources: {{ len .Resources }}|JSON
151 -- layouts/_default/list.html --
152 List: {{ .Lang}}|{{ .Kind }}|{{ .RelPermalink }}|{{ .Title }}|{{ .Content }}|Len Resources: {{ len .Resources }}|
153 Resources: {{ range .Resources }}{{ .ResourceType }}|{{ .RelPermalink }}|{{ .MediaType }} - {{ end }}
154 Pages Length: {{ len .Pages }}
155 RegularPages Length: {{ len .RegularPages }}
156 RegularPagesRecursive Length: {{ len .RegularPagesRecursive }}
157 List last mod: {{ .Lastmod.Format "2006-02-01" }}
158 Background: {{ .Params.background }}|
159 Kind: {{ .Kind }}
160 Type: {{ .Type }}
161 Paginate: {{ .Paginator.PageNumber }}/{{ .Paginator.TotalPages }}|
162 -- layouts/_default/single.html --
163 Single: {{ .Lang}}|{{ .Kind }}|{{ .RelPermalink }}|{{ .Title }}|{{ .Content }}|Len Resources: {{ len .Resources }}|Background: {{ .Params.background }}|
164 Resources: {{ range .Resources }}{{ .ResourceType }}|{{ .RelPermalink }}|{{ .MediaType }}|{{ .Params }} - {{ end }}
165 {{ $textResource := .Resources.GetMatch "**.txt" }}
166 {{ with $textResource }}
167 Icon: {{ .Params.icon }}|
168 {{ $textResourceFingerprinted := . | fingerprint }}
169 Icon fingerprinted: {{ with $textResourceFingerprinted }}{{ .Params.icon }}|{{ .RelPermalink }}{{ end }}|
170 {{ end }}
171 NextInSection: {{ with .NextInSection }}{{ .RelPermalink }}|{{ .Title }}{{ end }}|
172 PrevInSection: {{ with .PrevInSection }}{{ .RelPermalink }}|{{ .Title }}{{ end }}|
173 GetTerms: {{ range .GetTerms "tags" }}name: {{ .Name }}, title: {{ .Title }}|{{ end }}
174 -- layouts/shortcodes/hello.html --
175 Hello.
176 -- content/_index.md --
177 ---
178 title: Home in English
179 ---
180 Home Content.
181 -- content/_index.no.md --
182 ---
183 title: Hjem
184 cascade:
185 - _target:
186 kind: page
187 path: /posts/**
188 background: post.jpg
189 - _target:
190 kind: term
191 background: term.jpg
192 ---
193 Hjem Innhold.
194 -- content/posts/f1.txt --
195 posts f1 text.
196 -- content/posts/sub/f1.txt --
197 posts sub f1 text.
198 -- content/posts/p1/index.md --
199 +++
200 title = "Post 1"
201 lastMod = "2001-01-01"
202 tags = ["tag1"]
203 [[resources]]
204 src = '**'
205 [resources.params]
206 icon = 'enicon'
207 +++
208 Content 1.
209 -- content/posts/p1/index.no.md --
210 +++
211 title = "Post 1 no"
212 lastMod = "2002-02-02"
213 tags = ["tag1", "tag2"]
214 [[resources]]
215 src = '**'
216 [resources.params]
217 icon = 'noicon'
218 +++
219 Content 1 no.
220 -- content/posts/_index.md --
221 ---
222 title: Posts
223 ---
224 -- content/posts/p1/f1.txt --
225 posts p1 f1 text.
226 -- content/posts/p1/sub/ps1.md --
227 ---
228 title: Post Sub 1
229 ---
230 Content Sub 1.
231 -- content/posts/p2.md --
232 ---
233 title: Post 2
234 tags: ["tag1", "tag3"]
235 ---
236 Content 2.
237 -- content/posts/p2.no.md --
238 ---
239 title: Post 2 No
240 ---
241 Content 2 No.
242 -- content/tags/_index.md --
243 ---
244 title: Tags
245 ---
246 Content Tags.
247 -- content/tags/tag1/_index.md --
248 ---
249 title: Tag 1
250 ---
251 Content Tag 1.
252
253
254 `
255
256 b := NewIntegrationTestBuilder(IntegrationTestConfig{
257 T: t,
258 TxtarString: files,
259 NeedsOsFS: true,
260 // Verbose: true,
261 // LogLevel: logg.LevelTrace,
262 }).Build()
263
264 b.AssertFileContent("public/en/index.html",
265 "Home: en|home|/en/|Home in English|<p>Home Content.</p>\n|HTML",
266 "Site last mod: 2001-01-01",
267 "Home last mod: 2001-01-01",
268 "Translations: 1|",
269 "Len home.RegularPagesRecursive: 2|",
270 "Len site.RegularPages: 2|",
271 "Len site.Pages: 8|",
272 "Len site.AllPages: 16|",
273 "GetPage: /en/posts/p1/|Post 1|",
274 "RenderString with shortcode: Hello.|",
275 "Paginate: 1/2|",
276 )
277 b.AssertFileContent("public/en/page/2/index.html", "Paginate: 2/2|")
278
279 b.AssertFileContent("public/no/index.html",
280 "Home: no|home|/no/|Hjem|<p>Hjem Innhold.</p>\n|HTML",
281 "Site last mod: 2002-02-02",
282 "Home last mod: 2002-02-02",
283 "Translations: 1",
284 "GetPage: /no/posts/p1/|Post 1 no|",
285 )
286
287 b.AssertFileContent("public/en/index.json", "Home:en|home|/en/|Home in English|<p>Home Content.</p>\n|JSON")
288 b.AssertFileContent("public/no/index.json", "Home:no|home|/no/|Hjem|<p>Hjem Innhold.</p>\n|JSON")
289
290 b.AssertFileContent("public/en/posts/p1/index.html",
291 "Single: en|page|/en/posts/p1/|Post 1|<p>Content 1.</p>\n|Len Resources: 2|",
292 "Resources: text|/en/posts/p1/f1.txt|text/plain|map[icon:enicon] - page||application/octet-stream|map[draft:false iscjklanguage:false title:Post Sub 1] -",
293 "Icon: enicon",
294 "Icon fingerprinted: enicon|/en/posts/p1/f1.e5746577af5cbfc4f34c558051b7955a9a5a795a84f1c6ab0609cb3473a924cb.txt|",
295 "NextInSection: |\nPrevInSection: /en/posts/p2/|Post 2|",
296 "GetTerms: name: tag1, title: Tag 1|",
297 )
298
299 b.AssertFileContent("public/no/posts/p1/index.html",
300 "Resources: 1",
301 "Resources: text|/en/posts/p1/f1.txt|text/plain|map[icon:noicon] -",
302 "Icon: noicon",
303 "Icon fingerprinted: noicon|/en/posts/p1/f1.e5746577af5cbfc4f34c558051b7955a9a5a795a84f1c6ab0609cb3473a924cb.txt|",
304 "Background: post.jpg",
305 "NextInSection: |\nPrevInSection: /no/posts/p2/|Post 2 No|",
306 )
307
308 b.AssertFileContent("public/en/posts/index.html",
309 "List: en|section|/en/posts/|Posts||Len Resources: 2|",
310 "Resources: text|/en/posts/f1.txt|text/plain - text|/en/posts/sub/f1.txt|text/plain -",
311 "List last mod: 2001-01-01",
312 )
313
314 b.AssertFileContent("public/no/posts/index.html",
315 "List last mod: 2002-02-02",
316 )
317
318 b.AssertFileContent("public/en/posts/p2/index.html", "Single: en|page|/en/posts/p2/|Post 2|<p>Content 2.</p>\n|",
319 "|Len Resources: 0",
320 "GetTerms: name: tag1, title: Tag 1|name: tag3, title: Tag3|",
321 )
322 b.AssertFileContent("public/no/posts/p2/index.html", "Single: no|page|/no/posts/p2/|Post 2 No|<p>Content 2 No.</p>\n|")
323
324 b.AssertFileContent("public/no/categories/index.html",
325 "Kind: taxonomy",
326 "Type: categories",
327 )
328 b.AssertFileContent("public/no/tags/index.html",
329 "Kind: taxonomy",
330 "Type: tags",
331 )
332
333 b.AssertFileContent("public/no/tags/tag1/index.html",
334 "Background: term.jpg",
335 "Kind: term",
336 "Type: tags",
337 "Paginate: 1/1|",
338 )
339
340 b.AssertFileContent("public/en/tags/tag1/index.html",
341 "Kind: term",
342 "Type: tags",
343 "Paginate: 1/2|",
344 )
345 }
346
347 // Basic tests that verifies that the different file systems work as expected.
348 func TestSmokeFilesystems(t *testing.T) {
349 t.Parallel()
350
351 files := `
352 -- hugo.toml --
353 baseURL = "https://example.com"
354 defaultContentLanguage = "en"
355 defaultContentLanguageInSubdir = true
356 [languages]
357 [languages.en]
358 title = "In English"
359 [languages.nn]
360 title = "På nynorsk"
361 [module]
362 [[module.mounts]]
363 source = "i18n"
364 target = "i18n"
365 [[module.mounts]]
366 source = "data"
367 target = "data"
368 [[module.mounts]]
369 source = "content/en"
370 target = "content"
371 lang = "en"
372 [[module.mounts]]
373 source = "content/nn"
374 target = "content"
375 lang = "nn"
376 [[module.imports]]
377 path = "mytheme"
378 -- layouts/index.html --
379 i18n s1: {{ i18n "s1" }}|
380 i18n s2: {{ i18n "s2" }}|
381 data s1: {{ site.Data.d1.s1 }}|
382 data s2: {{ site.Data.d1.s2 }}|
383 title: {{ .Title }}|
384 -- themes/mytheme/hugo.toml --
385 [[module.mounts]]
386 source = "i18n"
387 target = "i18n"
388 [[module.mounts]]
389 source = "data"
390 target = "data"
391 # i18n files both project and theme.
392 -- i18n/en.toml --
393 [s1]
394 other = 's1project'
395 -- i18n/nn.toml --
396 [s1]
397 other = 's1prosjekt'
398 -- themes/mytheme/i18n/en.toml --
399 [s1]
400 other = 's1theme'
401 [s2]
402 other = 's2theme'
403 # data files both project and theme.
404 -- data/d1.yaml --
405 s1: s1project
406 -- themes/mytheme/data/d1.yaml --
407 s1: s1theme
408 s2: s2theme
409 # Content
410 -- content/en/_index.md --
411 ---
412 title: "Home"
413 ---
414 -- content/nn/_index.md --
415 ---
416 title: "Heim"
417 ---
418
419 `
420 b := Test(t, files)
421
422 b.AssertFileContent("public/en/index.html",
423 "i18n s1: s1project", "i18n s2: s2theme",
424 "data s1: s1project", "data s2: s2theme",
425 "title: Home",
426 )
427
428 b.AssertFileContent("public/nn/index.html",
429 "i18n s1: s1prosjekt", "i18n s2: s2theme",
430 "data s1: s1project", "data s2: s2theme",
431 "title: Heim",
432 )
433 }
434
435 // https://github.com/golang/go/issues/30286
436 func TestDataRace(t *testing.T) {
437 const page = `
438 ---
439 title: "The Page"
440 outputs: ["HTML", "JSON"]
441 ---
442
443 The content.
444
445
446 `
447
448 b := newTestSitesBuilder(t).WithSimpleConfigFile()
449 for i := 1; i <= 50; i++ {
450 b.WithContent(fmt.Sprintf("blog/page%d.md", i), page)
451 }
452
453 b.WithContent("_index.md", `
454 ---
455 title: "The Home"
456 outputs: ["HTML", "JSON", "CSV", "RSS"]
457 ---
458
459 The content.
460
461
462 `)
463
464 commonTemplate := `{{ .Data.Pages }}`
465
466 b.WithTemplatesAdded("_default/single.html", "HTML Single: "+commonTemplate)
467 b.WithTemplatesAdded("_default/list.html", "HTML List: "+commonTemplate)
468
469 b.CreateSites().Build(BuildCfg{})
470 }
471
472 // This is just a test to verify that BenchmarkBaseline is working as intended.
473 func TestBenchmarkBaseline(t *testing.T) {
474 cfg := IntegrationTestConfig{
475 T: t,
476 TxtarString: benchmarkBaselineFiles(true),
477 }
478 b := NewIntegrationTestBuilder(cfg).Build()
479
480 b.Assert(len(b.H.Sites), qt.Equals, 4)
481 b.Assert(len(b.H.Sites[0].RegularPages()), qt.Equals, 161)
482 b.Assert(len(b.H.Sites[0].Pages()), qt.Equals, 197)
483 b.Assert(len(b.H.Sites[2].RegularPages()), qt.Equals, 158)
484 b.Assert(len(b.H.Sites[2].Pages()), qt.Equals, 194)
485 }
486
487 func BenchmarkBaseline(b *testing.B) {
488 cfg := IntegrationTestConfig{
489 T: b,
490 TxtarString: benchmarkBaselineFiles(false),
491 }
492 builders := make([]*IntegrationTestBuilder, b.N)
493
494 for i := range builders {
495 builders[i] = NewIntegrationTestBuilder(cfg)
496 }
497
498 b.ResetTimer()
499 for i := 0; i < b.N; i++ {
500 builders[i].Build()
501 }
502 }
503
504 func benchmarkBaselineFiles(leafBundles bool) string {
505 rnd := rand.New(rand.NewSource(32))
506
507 files := `
508 -- config.toml --
509 baseURL = "https://example.com"
510 defaultContentLanguage = 'en'
511
512 [module]
513 [[module.mounts]]
514 source = 'content/en'
515 target = 'content/en'
516 lang = 'en'
517 [[module.mounts]]
518 source = 'content/nn'
519 target = 'content/nn'
520 lang = 'nn'
521 [[module.mounts]]
522 source = 'content/no'
523 target = 'content/no'
524 lang = 'no'
525 [[module.mounts]]
526 source = 'content/sv'
527 target = 'content/sv'
528 lang = 'sv'
529 [[module.mounts]]
530 source = 'layouts'
531 target = 'layouts'
532
533 [languages]
534 [languages.en]
535 title = "English"
536 weight = 1
537 [languages.nn]
538 title = "Nynorsk"
539 weight = 2
540 [languages.no]
541 title = "Norsk"
542 weight = 3
543 [languages.sv]
544 title = "Svenska"
545 weight = 4
546 -- layouts/_default/list.html --
547 {{ .Title }}
548 {{ .Content }}
549 -- layouts/_default/single.html --
550 {{ .Title }}
551 {{ .Content }}
552 -- layouts/shortcodes/myshort.html --
553 {{ .Inner }}
554 `
555
556 contentTemplate := `
557 ---
558 title: "Page %d"
559 date: "2018-01-01"
560 weight: %d
561 ---
562
563 ## Heading 1
564
565 Duis nisi reprehenderit nisi cupidatat cillum aliquip ea id eu esse commodo et.
566
567 ## Heading 2
568
569 Aliqua labore enim et sint anim amet excepteur ea dolore.
570
571 {{< myshort >}}
572 Hello, World!
573 {{< /myshort >}}
574
575 Aliqua labore enim et sint anim amet excepteur ea dolore.
576
577
578 `
579
580 for _, lang := range []string{"en", "nn", "no", "sv"} {
581 files += fmt.Sprintf("\n-- content/%s/_index.md --\n"+contentTemplate, lang, 1, 1, 1)
582 for i, root := range []string{"", "foo", "bar", "baz"} {
583 for j, section := range []string{"posts", "posts/funny", "posts/science", "posts/politics", "posts/world", "posts/technology", "posts/world/news", "posts/world/news/europe"} {
584 n := i + j + 1
585 files += fmt.Sprintf("\n-- content/%s/%s/%s/_index.md --\n"+contentTemplate, lang, root, section, n, n, n)
586 for k := 1; k < rnd.Intn(30)+1; k++ {
587 n := n + k
588 ns := fmt.Sprintf("%d", n)
589 if leafBundles {
590 ns = fmt.Sprintf("%d/index", n)
591 }
592 file := fmt.Sprintf("\n-- content/%s/%s/%s/p%s.md --\n"+contentTemplate, lang, root, section, ns, n, n)
593 files += file
594 }
595 }
596 }
597 }
598
599 return files
600 }