rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package fiesta
2
3import (
4 "os"
5 "os/exec"
6 "strings"
7 "testing"
8)
9
10// Fiesta is the design system on its own. Rastrillo adopts it, so a
11// path from here back to Rastrillo would be a cycle, and a user who
12// links the CSS from a static page has no Go at all. The two tests
13// below are the two halves of that promise, executable: no build of
14// this module reaches amadan.net/rastrillo/rastrillo, and the packages
15// a Go program imports from Fiesta pull in no browser.
16
17// rastrilloModule is the import path that must never appear in this
18// module's dependency graph, and never in its go.mod.
19const rastrilloModule = "amadan.net/rastrillo/rastrillo"
20
21// listDeps runs go list with the given arguments and returns its
22// output, one import path per line. A go list that cannot run fails
23// the test rather than listing nothing: piped straight into a check,
24// an empty listing would pass as clean, which is how a toolchain that
25// could not fetch itself once passed rastrillo's own graph check.
26func listDeps(t *testing.T, args ...string) []string {
27 t.Helper()
28 cmd := exec.Command("go", append([]string{"list"}, args...)...)
29 out, err := cmd.CombinedOutput()
30 if err != nil {
31 t.Fatalf("go list %s: %v\n%s", strings.Join(args, " "), err, out)
32 }
33 lines := strings.Split(strings.TrimRight(string(out), "\n"), "\n")
34 if len(lines) == 0 || lines[0] == "" {
35 t.Fatalf("go list %s printed nothing", strings.Join(args, " "))
36 }
37 return lines
38}
39
40// requireListed is the precondition that keeps either check honest: a
41// listing that does not name this module's own package is not a
42// listing of this module, whatever else it says.
43func requireListed(t *testing.T, lines []string, args string) {
44 t.Helper()
45 for _, l := range lines {
46 if l == "amadan.net/rastrillo/fiesta" {
47 return
48 }
49 }
50 t.Fatalf("go list %s did not list amadan.net/rastrillo/fiesta itself; the check below would be looking at nothing:\n%s", args, strings.Join(lines, "\n"))
51}
52
53// TestFiestaNeverImportsRastrillo is the global constraint "No
54// Rastrillo dependency" as a test: every package of this module, its
55// tests included and with the browser tag on (a strict superset of the
56// plain build), imports nothing from amadan.net/rastrillo/rastrillo,
57// and go.mod never requires it. The go.mod half catches a requirement
58// nobody imports yet, which `go list -deps` alone would not see.
59func TestFiestaNeverImportsRastrillo(t *testing.T) {
60 mod, err := os.ReadFile("go.mod")
61 if err != nil {
62 t.Fatalf("reading go.mod: %v", err)
63 }
64 if strings.Contains(string(mod), rastrilloModule) {
65 t.Errorf("go.mod mentions %s; Fiesta never requires Rastrillo", rastrilloModule)
66 }
67
68 args := "-deps -test -tags browser ./..."
69 lines := listDeps(t, "-deps", "-test", "-tags", "browser", "./...")
70 requireListed(t, lines, args)
71 for _, l := range lines {
72 if strings.HasPrefix(l, rastrilloModule) {
73 t.Errorf("go list %s reaches %s; Fiesta never imports Rastrillo in any build, tag or test", args, l)
74 }
75 }
76}
77
78// TestThePublicPackagesLinkNoBrowser is the other half: the packages
79// a Go program imports from Fiesta, the root and example, never link
80// chromedp. The browser is for check/ and the drives, and an app that
81// embeds the CSS must not take on a Chrome driver to do it.
82func TestThePublicPackagesLinkNoBrowser(t *testing.T) {
83 args := "-deps . ./example"
84 lines := listDeps(t, "-deps", ".", "./example")
85 requireListed(t, lines, args)
86 for _, l := range lines {
87 if strings.Contains(l, "chromedp") {
88 t.Errorf("go list %s reaches %s; the public packages never link a browser", args, l)
89 }
90 }
91}
92