package buildstep import ( "strings" "testing" ) // The shared warm caches are read under a throwaway writable layer (novox/hq ADR 0448; issue 1309): a candidate's step // writes into them as a build does, and nothing it writes outlives it or reaches a later build; only a trunk build // writes them. func TestACandidatesStepWritesTheCachesOnlyIntoAThrowawayLayer(t *testing.T) { fixedSystem(t) iso := Isolation{Workspace: "/w", Caches: []string{"/var/cache/go-build", "/var/cache/npm"}} argv, err := iso.Command("go", "test") if err != nil { t.Fatal(err) } for _, c := range iso.Caches { if !holds(argv, "--overlay-src", c, "--tmp-overlay", c) { t.Errorf("the cache %s is not under a throwaway layer: %v", c, argv) } if holds(argv, "--bind", c, c) { t.Errorf("a candidate's step writes the cache %s: %v", c, argv) } } iso.WriteCaches = true argv, _ = iso.Command("go", "build") for _, c := range iso.Caches { if !holds(argv, "--bind", c, c) || holds(argv, "--tmp-overlay", c) { t.Errorf("a trunk build does not write the cache %s: %v", c, argv) } } // 1921/S2: with a cache layer, a command reads the ask's kept layer above the shared cache and writes into a layer // on disk of the ask's own, never into the shared cache and never into a throwaway tmpfs. iso = Isolation{Workspace: "/w", Caches: []string{"/cache/gomod", "/cache/gobuild"}, CacheLayer: "/w/cachelayer"} argv, err = iso.Command("go", "vet") if err != nil { t.Fatal(err) } for i, c := range iso.Caches { if !holds(argv, "--overlay-src", c, "--overlay-src", keptLayer(iso.CacheLayer, i), "--overlay") { t.Errorf("the cache %s is not read beneath the ask's kept layer: %v", c, argv) } if up := overlayOf(argv, c); up == "" || !strings.HasPrefix(up, "/w/cachelayer/") { t.Errorf("the cache %s is written into %q, not a layer of the ask's own: %v", c, up, argv) } if holds(argv, "--tmp-overlay", c) || holds(argv, "--bind", c, c) { t.Errorf("the cache %s is thrown away or written: %v", c, argv) } } if _, err := (Isolation{Workspace: "/w", CacheLayer: "cachelayer"}).Command("go"); err == nil { t.Error("a relative cache layer was taken") } } // overlayOf answers the upper directory a command line gives the cache c, "" when it gives none. func overlayOf(argv []string, c string) string { for i := 0; i+3 < len(argv); i++ { if argv[i] == "--overlay" && argv[i+3] == c { return argv[i+1] } } return "" }