Files

82 lines
2.6 KiB
Go

package isolate
import (
"io/fs"
"os"
"path/filepath"
"strings"
"testing"
"time"
"git.coffeylabs.org/coffey-labs/hotdog-cms/internal/build"
"git.coffeylabs.org/coffey-labs/hotdog-cms/starter"
)
// The test binary is its own build child.
func TestMain(m *testing.M) {
if len(os.Args) == 2 && os.Args[1] == ChildArg {
Child()
}
os.Exit(m.Run())
}
func site(t *testing.T, layout string) string {
t.Helper()
dir := t.TempDir()
fs.WalkDir(starter.Files, "site", func(p string, d fs.DirEntry, err error) error {
target := filepath.Join(dir, strings.TrimPrefix(p, "site"))
if d.IsDir() {
return os.MkdirAll(target, 0o755)
}
data, _ := starter.Files.ReadFile(p)
return os.WriteFile(target, []byte(strings.ReplaceAll(string(data), "{{SITE_NAME}}", "Test")), 0o644)
})
if layout != "" {
os.WriteFile(filepath.Join(dir, "layouts", "page.html"), []byte(layout), 0o644)
}
return dir
}
func TestIsolatedBuilds(t *testing.T) {
Enabled = true
defer func() { Enabled = false }()
BuildTimeout = 20 * time.Second
// An ordinary build works the same as in-process.
dir := site(t, "")
sum, err := Build(build.Options{SiteDir: dir, Out: filepath.Join(t.TempDir(), "out")})
if err != nil || sum.Pages == 0 {
t.Fatalf("plain build: %v %+v", err, sum)
}
html, p, err := RenderPage(dir, "content/about.md", []byte("---\ntitle: Changed\n---\nHi.\n"), build.Options{})
if err != nil || p != "/about/" || !strings.Contains(string(html), "Changed") {
t.Fatalf("render: %v %s", err, p)
}
// A template that loops forever is stopped at the deadline.
BuildTimeout = 3 * time.Second
loop := site(t, `{{ define "main" }}{{ range 100000000000000 }}{{ end }}{{ end }}`)
start := time.Now()
_, err = Build(build.Options{SiteDir: loop, Out: filepath.Join(t.TempDir(), "out")})
if err == nil || !strings.Contains(err.Error(), "took longer") || time.Since(start) > 10*time.Second {
t.Errorf("looping template: %v after %s", err, time.Since(start))
}
// One that eats memory without writing anything dies alone.
BuildTimeout = 8 * time.Second
hog := site(t, `{{ define "main" }}{{ $x := list }}{{ range 1000000000 }}{{ $x = append $x "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }}{{ end }}{{ end }}`)
_, err = Build(build.Options{SiteDir: hog, Out: filepath.Join(t.TempDir(), "out")})
if err == nil {
t.Error("a memory-eating template built")
}
t.Logf("memory hog: %v", err)
// The child sees none of the parent's secrets.
t.Setenv("HOTDOG_EDITOR_SECRET", "do-not-leak")
for _, kv := range childEnv() {
if strings.Contains(kv, "do-not-leak") {
t.Error("a secret reached the build child")
}
}
}