diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
| commit | c2d900ec74e03e9c782cfe7b7ce06ff62cda6601 (patch) | |
| tree | fb13320bfdc62d810aa59769e8809dc2f707919e /internal/pkg/pkg_test.go | |
| parent | bd4f29909e0750a4660eaf48e3169777a265b0ab (diff) | |
Closes #43.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/pkg_test.go')
| -rw-r--r-- | internal/pkg/pkg_test.go | 2375 |
1 files changed, 0 insertions, 2375 deletions
diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go deleted file mode 100644 index b23948f8..00000000 --- a/internal/pkg/pkg_test.go +++ /dev/null @@ -1,2375 +0,0 @@ -package pkg_test - -import ( - "archive/tar" - "bytes" - "context" - "crypto/sha512" - "encoding/base64" - "errors" - "fmt" - "io" - "io/fs" - "log" - "net/http" - "os" - "path/filepath" - "reflect" - "strconv" - "strings" - "sync" - "syscall" - "testing" - "testing/fstest" - "time" - "unique" - "unsafe" - - "hakurei.app/check" - "hakurei.app/container" - "hakurei.app/fhs" - "hakurei.app/internal/info" - "hakurei.app/internal/landlock" - "hakurei.app/internal/pkg" - "hakurei.app/internal/stub" - "hakurei.app/message" -) - -var skipLock = func() pkg.CacheAttr { - var attr pkg.CacheAttr - *(*bool)(unsafe.Pointer(reflect.ValueOf(&attr). - Elem(). - FieldByName("skipLock"). - UnsafeAddr())) = true - return attr -}() - -var ( - // extension is a string uniquely identifying a set of custom [Artifact] - // implementations registered by calling [Register]. - // - //go:linkname extension hakurei.app/internal/pkg.extension - extension string - - // opened is false if [Open] was never called. - // - //go:linkname opened hakurei.app/internal/pkg.opened - opened bool - - // irArtifact refers to artifact IR interpretation functions and must not be - // written to directly. - // - //go:linkname irArtifact hakurei.app/internal/pkg.irArtifact - irArtifact map[pkg.Kind]pkg.IRReadFunc - - // statusHeader is the header written to all status files in dirStatus. - // - //go:linkname statusHeader hakurei.app/internal/pkg.statusHeader - statusHeader string -) - -// newRContext returns the address of a new [pkg.RContext] unsafely created for -// the specified [testing.TB]. -func newRContext(tb testing.TB, c *pkg.Cache) *pkg.RContext { - var r pkg.RContext - rContextVal := reflect.ValueOf(&r).Elem().FieldByName("ctx") - reflect.NewAt( - rContextVal.Type(), - unsafe.Pointer(rContextVal.UnsafeAddr()), - ).Elem().Set(reflect.ValueOf(tb.Context())) - rCacheVal := reflect.ValueOf(&r).Elem().FieldByName("cache") - reflect.NewAt( - rCacheVal.Type(), - unsafe.Pointer(rCacheVal.UnsafeAddr()), - ).Elem().Set(reflect.ValueOf(c)) - return &r -} - -// overrideIdent overrides the ID method of [Artifact]. -type overrideIdent struct { - id pkg.ID - pkg.TrivialArtifact -} - -func (a overrideIdent) ID() pkg.ID { return a.id } - -// overrideIdentFile overrides the ID method of [FileArtifact]. -type overrideIdentFile struct { - id pkg.ID - pkg.FileArtifact -} - -func (a overrideIdentFile) ID() pkg.ID { return a.id } - -// A knownIdentArtifact implements [pkg.KnownIdent] and [Artifact] -type knownIdentArtifact interface { - pkg.KnownIdent - pkg.TrivialArtifact -} - -// A knownIdentFile implements [pkg.KnownIdent] and [FileArtifact] -type knownIdentFile interface { - pkg.KnownIdent - pkg.FileArtifact -} - -// overrideChecksum overrides the Checksum method of [Artifact]. -type overrideChecksum struct { - checksum pkg.Checksum - knownIdentArtifact -} - -func (a overrideChecksum) Checksum() pkg.Checksum { return a.checksum } - -// overrideChecksumFile overrides the Checksum method of [FileArtifact]. -type overrideChecksumFile struct { - checksum pkg.Checksum - knownIdentFile -} - -func (a overrideChecksumFile) Checksum() pkg.Checksum { return a.checksum } - -// A stubArtifact implements [TrivialArtifact] with hardcoded behaviour. -type stubArtifact struct { - kind pkg.Kind - params []byte - deps []pkg.Artifact - - cure func(t *pkg.TContext) error -} - -func (a *stubArtifact) Kind() pkg.Kind { return a.kind } -func (a *stubArtifact) Params(ctx *pkg.IContext) { ctx.Write(a.params) } -func (a *stubArtifact) Inputs() []pkg.Artifact { return a.deps } -func (a *stubArtifact) Cure(t *pkg.TContext) error { return a.cure(t) } -func (*stubArtifact) IsExclusive() bool { return false } - -// A stubArtifactF implements [FloodArtifact] with hardcoded behaviour. -type stubArtifactF struct { - kind pkg.Kind - params []byte - deps []pkg.Artifact - excl bool - - cure func(f *pkg.FContext) error -} - -func (a *stubArtifactF) Kind() pkg.Kind { return a.kind } -func (a *stubArtifactF) Params(ctx *pkg.IContext) { ctx.Write(a.params) } -func (a *stubArtifactF) Inputs() []pkg.Artifact { return a.deps } -func (a *stubArtifactF) Cure(f *pkg.FContext) error { return a.cure(f) } -func (a *stubArtifactF) IsExclusive() bool { return a.excl } - -// A stubFile implements [FileArtifact] with hardcoded behaviour. -type stubFile struct { - data []byte - err error - - stubArtifact -} - -func (*stubFile) IsExecutable() bool { return false } - -func (a *stubFile) Cure(*pkg.RContext) (io.ReadCloser, error) { - return io.NopCloser(bytes.NewReader(a.data)), a.err -} - -// newStubFile returns an implementation of [pkg.File] with hardcoded behaviour. -func newStubFile( - kind pkg.Kind, - id pkg.ID, - sum *pkg.Checksum, - data []byte, - err error, -) pkg.FileArtifact { - f := overrideIdentFile{id, &stubFile{data, err, stubArtifact{ - kind, - nil, - nil, - func(*pkg.TContext) error { - panic("unreachable") - }, - }}} - if sum == nil { - return f - } else { - return overrideChecksumFile{*sum, f} - } -} - -// stubExtern implements [External] with hardcoded prepared outcomes. -type stubExtern struct { - artifact map[unique.Handle[pkg.ID]]pkg.Checksum - checksum map[unique.Handle[pkg.Checksum]]fstest.MapFS - status map[unique.Handle[pkg.ID]]string -} - -func (e stubExtern) Artifact(_ context.Context, id unique.Handle[pkg.ID]) (*pkg.Checksum, error) { - if checksum, ok := e.artifact[id]; ok { - return &checksum, nil - } - return nil, nil -} - -func (e stubExtern) Checksum(checksum unique.Handle[pkg.Checksum]) pkg.Artifact { - var buf bytes.Buffer - if err := pkg.Write(e.checksum[checksum], ".", &buf); err != nil { - panic(err) - } - return pkg.NewArchive(pkg.NewFile("", buf.Bytes())) -} - -func (e stubExtern) Status(_ *pkg.RContext, id unique.Handle[pkg.ID]) (io.ReadCloser, error) { - if status, ok := e.status[id]; ok { - return io.NopCloser(strings.NewReader(status)), nil - } - return nil, nil -} - -// destroyArtifact removes all traces of an [Artifact] from the on-disk cache. -// Do not use this in a test case without a very good reason to do so. -func destroyArtifact( - t *testing.T, - base *check.Absolute, - c *pkg.Cache, - a pkg.Artifact, -) { - if pathname, checksum, err := c.Cure(a); err != nil { - t.Fatalf("Cure: error = %v", err) - } else if err = os.Remove(pathname.String()); err != nil { - t.Fatal(err) - } else { - p := base.Append( - "checksum", - pkg.Encode(checksum.Value()), - ) - if err = filepath.WalkDir(p.String(), func( - path string, - d fs.DirEntry, - err error, - ) error { - if err != nil { - return err - } - if d.IsDir() { - return os.Chmod(path, 0700) - } - return nil - }); err != nil && !errors.Is(err, os.ErrNotExist) { - t.Fatal(err) - } - if err = os.RemoveAll(p.String()); err != nil { - t.Fatal(err) - } - } -} - -// newDestroyArtifactFunc returns a function that calls destroyArtifact. -func newDestroyArtifactFunc(a pkg.Artifact) func( - t *testing.T, - base *check.Absolute, - c *pkg.Cache, -) { - return func( - t *testing.T, - base *check.Absolute, - c *pkg.Cache, - ) { - destroyArtifact(t, base, c, a) - } -} - -// destroyStatus counts non-substitution status entries and destroys them. -func destroyStatus(t *testing.T, base *check.Absolute, c, s int) { - dents, err := os.ReadDir(base.Append("status").String()) - if err != nil { - t.Fatal(err) - } - - var gotC, gotS int - for _, dent := range dents { - if err = os.Remove(base.Append( - "status", - dent.Name(), - ).String()); err != nil { - t.Fatal(err) - } - - if dent.Type().IsRegular() { - gotC++ - continue - } - if dent.Type()&fs.ModeSymlink == fs.ModeSymlink { - gotS++ - continue - } - t.Errorf("%s: %s", dent.Name(), dent.Type()) - } - - if gotC != c { - t.Errorf("status: c = %d, want %d", gotC, c) - } - if gotS != s { - t.Errorf("status: s = %d, want %d", gotS, s) - } -} - -func TestIdent(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - a pkg.Artifact - want unique.Handle[pkg.ID] - }{ - {"decompress", &stubArtifact{ - pkg.KindDecompress, - []byte{pkg.Gzip, 0, 0, 0, 0, 0, 0, 0}, - []pkg.Artifact{ - overrideIdent{pkg.ID{}, new(stubArtifact)}, - }, - nil, - }, unique.Make[pkg.ID](pkg.MustDecode( - "fkmge-H56Ph2LzNNbEUjTypes8LfOxrF_CEXg07kq6ho_nbTNvzQde9-bjB7gyB_", - ))}, - } - - msg := message.New(log.New(os.Stderr, "ident: ", 0)) - msg.SwapVerbose(true) - var cache *pkg.Cache - if a, err := check.NewAbs(t.TempDir()); err != nil { - t.Fatal(err) - } else if cache, err = pkg.Open(t.Context(), msg, a, nil); err != nil { - t.Fatal(err) - } - t.Cleanup(cache.Close) - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - if got := cache.Ident(tc.a); got != tc.want { - t.Errorf("Ident: %s, want %s", - pkg.Encode(got.Value()), - pkg.Encode(tc.want.Value()), - ) - } - }) - } -} - -// An expectsKnown describes an expected file or directory. -type expectsKnown interface { - // hash returns the checksum of the represented data. - hash() (checksum pkg.Checksum) -} - -// An expectsChecksum is a prepared checksum value. -type expectsChecksum pkg.Checksum - -// hash returns e. -func (e expectsChecksum) hash() pkg.Checksum { return e } - -// An expectsFile is the contents of a file expected by the test suite. -type expectsFile []byte - -// hash computes the checksum of e. -func (e expectsFile) hash() (checksum pkg.Checksum) { - h := sha512.New384() - h.Write(e) - h.Sum(checksum[:0]) - return -} - -// An expectsFS describes the state of a filesystem expected by the test suite. -type expectsFS fstest.MapFS - -// hash computes the checksum of e. -func (e expectsFS) hash() (checksum pkg.Checksum) { - if err := pkg.SumFS(&checksum, fstest.MapFS(e), "."); err != nil { - panic(err) - } - return -} - -// expectsFrom generates expectsFS for a filesystem directory. -func expectsFrom(pathname string) string { - var buf strings.Builder - buf.WriteString("expectsFS{\n") - if err := filepath.WalkDir(pathname, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - var rel string - if rel, err = filepath.Rel(pathname, path); err != nil { - return err - } - buf.WriteString("\t" + strconv.Quote(rel) + ": {Mode: ") - - var fi fs.FileInfo - if fi, err = d.Info(); err != nil { - return err - } - mode := fi.Mode() - - switch { - case mode.IsDir(): - buf.WriteString("fs.ModeDir | 0" + - strconv.FormatInt(int64(mode&^fs.ModeDir), 8)) - - case mode&fs.ModeSymlink != 0: - buf.WriteString("fs.ModeSymlink | 0" + - strconv.FormatInt(int64(mode&^fs.ModeSymlink), 8) + - ", Data: []byte(") - var linkname string - if linkname, err = os.Readlink(path); err != nil { - return err - } - buf.WriteString(strconv.Quote(linkname)) - buf.WriteByte(')') - - case mode.IsRegular(): - buf.WriteString("0" + strconv.FormatInt(int64(mode), 8)) - var p []byte - if p, err = os.ReadFile(path); err != nil { - return err - } - - if len(p) > 0 { - buf.WriteString(", Data: []byte(") - buf.WriteString(strconv.Quote(unsafe.String(unsafe.SliceData(p), len(p)))) - buf.WriteByte(')') - } - } - buf.WriteString("},\n") - return nil - }); err != nil { - panic(err) - } - buf.WriteString("}") - return buf.String() -} - -// cacheTestCase is a test case passed to checkWithCache where a new instance -// of [pkg.Cache] is prepared for the test case, and is validated and removed -// on test completion. -type cacheTestCase struct { - name string - flags int - early func(t *testing.T, base *check.Absolute) - f func(t *testing.T, base *check.Absolute, c *pkg.Cache) - want expectsFS -} - -const ( - // checkDestroySubstitutes arranges for substitutes to be destroyed before - // measurement during checkWithCache. - checkDestroySubstitutes = 1 << (iota + 32) -) - -// makeBase returns a [pkg.Cache] base directory created for tb. -func makeBase(tb testing.TB) (base *check.Absolute) { - tb.Helper() - - base = check.MustAbs(tb.TempDir()) - if err := os.Chmod(base.String(), 0700); err != nil { - tb.Fatal(err) - } - tb.Cleanup(func() { - if err := filepath.WalkDir(base.String(), func(path string, d fs.DirEntry, err error) error { - if err != nil { - tb.Error(err) - return nil - } - if !d.IsDir() { - return nil - } - return os.Chmod(path, 0700) - }); err != nil { - tb.Fatal(err) - } - }) - return -} - -// checkWithCache runs a slice of cacheTestCase. -func checkWithCache(t *testing.T, testCases []cacheTestCase) { - t.Helper() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Helper() - t.Parallel() - - base := makeBase(t) - msg := message.New(log.New(os.Stderr, "cache: ", 0)) - msg.SwapVerbose(testing.Verbose()) - - flags := tc.flags | pkg.CSuppressInit - - if info.CanDegrade { - if _, err := landlock.GetABI(); err != nil { - if !errors.Is(err, syscall.ENOSYS) { - t.Fatalf("LandlockGetABI: error = %v", err) - } - flags |= pkg.CHostAbstract - t.Log("Landlock LSM is unavailable, setting CHostAbstract") - } - } - - var scrubFunc func() error // scrub after hashing - if c, err := pkg.Open(t.Context(), msg, base, &pkg.CacheAttr{ - Cures: 1 << 4, - Flags: flags, - }); err != nil { - t.Fatalf("Open: error = %v", err) - } else { - t.Cleanup(c.Close) - if tc.early != nil { - tc.early(t, base) - } - tc.f(t, base, c) - scrubFunc = func() error { - err = c.Scrub(1 << 7) - idents, checksums, cleanErr := c.Clean(false, false) - if len(idents) > 0 { - t.Errorf("destroyed %d idents", len(idents)) - } - if len(checksums) > 0 { - t.Errorf("destroyed %d checksums", len(checksums)) - } - return errors.Join(err, cleanErr) - } - } - - var restoreTemp bool - if _, err := os.Lstat(base.Append("temp").String()); err != nil { - if !errors.Is(err, os.ErrNotExist) { - t.Fatal(err) - } - } else { - restoreTemp = true - } - - // destroy lock and variant file to avoid changing cache checksums - for _, s := range []string{ - "lock", - "variant", - } { - pathname := base.Append(s) - if p, err := os.ReadFile(pathname.String()); err != nil { - t.Fatal(err) - } else if len(p) != 0 { - t.Fatalf("file %q: %q", s, string(p)) - } - if err := os.Remove(pathname.String()); err != nil { - t.Fatal(err) - } - } - - // destroy non-deterministic substitutes - if tc.flags&checkDestroySubstitutes != 0 { - substitute := base.Append("substitute") - if err := os.RemoveAll(substitute.String()); err != nil { - t.Fatal(err) - } else if err = os.Mkdir(substitute.String(), 0700); err != nil { - t.Fatal(err) - } - } - - // destroy empty status directory - if err := syscall.Rmdir(base.Append("status").String()); err != nil { - if !errors.Is(err, syscall.ENOTEMPTY) { - t.Fatal(err) - } - } - - // destroy empty fault directory - if err := os.Remove(base.Append("fault").String()); err != nil { - t.Fatal(err) - } - - want := tc.want.hash() - - var checksum pkg.Checksum - if err := pkg.SumDir(&checksum, base); err != nil { - t.Fatalf("SumDir: error = %v", err) - } else if checksum != want { - t.Fatal(expectsFrom(base.String())) - } - - if err := scrubFunc(); err != nil { - t.Fatal("cache contains inconsistencies\n\n" + err.Error()) - } - - if restoreTemp { - if err := os.Mkdir( - base.Append("temp").String(), - 0700, - ); err != nil { - t.Fatal(err) - } - } - - // validate again to make sure scrub did not condemn anything - if err := pkg.SumDir(&checksum, base); err != nil { - t.Fatalf("SumDir: error = %v", err) - } else if checksum != want { - t.Fatalf("(scrubbed) %s", expectsFrom(base.String())) - } - }) - } -} - -// A cureStep contains an [Artifact] to be cured, and the expected outcome. -type cureStep struct { - name string - - a pkg.Artifact - - pathname *check.Absolute - output expectsKnown - whence int - err error -} - -// ignorePathname is passed to cureMany to skip the pathname check. -var ignorePathname = check.MustAbs("/\x00") - -// cureMany cures many artifacts against a [Cache] and checks their outcomes. -func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) { - t.Helper() - - makeChecksumH := func(checksum pkg.Checksum) unique.Handle[pkg.Checksum] { - if checksum == (pkg.Checksum{}) { - return unique.Handle[pkg.Checksum]{} - } - return unique.Make(checksum) - } - - for _, step := range steps { - t.Log("cure step:", step.name) - if pathname, checksum, whence, err := c.CureWhence(step.a); !reflect.DeepEqual(err, step.err) { - faults, _err := c.ReadFaults(step.a) - if _err != nil { - t.Errorf("ReadFaults: error = %v", _err) - } - - var p []byte - for _, fault := range faults { - p, _err = os.ReadFile(fault.String()) - if _err != nil { - t.Error(_err) - continue - } - t.Log(string(p)) - t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time())) - } - t.Fatalf("Cure: error = %v, want %v", err, step.err) - } else if step.whence != whence { - t.Fatalf("Cure: whence = %s, want %s", pkg.WhenceString(whence), pkg.WhenceString(step.whence)) - } else if step.pathname != ignorePathname && !pathname.Is(step.pathname) { - t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname) - } else if step.output == nil || checksum != makeChecksumH(step.output.hash()) { - if pathname != nil { - if name, _err := filepath.EvalSymlinks(pathname.String()); _err != nil { - t.Fatal(_err) - } else { - t.Fatal(expectsFrom(name)) - } - } else if checksum != (unique.Handle[pkg.Checksum]{}) { - t.Fatalf("Cure: unexpected checksum %s", pkg.Encode(checksum.Value())) - } - } else { - v := any(err) - if err == nil { - v = pathname - } - var checksumVal pkg.Checksum - if checksum != (unique.Handle[pkg.Checksum]{}) { - checksumVal = checksum.Value() - } - t.Log(pkg.Encode(checksumVal)+":", v) - } - } -} - -// newWantScrubError returns the address to a new [ScrubError] for base. -func newWantScrubError(base *check.Absolute) *pkg.ScrubError { - return &pkg.ScrubError{ - ChecksumMismatches: []pkg.ChecksumMismatchError{ - {Got: pkg.MustDecode( - "vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", - ), Want: pkg.Checksum{0xff, 0}}, - }, - DanglingIdentifiers: []pkg.ID{ - {0xfe, 0}, - {0xfe, 0xfe}, - {0xfe, 0xff}, - }, - Errs: map[unique.Handle[string]][]error{ - base.Append("checksum", "__8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").Handle(): { - pkg.InvalidFileModeError(fs.ModeSymlink), - }, - - base.Append("checksum", "invalid").Handle(): { - base64.CorruptInputError(4), - }, - - base.Append("nonexistent").Handle(): { - base64.CorruptInputError(8), - }, - - base.Append("identifier", pkg.Encode(pkg.ID{0xfe, 0xff})).Handle(): { - &os.PathError{ - Op: "readlink", - Path: base.Append( - "identifier", - pkg.Encode(pkg.ID{0xfe, 0xff}), - ).String(), - Err: syscall.EINVAL, - }, - }, - base.Append("identifier", "invalid").Handle(): { - base64.CorruptInputError(4), - }, - }, - } -} - -func TestCache(t *testing.T) { - t.Parallel() - - testdata := expectsFile("" + - "\x00\x00\x00\x00" + - "\xad\x0b\x00" + - "\x04" + - "\xfe\xfe\x00\x00" + - "\xfe\xca\x00\x00") - - testCases := []cacheTestCase{ - {"file", pkg.CValidateKnown | pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - identifier := (pkg.ID)(bytes.Repeat([]byte{ - 0x75, 0xe6, 0x9d, 0x6d, 0xe7, 0x9f, - }, 8)) - wantPathname := base.Append( - "identifier", - "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - ) - identifier0 := (pkg.ID)(bytes.Repeat([]byte{ - 0x71, 0xa7, 0xde, 0x6d, 0xa6, 0xde, - }, 8)) - wantPathname0 := base.Append( - "identifier", - "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe", - ) - failingFile := newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 3}, - nil, - nil, struct { - _ []byte - stub.UniqueError - }{UniqueError: 0xbad}, - ) - - cureMany(t, c, []cureStep{ - {"initial file", newStubFile( - pkg.KindHTTPGet, - identifier, - new(testdata.hash()), - testdata, nil, - ), wantPathname, testdata, pkg.WNew, nil}, - - {"identical content", newStubFile( - pkg.KindHTTPGet, - identifier0, - new(testdata.hash()), - testdata, nil, - ), wantPathname0, testdata, pkg.WCache, nil}, - - {"existing entry", newStubFile( - pkg.KindHTTPGet, - identifier, - new(testdata.hash()), - testdata, nil, - ), wantPathname, testdata, pkg.WCache, nil}, - - {"checksum mismatch", newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 0}, - new(pkg.Checksum), - testdata, nil, - ), nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{ - Got: testdata.hash(), - }}, - - {"store without validation", newStubFile( - pkg.KindHTTPGet, - pkg.MustDecode("vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX"), - nil, - []byte{0}, nil, - ), base.Append( - "identifier", - "vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", - ), expectsChecksum{ - 0xbe, 0xc0, 0x21, 0xb4, 0xf3, 0x68, - 0xe3, 0x06, 0x91, 0x34, 0xe0, 0x12, - 0xc2, 0xb4, 0x30, 0x70, 0x83, 0xd3, - 0xa9, 0xbd, 0xd2, 0x06, 0xe2, 0x4e, - 0x5f, 0x0d, 0x86, 0xe1, 0x3d, 0x66, - 0x36, 0x65, 0x59, 0x33, 0xec, 0x2b, - 0x41, 0x34, 0x65, 0x96, 0x68, 0x17, - 0xa9, 0xc2, 0x08, 0xa1, 0x17, 0x17, - }, pkg.WNew, nil}, - - {"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{ - kind: pkg.KindExec, - params: []byte("artifact overridden to be incomplete"), - }}, nil, nil, pkg.WNew, pkg.InvalidArtifactError(pkg.MustDecode( - "poVrv3zNINbHd-WUJihwgWQwJpbHURFHfpY7Zux-ztto_bQhhS5PdpbNMjdkXv-V", - ))}, - - {"error passthrough", newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 1}, - nil, - nil, stub.UniqueError(0xcafe), - ), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)}, - - {"error caching", newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 1}, - nil, - nil, nil, - ), nil, nil, pkg.WCache, stub.UniqueError(0xcafe)}, - - {"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{ - kind: pkg.KindTar, - }}}, nil, nil, pkg.WCache, pkg.InvalidFileModeError( - 0400, - )}, - - {"noncomparable error", &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("artifact with dependency returning noncomparable error"), - deps: []pkg.Artifact{failingFile}, - - cure: func(f *pkg.FContext) error { - panic("attempting to cure impossible artifact") - }, - }, nil, nil, pkg.WNew, pkg.InputError{ - failingFile: struct { - _ []byte - stub.UniqueError - }{UniqueError: 0xbad}, - }}, - }) - - if c0, err := pkg.Open( - t.Context(), - message.New(nil), - base, &skipLock, - ); err != nil { - t.Fatalf("open: error = %v", err) - } else { - t.Cleanup(c.Close) // check doubled cancel - cureMany(t, c0, []cureStep{ - {"cache hit ident", overrideIdent{ - id: identifier, - }, wantPathname, testdata, pkg.WCache, nil}, - - {"cache miss checksum match", newStubFile( - pkg.KindHTTPGet, - testdata.hash(), - nil, - testdata, - nil, - ), base.Append( - "identifier", - pkg.Encode(testdata.hash()), - ), testdata, pkg.WNew, nil}, - }) - - // cure after close - c.Close() - if _, _, err = c.Cure(&stubArtifactF{ - kind: pkg.KindExec, - params: []byte("unreachable artifact cured after cancel"), - deps: []pkg.Artifact{pkg.NewFile("", []byte("unreachable dependency"))}, - }); !reflect.DeepEqual(err, context.Canceled) { - t.Fatalf("(closed) Cure: error = %v", err) - } - } - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}}, - "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")}, - "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")}, - "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")}, - "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"directory", pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - id := pkg.MustDecode( - "HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", - ) - makeSample := func(t *pkg.TContext) error { - work := t.GetWorkDir() - if err := os.Mkdir(work.String(), 0700); err != nil { - return err - } - - if err := os.WriteFile( - work.Append("check").String(), - []byte{0, 0}, - 0400, - ); err != nil { - return err - } - - if err := os.MkdirAll(work.Append( - "lib", - "pkgconfig", - ).String(), 0700); err != nil { - return err - } - - return os.Symlink( - "/proc/nonexistent/libedac.so", - work.Append( - "lib", - "libedac.so", - ).String(), - ) - } - want := expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - - "check": {Mode: 0400, Data: []byte{0, 0}}, - - "lib": {Mode: fs.ModeDir | 0700}, - "lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")}, - - "lib/pkgconfig": {Mode: fs.ModeDir | 0700}, - } - wantPathname := base.Append( - "identifier", - pkg.Encode(id), - ) - - id0 := pkg.MustDecode( - "Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", - ) - wantPathname0 := base.Append( - "identifier", - pkg.Encode(id0), - ) - - makeGarbage := func(work *check.Absolute, wantErr error) error { - if err := os.Mkdir(work.String(), 0700); err != nil { - return err - } - - mode := fs.FileMode(0) - if wantErr == nil { - mode = 0500 - } - - if err := os.MkdirAll(work.Append( - "lib", - "pkgconfig", - ).String(), 0700); err != nil { - return err - } - - if err := os.WriteFile(work.Append( - "lib", - "check", - ).String(), nil, 0400&mode); err != nil { - return err - } - - if err := os.Chmod(work.Append( - "lib", - "pkgconfig", - ).String(), 0500&mode); err != nil { - return err - } - if err := os.Chmod(work.Append( - "lib", - ).String(), 0500&mode); err != nil { - return err - } - - return wantErr - } - - cureMany(t, c, []cureStep{ - {"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{ - kind: pkg.KindTar, - cure: makeSample, - }}}, wantPathname, want, pkg.WNew, nil}, - - {"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{ - kind: pkg.KindTar, - }}}, wantPathname, want, pkg.WCache, nil}, - - {"identical checksum", overrideIdent{id0, &stubArtifact{ - kind: pkg.KindTar, - cure: makeSample, - }}, wantPathname0, want, pkg.WNew, nil}, - - {"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe)) - }, - }}, nil, nil, pkg.WNew, stub.UniqueError(0xcafe)}, - - {"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return makeGarbage(t.GetWorkDir(), nil) - }, - }}}, nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{ - Got: pkg.MustDecode( - "CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT", - ), - }}, - - {"cache hit bad type", newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 2}, - new(want.hash()), - testdata, nil, - ), nil, nil, pkg.WCache, pkg.InvalidFileModeError( - fs.ModeDir | 0500, - )}, - - {"openFile directory", overrideIdent{pkg.ID{0xff, 3}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - r, err := t.Open(overrideChecksumFile{checksum: want.hash()}) - if err != nil { - panic(err) - } - _, err = io.ReadAll(r) - return err - }, - }}, nil, nil, pkg.WNew, &os.PathError{ - Op: "read", - Path: base.Append( - "checksum", - pkg.Encode(want.hash()), - ).String(), - Err: syscall.EISDIR, - }}, - - {"no output", overrideIdent{pkg.ID{0xff, 4}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return nil - }, - }}, nil, nil, pkg.WNew, pkg.NoOutputError{}}, - - {"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400) - }, - }}, nil, nil, pkg.WNew, errors.New("non-file artifact produced regular file")}, - - {"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return os.Symlink( - t.GetWorkDir().String(), - t.GetWorkDir().String(), - ) - }, - }}, nil, nil, pkg.WNew, pkg.InvalidFileModeError( - fs.ModeSymlink | 0777, - )}, - - {"alternative", &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("substitutable artifact"), - deps: []pkg.Artifact{newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 8}, - nil, - []byte("substitutable dependency"), - nil, - )}, - - cure: func(f *pkg.FContext) error { - return makeSample(&f.TContext) - }, - }, base.Append( - "identifier", - "gIH5eti07nBAhVti3ZTn8EIGOBCZWWvNpxg5CmCZlDzIC4mBdomPmQLeEpf1IQg9", - ), want, pkg.WNew, nil}, - - {"substitutable", &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("substitutable artifact"), - deps: []pkg.Artifact{newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 10}, - nil, - []byte("substitutable dependency"), - nil, - )}, - - cure: func(f *pkg.FContext) error { - panic("substitution missed") - }, - }, base.Append( - "identifier", - "VGjpp7NVw3OYLpgOQumfM0KcJgY3suz6torykUczcg4bGT24ySkPn5hy-4dNqqkR", - ), want, pkg.WSubstitute, nil}, - }) - - if c0, err := pkg.Open( - t.Context(), - message.New(nil), - base, &skipLock, - ); err != nil { - t.Fatalf("open: error = %v", err) - } else { - t.Cleanup(c.Close) - cureMany(t, c0, []cureStep{ - {"substitutable", &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("substitutable artifact"), - deps: []pkg.Artifact{newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 0xff, 0xfd, 0xfd}, - nil, - []byte("substitutable dependency"), - nil, - )}, - - cure: func(f *pkg.FContext) error { - panic("substitution missed") - }, - }, base.Append( - "identifier", - "zeZ4JEZ0atAKl6Am67cBID6-KR18nZGgeYfU4qTuYaWhQC4eAn0dyTXdIBH9Bos8", - ), want, pkg.WSubstitute, nil}, - }) - } - - if dents, err := os.ReadDir(base.Append("status").String()); err != nil { - t.Fatal(err) - } else if len(dents) > 0 { - t.Errorf("ReadDir: %v", dents) - } - - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO": {Mode: 0400, Data: []byte("substitutable dependency")}, - "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500}, - "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}}, - "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700}, - "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig": {Mode: fs.ModeDir | 0700}, - "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - "identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - "identifier/zeZ4JEZ0atAKl6Am67cBID6-KR18nZGgeYfU4qTuYaWhQC4eAn0dyTXdIBH9Bos8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - "identifier/___9_QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")}, - "identifier/_wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")}, - "identifier/_woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")}, - "identifier/VGjpp7NVw3OYLpgOQumfM0KcJgY3suz6torykUczcg4bGT24ySkPn5hy-4dNqqkR": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - "identifier/gIH5eti07nBAhVti3ZTn8EIGOBCZWWvNpxg5CmCZlDzIC4mBdomPmQLeEpf1IQg9": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - "substitute/nWPg893oqn_YNN8kgfZrs_LVLwP90e0mKxqU8UwoazQh-yBPwhoviD7of6YALx-M": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"pending", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - wantErr := stub.UniqueError(0xcafe) - n, ready := make(chan struct{}), make(chan struct{}) - go func() { - if _, _, err := c.Cure(overrideIdent{pkg.ID{0xff}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - close(ready) - <-n - return wantErr - }, - }}); !reflect.DeepEqual(err, wantErr) { - panic(fmt.Sprintf("Cure: error = %v, want %v", err, wantErr)) - } - }() - - <-ready - wCureDone := make(chan struct{}) - go func() { - if _, _, err := c.Cure(overrideIdent{pkg.ID{0xff}, &stubArtifact{ - kind: pkg.KindTar, - }}); !reflect.DeepEqual(err, wantErr) { - panic(fmt.Sprintf("Cure: error = %v, want %v", err, wantErr)) - } - close(wCureDone) - }() - - // check cache activity while a cure is blocking - cureMany(t, c, []cureStep{ - {"error passthrough", newStubFile( - pkg.KindHTTPGet, - pkg.ID{0xff, 1}, - nil, - nil, stub.UniqueError(0xbad), - ), nil, nil, pkg.WNew, stub.UniqueError(0xbad)}, - - {"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return os.WriteFile( - t.GetWorkDir().String(), - []byte{0}, - 0400, - ) - }, - }}, nil, nil, pkg.WNew, errors.New( - "non-file artifact produced regular file", - )}, - }) - - wantErrScrub := &pkg.ScrubError{ - Errs: map[unique.Handle[string]][]error{ - base.Handle(): {errors.New("scrub began with pending artifacts")}, - }, - } - if err := c.Scrub(1 << 6); !reflect.DeepEqual(err, wantErrScrub) { - t.Fatalf("Scrub: error = %#v, want %#v", err, wantErrScrub) - } - - notify := c.Done(unique.Make(pkg.ID{0xff})) - go close(n) - if notify != nil { - <-notify - } - for c.Done(unique.Make(pkg.ID{0xff})) != nil { - } - <-wCureDone - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - "checksum": {Mode: fs.ModeDir | 0700}, - "identifier": {Mode: fs.ModeDir | 0700}, - "substitute": {Mode: fs.ModeDir | 0700}, - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"cancel abort block", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - var wg sync.WaitGroup - defer wg.Wait() - - var started sync.WaitGroup - defer started.Wait() - - blockCures := func(d byte, e stub.UniqueError, n int) { - started.Add(n) - for i := range n { - wg.Go(func() { - if _, _, err := c.Cure(overrideIdent{pkg.ID{d, byte(i)}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - started.Done() - <-t.Unwrap().Done() - return e + stub.UniqueError(i) - }, - }}); !reflect.DeepEqual(err, e+stub.UniqueError(i)) { - panic(err) - } - }) - } - started.Wait() - } - - blockCures(0xfd, 0xbad, 16) - c.Abort() - wg.Wait() - - blockCures(0xfd, 0xcafe, 16) - c.Abort() - wg.Wait() - - blockCures(0xff, 0xbad, 1) - if !c.Cancel(unique.Make(pkg.ID{0xff})) { - t.Fatal("missed cancellation") - } - wg.Wait() - - blockCures(0xff, 0xcafe, 1) - if !c.Cancel(unique.Make(pkg.ID{0xff})) { - t.Fatal("missed cancellation") - } - wg.Wait() - - for c.Cancel(unique.Make(pkg.ID{0xff})) { - } - - c.Close() - c.Abort() - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - "checksum": {Mode: fs.ModeDir | 0700}, - "identifier": {Mode: fs.ModeDir | 0700}, - "substitute": {Mode: fs.ModeDir | 0700}, - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"no assume checksum", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - makeGarbage := func(work *check.Absolute, wantErr error) error { - if err := os.Mkdir(work.String(), 0700); err != nil { - return err - } - - if err := os.WriteFile(work.Append( - "check", - ).String(), nil, 0400); err != nil { - return err - } - - return wantErr - } - - want := expectsChecksum(pkg.MustDecode( - "Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M", - )) - - cureMany(t, c, []cureStep{ - {"create", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return makeGarbage(t.GetWorkDir(), nil) - }, - }}}, base.Append( - "identifier", - pkg.Encode(pkg.ID{0xff, 0}), - ), want, pkg.WNew, nil}, - - {"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad)) - }, - }}}, nil, nil, pkg.WNew, stub.UniqueError(0xbad)}, - - {"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{ - kind: pkg.KindTar, - cure: func(t *pkg.TContext) error { - return makeGarbage(t.GetWorkDir(), nil) - }, - }}}, base.Append( - "identifier", - pkg.Encode(pkg.ID{0xff, 1}), - ), want, pkg.WNew, nil}, - }) - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M": {Mode: fs.ModeDir | 0500}, - "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check": {Mode: 0400, Data: []byte{}}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")}, - "identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"scrub", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - cureMany(t, c, []cureStep{ - {"bad measured file", newStubFile( - pkg.KindHTTPGet, - pkg.Checksum{0xfe, 0}, - &pkg.Checksum{0xff, 0}, - []byte{0}, nil, - ), base.Append( - "identifier", - pkg.Encode(pkg.Checksum{0xfe, 0}), - ), expectsChecksum{0xff, 0}, pkg.WNew, nil}, - }) - - for _, p := range [][]string{ - {"identifier", "invalid"}, - {"identifier", pkg.Encode(pkg.ID{0xfe, 0xff})}, - {"checksum", "invalid"}, - } { - if err := os.WriteFile( - base.Append(p...).String(), - nil, - 0400, - ); err != nil { - t.Fatal(err) - } - } - - for _, p := range [][]string{ - {"../nonexistent", "checksum", pkg.Encode(pkg.Checksum{0xff, 0xff})}, - {"../nonexistent", "identifier", pkg.Encode(pkg.Checksum{0xfe, 0xfe})}, - } { - if err := os.Symlink( - p[0], - base.Append(p[1:]...).String(), - ); err != nil { - t.Fatal(err) - } - } - - wantErr := newWantScrubError(base) - if err := c.Scrub(1 << 6); !reflect.DeepEqual(err, wantErr) { - t.Fatalf("Scrub: error =\n%s\nwant\n%s", err, wantErr) - } - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - "checksum": {Mode: fs.ModeDir | 0700}, - "identifier": {Mode: fs.ModeDir | 0700}, - "substitute": {Mode: fs.ModeDir | 0700}, - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"status substitute clean", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - destroyed := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("destroyed"), - deps: []pkg.Artifact{ - pkg.NewFile("destroyed-input", []byte("destroyed")), - }, - cure: func(f *pkg.FContext) error { - if w, err := f.GetStatusWriter(); err != nil { - return err - } else if _, err = w.Write([]byte("destroyed")); err != nil { - return err - } - - p := f.GetWorkDir() - if err := os.MkdirAll(p.String(), 0755); err != nil { - return err - } - return os.WriteFile(p.Append("result").String(), nil, 0444) - }, - } - substituted := new(*destroyed) - substituted.deps = []pkg.Artifact{ - pkg.NewFile("destroyed-input-0", []byte("destroyed")), - } - substituted.cure = func(*pkg.FContext) error { - panic("substitutable cure reached") - } - - cureMany(t, c, []cureStep{ - {"destroyed", destroyed, base.Append( - "identifier", - pkg.Encode(c.Ident(destroyed).Value()), - ), expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - "result": {Mode: 0444}, - }, pkg.WNew, nil}, - - {"substituted", substituted, base.Append( - "identifier", - pkg.Encode(c.Ident(substituted).Value()), - ), expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - "result": {Mode: 0444}, - }, pkg.WSubstitute, nil}, - }) - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE": {Mode: fs.ModeDir | 0500}, - "checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE/result": {Mode: 0444}, - "checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV": {Mode: 0400, Data: []byte("destroyed")}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/CLyyxJWn1yUGFs_0KnJ4ZSU2hH4-elvGFRB36x14LrNrKBJPxvORhL9O4Rc7oeYU": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, - "identifier/arv8a6z4i0x6pUb5Z2T-3iE4ETvyZj-uReHGKsS7uiBgMgKNEOzTGG3LIZb8vp0L": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/wILUy2izpj2sgKJVhGUGIAde1XVuqvp5BpFMIQHanT5Q8R6jK4QPVSrJsjZh-njV")}, - "identifier/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, - "identifier/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, - - "status": {Mode: fs.ModeDir | 0700}, - "status/q-VoVBI3IjcWTqwIokpi3y05CP113CHgHslc-XWnhOvDULwzVc3q9Y5xOCm_YyLZ": {Mode: fs.ModeSymlink | 0777, Data: []byte("dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x")}, - "status/heRgWhNJmhm898V68kw0ta76t4rP1o29tYW_TrdyBWXGfo37K3QWA7Z-JkLXAwcn": {Mode: 0400, Data: []byte(statusHeader + "destroyed")}, - "status/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: 0400, Data: []byte(statusHeader + "destroyed")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - "substitute/dP-6_wIDRRouOaOF-nkBy-IaUbLdYHbOUTrptu7j_qfW01mnHSjYJ0oykUmvUd2x": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UjZSrgz7_B7XMd9fHU7jM33UZhWlFgX0rz7JZbCBYR28bCS7jr_CAJdcDhi52ruE")}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"extern", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - a := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("extern"), - } - wantIdent := c.Ident(a) - wantOutput := expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - "result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, - } - var wantChecksum pkg.Checksum - if err := pkg.SumFS( - &wantChecksum, - fstest.MapFS(wantOutput), - ".", - ); err != nil { - t.Fatal(err) - } - wantChecksumH := unique.Make(wantChecksum) - - _a := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("extern substitute"), - deps: []pkg.Artifact{pkg.NewFile("", nil)}, - } - _wantIdent := c.Ident(_a) - _wantOutput := expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - } - var _wantChecksum pkg.Checksum - if err := pkg.SumFS( - &_wantChecksum, - fstest.MapFS(_wantOutput), - ".", - ); err != nil { - t.Fatal(err) - } - _wantChecksumH := unique.Make(_wantChecksum) - - kca := pkg.NewExec( - "", "", - new(pkg.Checksum), 0, false, false, - fhs.AbsRoot, nil, fhs.AbsRoot, nil, - ) - kcIdent := c.Ident(kca) - - c.SetExternal(stubExtern{ - artifact: map[unique.Handle[pkg.ID]]pkg.Checksum{ - wantIdent: wantChecksum, - _wantIdent: _wantChecksum, - kcIdent: wantChecksum, - }, - checksum: map[unique.Handle[pkg.Checksum]]fstest.MapFS{ - wantChecksumH: fstest.MapFS(wantOutput), - _wantChecksumH: fstest.MapFS(_wantOutput), - }, - status: map[unique.Handle[pkg.ID]]string{ - wantIdent: "\x00", - kcIdent: "unreachable", - }, - }) - - cureMany(t, c, []cureStep{ - {"extern", a, base.Append( - "identifier", - pkg.Encode(wantIdent.Value()), - ), wantOutput, pkg.WExternal, nil}, - - {"substitute", _a, base.Append( - "identifier", - pkg.Encode(_wantIdent.Value()), - ), _wantOutput, pkg.WExternal, nil}, - - {"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{ - Got: wantChecksum, - }}, - }) - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500}, - "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400}, - "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl": {Mode: fs.ModeDir | 0500}, - "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/ofaXbB5gIza_7W4Rzo5XDe_8FwlCPKWn3TBcmGgFAkkTWMl5GXGmOzX89Jd2Mk2A": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")}, - "identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - - "status": {Mode: fs.ModeDir | 0700}, - "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - "substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - - {"extern shallow", pkg.CExternShallow, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - a := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("extern"), - } - wantIdent := c.Ident(a) - wantOutput := expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - "result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, - } - var wantChecksum pkg.Checksum - if err := pkg.SumFS( - &wantChecksum, - fstest.MapFS(wantOutput), - ".", - ); err != nil { - t.Fatal(err) - } - wantChecksumH := unique.Make(wantChecksum) - - _a := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("extern substitute"), - deps: []pkg.Artifact{pkg.NewFile("", nil)}, - } - _wantIdent := c.Ident(_a) - _wantOutput := expectsFS{ - ".": {Mode: fs.ModeDir | 0500}, - } - var _wantChecksum pkg.Checksum - if err := pkg.SumFS( - &_wantChecksum, - fstest.MapFS(_wantOutput), - ".", - ); err != nil { - t.Fatal(err) - } - _wantChecksumH := unique.Make(_wantChecksum) - - kca := pkg.NewExec( - "", "", - new(pkg.Checksum), 0, false, false, - fhs.AbsRoot, nil, fhs.AbsRoot, nil, - ) - kcIdent := c.Ident(kca) - - fia := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("flood input"), - deps: []pkg.Artifact{_a}, - } - fiaIdent := c.Ident(fia) - - flia := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("flood input local"), - deps: []pkg.Artifact{_a}, - } - fliaIdent := c.Ident(flia) - - h := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("hanging input"), - } - - fhia := &stubArtifactF{ - kind: pkg.KindExec, - params: []byte("flood input local"), - deps: []pkg.Artifact{h}, - } - fhiaIdent := c.Ident(fhia) - - c.SetExternal(stubExtern{ - artifact: map[unique.Handle[pkg.ID]]pkg.Checksum{ - wantIdent: wantChecksum, - _wantIdent: _wantChecksum, - kcIdent: wantChecksum, - fiaIdent: wantChecksum, - fliaIdent: wantChecksum, - fhiaIdent: wantChecksum, - }, - checksum: map[unique.Handle[pkg.Checksum]]fstest.MapFS{ - wantChecksumH: fstest.MapFS(wantOutput), - _wantChecksumH: fstest.MapFS(_wantOutput), - }, - status: map[unique.Handle[pkg.ID]]string{ - wantIdent: "\x00", - kcIdent: "unreachable", - }, - }) - - cureMany(t, c, []cureStep{ - {"extern", a, base.Append( - "identifier", - pkg.Encode(wantIdent.Value()), - ), wantOutput, pkg.WExternal, nil}, - - {"flood shallow extern", fia, base.Append( - "identifier", - pkg.Encode(fiaIdent.Value()), - ), wantOutput, pkg.WExternal, nil}, - - {"substitute", _a, base.Append( - "identifier", - pkg.Encode(_wantIdent.Value()), - ), _wantOutput, pkg.WExternal, nil}, - - {"flood shallow local", flia, base.Append( - "identifier", - pkg.Encode(fliaIdent.Value()), - ), wantOutput, pkg.WExternal, nil}, - - {"flood shallow hanging", fhia, nil, nil, - pkg.WNew, pkg.HangingInputError(c.Ident(h))}, - - {"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{ - Got: wantChecksum, - }}, - }) - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - - "checksum": {Mode: fs.ModeDir | 0700}, - "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500}, - "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl": {Mode: fs.ModeDir | 0500}, - "checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl/result": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent")}, - - "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/3fYJjSiWhklt7TK9MPVLGk5_8AIU8ostTcFPXULJf_qeAVG6pmC-Cqqu4ZhEXRxn": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/8sInO_dhPW9kweit7jVuH_vtMkRxlZT7XE4_yEKPZmpGkgVxkmxz0OpXgbMsH6ET": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/Xys8hPpJsKirZmTTuT7SwQ6661TCp_ZRu8iUjPPD7pC5E3ll7xw4zhNlZ2PVcz_-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "identifier/k8yyhlBV3JpYzzywAnrRWkfp2TmgIDNC6FqMFwrrR2x0C3unBLveDNKgigOjG9MM": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "identifier/mXlNz_v77nW7jstn_rJn4RL7dCQlkakM0y-HjO6tkDubtzaj-wCmW1hIr2Gk64_O": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - - "status": {Mode: fs.ModeDir | 0700}, - "status/8VL-egZySw-RbnHZtxGWdf5Z2v9S9CihrdFwa54Bc5EYMQcEgWEem7QrdCTWlCb8": {Mode: 0400, Data: []byte("\x00")}, - - "substitute": {Mode: fs.ModeDir | 0700}, - "substitute/socGRnhdsJlJ4Z01ZwHFZdLzFH0rWvoaJrylcUKtvhBdGsE7VoYl-vdUuvfK8B4I": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")}, - "substitute/MccYezQ4pshkeBV4w_aAEIwvZdKHL3OAgAkR3ouZ43EF94Ur1HBHaN7njPfJAj50": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - "substitute/VV5W0_DiA1iylaqbKFThp1ZpV_y1ccVS1XyqDnDaXoHQ-EEyPI4XFrQHcHOF2hWG": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fHkl_RuHOoc4rso__nV-qreikovd6Yhrq5mpBlkf5hmPGaxDlik2bYOQ4dhUQjtl")}, - - "work": {Mode: fs.ModeDir | 0700}, - }}, - } - checkWithCache(t, testCases) -} - -func TestErrors(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - err error - want string - }{ - {"InvalidLookupError", pkg.InvalidLookupError{ - 0xff, 0xf0, - }, "attempting to look up non-input artifact __AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}, - - {"InvalidArtifactError", pkg.InvalidArtifactError{ - 0xff, 0xfd, - }, "artifact __0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA cannot be cured"}, - - {"ChecksumMismatchError", &pkg.ChecksumMismatchError{ - Want: (pkg.Checksum)(bytes.Repeat([]byte{ - 0x75, 0xe6, 0x9d, 0x6d, 0xe7, 0x9f, - }, 8)), - }, "got AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + - " instead of deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"}, - - {"ResponseStatusError", pkg.ResponseStatusError( - http.StatusNotAcceptable, - ), "the requested URL returned non-OK status: Not Acceptable"}, - - {"DisallowedTypeflagError", pkg.DisallowedTypeflagError( - tar.TypeChar, - ), "disallowed typeflag '3'"}, - - {"InvalidFileModeError", pkg.InvalidFileModeError( - fs.ModeSymlink | 0777, - ), "artifact did not produce a regular file or directory"}, - - {"NoOutputError", pkg.NoOutputError{ - // empty struct - }, "artifact cured successfully but did not produce any output"}, - - {"IRKindError", &pkg.IRKindError{ - Got: pkg.IRKindEnd, - Want: pkg.IRKindIdent, - Ancillary: 0xcafebabe, - }, "got terminator IR value (0xcafebabe) instead of ident"}, - {"IRKindError invalid", &pkg.IRKindError{ - Got: 0xbeef, - Want: pkg.IRKindIdent, - Ancillary: 0xcafe, - }, "got invalid kind 48879 IR value (0xcafe) instead of ident"}, - - {"UnsupportedVariantError", pkg.UnsupportedVariantError( - "rosa", - ), `unsupported variant "rosa"`}, - - {"UnsupportedArchError zero", pkg.UnsupportedArchError(""), - "invalid architecture name"}, - {"UnsupportedArchError", pkg.UnsupportedArchError("riscv64"), - "unsupported architecture riscv64"}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - if got := tc.err.Error(); got != tc.want { - t.Errorf("Error: %q, want %q", got, tc.want) - } - }) - } -} - -func TestScrubError(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - err pkg.ScrubError - want string - unwrap []error - }{ - {"sample", *newWantScrubError( - fhs.AbsVarLib.Append("cure"), - ), `checksum mismatches: -got vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX instead of _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - -dangling identifiers: -_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -_v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - -errors during scrub: - /var/lib/cure/checksum/__8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: - artifact did not produce a regular file or directory - /var/lib/cure/checksum/invalid: - illegal base64 data at input byte 4 - /var/lib/cure/identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: - readlink /var/lib/cure/identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: invalid argument - /var/lib/cure/identifier/invalid: - illegal base64 data at input byte 4 - /var/lib/cure/nonexistent: - illegal base64 data at input byte 8 -`, []error{ - &pkg.ChecksumMismatchError{Got: pkg.MustDecode( - "vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", - ), Want: pkg.Checksum{0xff, 0}}, - - pkg.InvalidFileModeError(fs.ModeSymlink), - base64.CorruptInputError(4), - - &os.PathError{ - Op: "readlink", - Path: fhs.AbsVarLib.Append("cure").Append( - "identifier", - pkg.Encode(pkg.ID{0xfe, 0xff}), - ).String(), - Err: syscall.EINVAL, - }, - - base64.CorruptInputError(4), - base64.CorruptInputError(8), - }}, - - {"full", pkg.ScrubError{ - ChecksumMismatches: []pkg.ChecksumMismatchError{ - {Want: pkg.MustDecode("CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")}, - }, - DanglingIdentifiers: []pkg.ID{ - (pkg.ID)(bytes.Repeat([]byte{0x75, 0xe6, 0x9d, 0x6d, 0xe7, 0x9f}, 8)), - (pkg.ID)(bytes.Repeat([]byte{0x71, 0xa7, 0xde, 0x6d, 0xa6, 0xde}, 8)), - }, - Errs: map[unique.Handle[string]][]error{ - unique.Make("/proc/nonexistent"): { - stub.UniqueError(0xcafe), - stub.UniqueError(0xbad), - stub.UniqueError(0xff), - }, - }, - }, `checksum mismatches: -got AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA instead of CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN - -dangling identifiers: -deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef -cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe - -errors during scrub: - /proc/nonexistent: - unique error 51966 injected by the test suite - unique error 2989 injected by the test suite - unique error 255 injected by the test suite -`, []error{ - &pkg.ChecksumMismatchError{Want: pkg.MustDecode("CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")}, - stub.UniqueError(0xcafe), - stub.UniqueError(0xbad), - stub.UniqueError(0xff), - }}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - if got := tc.err.Error(); got != tc.want { - t.Errorf("Error:\n\n%s\n\nwant\n\n%s", got, tc.want) - } - - if unwrap := tc.err.Unwrap(); !reflect.DeepEqual(unwrap, tc.unwrap) { - t.Errorf("Unwrap: %#v, want %#v", unwrap, tc.unwrap) - } - }) - } -} - -func TestInputError(t *testing.T) { - t.Parallel() - - makeIdent := func(ident ...byte) pkg.Artifact { - var a overrideIdent - copy(a.id[:], ident) - // does not compare equal - a.TrivialArtifact = new(stubArtifact) - return a - } - - testCases := []struct { - name string - err pkg.InputError - want string - unwrap []error - }{ - {"simple", pkg.InputError{ - makeIdent(0xff, 9): stub.UniqueError(0xbad09), - makeIdent(0xff, 0): stub.UniqueError(0xbad00), - makeIdent(0xff, 0xf): stub.UniqueError(0xbad0f), - makeIdent(0xff, 1): stub.UniqueError(0xbad01), - }, `errors curing inputs: - _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite - _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite - _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite - _w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{ - stub.UniqueError(0xbad00), - stub.UniqueError(0xbad01), - stub.UniqueError(0xbad09), - stub.UniqueError(0xbad0f), - }}, - - {"dedup", pkg.InputError{ - makeIdent(0xff, 9): stub.UniqueError(0xbad09), - makeIdent(0xff, 9): stub.UniqueError(0xbad09), - makeIdent(0xff, 9): stub.UniqueError(0xbad09), - makeIdent(0xff, 0): stub.UniqueError(0xbad00), - makeIdent(0xff, 0): stub.UniqueError(0xbad00), - makeIdent(0xff, 1): stub.UniqueError(0xbad01), - }, `errors curing inputs: - _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite - _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite - _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite`, []error{ - stub.UniqueError(0xbad00), - stub.UniqueError(0xbad01), - stub.UniqueError(0xbad09), - }}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - if got := tc.err.Error(); got != tc.want { - t.Errorf("Error:\n%s\nwant\n%s", got, tc.want) - } - - if unwrap := tc.err.Unwrap(); !reflect.DeepEqual(unwrap, tc.unwrap) { - t.Errorf("Unwrap: %#v, want %#v", unwrap, tc.unwrap) - } - }) - } -} - -// earlyFailureF is a [FloodArtifact] with a large dependency graph resulting in -// a large [DependencyCureError]. -type earlyFailureF int - -func (earlyFailureF) Kind() pkg.Kind { return pkg.KindExec } -func (earlyFailureF) Params(*pkg.IContext) {} -func (earlyFailureF) IsExclusive() bool { return false } - -func (a earlyFailureF) Inputs() []pkg.Artifact { - deps := make([]pkg.Artifact, a) - for i := range deps { - deps[i] = a - 1 - } - return deps -} - -func (a earlyFailureF) Cure(*pkg.FContext) error { - if a != 0 { - panic("unexpected cure on " + strconv.Itoa(int(a))) - } - return stub.UniqueError(0xcafe) -} - -func BenchmarkEarlyDCE(b *testing.B) { - msg := message.New(log.New(os.Stderr, "dce: ", 0)) - msg.SwapVerbose(testing.Verbose()) - - for b.Loop() { - b.StopTimer() - c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil) - if err != nil { - b.Fatal(err) - } - b.StartTimer() - _, _, err = c.Cure(earlyFailureF(8)) - b.StopTimer() - if !errors.Is(err, stub.UniqueError(0xcafe)) { - b.Fatalf("Cure: error = %v", err) - } - c.Close() - b.StartTimer() - } -} - -func TestDependencyCureErrorEarly(t *testing.T) { - t.Parallel() - - checkWithCache(t, []cacheTestCase{ - {"early", 0, nil, func(t *testing.T, _ *check.Absolute, c *pkg.Cache) { - _, _, err := c.Cure(earlyFailureF(8)) - if !errors.Is(err, stub.UniqueError(0xcafe)) { - t.Fatalf("Cure: error = %v", err) - } - }, expectsFS{ - ".": {Mode: fs.ModeDir | 0700}, - "checksum": {Mode: fs.ModeDir | 0700}, - "identifier": {Mode: fs.ModeDir | 0700}, - "substitute": {Mode: fs.ModeDir | 0700}, - "work": {Mode: fs.ModeDir | 0700}, - }}, - }) -} - -func TestOpen(t *testing.T) { - t.Parallel() - - t.Run("nonexistent", func(t *testing.T) { - t.Parallel() - - wantErr := &os.PathError{ - Op: "mkdir", - Path: container.Nonexistent, - Err: syscall.ENOENT, - } - if _, err := pkg.Open( - t.Context(), - message.New(nil), - check.MustAbs(container.Nonexistent), - nil, - ); !reflect.DeepEqual(err, wantErr) { - t.Errorf("Open: error = %#v, want %#v", err, wantErr) - } - }) - - t.Run("permission", func(t *testing.T) { - t.Parallel() - - tempDir := check.MustAbs(t.TempDir()) - if err := os.Chmod(tempDir.String(), 0); err != nil { - t.Fatal(err) - } else { - t.Cleanup(func() { - if err = os.Chmod(tempDir.String(), 0700); err != nil { - t.Fatal(err) - } - }) - } - - wantErr := &os.PathError{ - Op: "mkdir", - Path: tempDir.Append("cache").String(), - Err: syscall.EACCES, - } - if _, err := pkg.Open( - t.Context(), - message.New(nil), - tempDir.Append("cache"), - nil, - ); !reflect.DeepEqual(err, wantErr) { - t.Errorf("Open: error = %#v, want %#v", err, wantErr) - } - }) - - t.Run("dirty", func(t *testing.T) { - t.Parallel() - - tempDir := check.MustAbs(t.TempDir()) - if err := os.MkdirAll(tempDir.Append( - "cache", - "work", - "dirty", - ).String(), 0755); err != nil { - t.Fatal(err) - } - - wantErr := errors.New("work is not empty, scrub likely required") - if _, err := pkg.Open( - t.Context(), - message.New(nil), - tempDir.Append("cache"), - nil, - ); !reflect.DeepEqual(err, wantErr) { - t.Errorf("Open: error = %#v, want %#v", err, wantErr) - } - }) - - t.Run("scratch", func(t *testing.T) { - t.Parallel() - - tempDir := check.MustAbs(t.TempDir()) - if err := os.MkdirAll(tempDir.Append( - "cache", - "scratch", - ).String(), 0755); err != nil { - t.Fatal(err) - } - - wantErr := errors.New("scratch is present, scrub likely required") - if _, err := pkg.Open( - t.Context(), - message.New(nil), - tempDir.Append("cache"), nil, - ); !reflect.DeepEqual(err, wantErr) { - t.Errorf("Open: error = %#v, want %#v", err, wantErr) - } - }) -} - -func TestExtensionRegister(t *testing.T) { - extensionOld := extension - openedOld := opened - t.Cleanup(func() { extension = extensionOld; opened = openedOld }) - extension = "" - opened = false - - t.Run("set", func(t *testing.T) { - t.Cleanup(func() { extension = "" }) - - const want = "rosa" - pkg.SetExtension(want) - if got := pkg.Extension(); got != want { - t.Fatalf("Extension: %q, want %q", got, want) - } - }) - - t.Run("twice", func(t *testing.T) { - t.Cleanup(func() { extension = "" }) - - defer func() { - const wantPanic = "attempting to set extension twice" - if r := recover(); r != wantPanic { - t.Errorf("panic: %#v, want %q", r, wantPanic) - } - }() - pkg.SetExtension("rosa") - pkg.SetExtension("rosa") - }) - - t.Run("invalid", func(t *testing.T) { - defer func() { - var wantPanic = pkg.ErrInvalidExtension - if r := recover(); r != wantPanic { - t.Errorf("panic: %#v, want %#v", r, wantPanic) - } - }() - pkg.SetExtension(" ") - }) - - t.Run("opened", func(t *testing.T) { - t.Cleanup(func() { opened = false }) - - if _, err := pkg.Open( - t.Context(), - message.New(log.Default()), - check.MustAbs(container.Nonexistent), - nil, - ); !errors.Is(err, os.ErrNotExist) { - t.Fatalf("Open: error = %v", err) - } - - t.Run("variant", func(t *testing.T) { - defer func() { - const wantPanic = "attempting to set extension after open" - if r := recover(); r != wantPanic { - t.Errorf("panic: %#v, want %q", r, wantPanic) - } - }() - pkg.SetExtension("rosa") - }) - - t.Run("register", func(t *testing.T) { - defer func() { - const wantPanic = "attempting to register after open" - if r := recover(); r != wantPanic { - t.Errorf("panic: %#v, want %q", r, wantPanic) - } - }() - pkg.Register(pkg.KindCustomOffset, nil) - }) - }) - - t.Run("incomplete", func(t *testing.T) { - t.Cleanup(func() { delete(irArtifact, pkg.KindCustomOffset) }) - - defer func() { - const wantPanic = "attempting to open cache with incomplete variant setup" - if r := recover(); r != wantPanic { - t.Errorf("panic: %#v, want %q", r, wantPanic) - } - }() - pkg.Register(pkg.KindCustomOffset, nil) - - t.Cleanup(func() { opened = false }) - _, _ = pkg.Open(nil, nil, nil, nil) - panic("unreachable") - }) - - t.Run("create", func(t *testing.T) { - t.Cleanup(func() { extension = "" }) - const want = "rosa" - pkg.SetExtension(want) - - base := check.MustAbs(t.TempDir()) - t.Cleanup(func() { opened = false }) - if c, err := pkg.Open(t.Context(), nil, base, nil); err != nil { - t.Fatal(err) - } else { - c.Close() - } - - if got, err := os.ReadFile(base.Append("variant").String()); err != nil { - t.Fatal(err) - } else if string(got) != want { - t.Fatalf("variant: %q", string(got)) - } - }) - - t.Run("access", func(t *testing.T) { - base := check.MustAbs(t.TempDir()) - t.Cleanup(func() { opened = false }) - - if err := os.WriteFile(base.Append("variant").String(), nil, 0); err != nil { - t.Fatal(err) - } - - wantErr := &os.PathError{ - Op: "open", - Path: base.Append("variant").String(), - Err: syscall.EACCES, - } - if _, err := pkg.Open( - t.Context(), nil, - base, nil, - ); !reflect.DeepEqual(err, wantErr) { - t.Fatalf("Open: error = %v, want %v", err, wantErr) - } - }) - - t.Run("promote", func(t *testing.T) { - t.Cleanup(func() { extension = "" }) - const want = "rosa" - pkg.SetExtension(want) - - base := check.MustAbs(t.TempDir()) - t.Cleanup(func() { opened = false }) - - variantPath := base.Append("variant") - if err := os.WriteFile(variantPath.String(), nil, 0600); err != nil { - t.Fatal(err) - } - - if _, err := pkg.Open( - t.Context(), nil, - base, - nil, - ); !reflect.DeepEqual(err, pkg.ErrWouldPromote) { - t.Fatalf("Open: error = %v", err) - } - - if p, err := os.ReadFile(variantPath.String()); err != nil { - t.Fatal(err) - } else if len(p) != 0 { - t.Fatalf("variant: %q", string(p)) - } - - if c, err := pkg.Open( - t.Context(), nil, - base, &pkg.CacheAttr{Flags: pkg.CPromoteVariant}, - ); err != nil { - t.Fatalf("Open: error = %v", err) - } else { - c.Close() - } - - if p, err := os.ReadFile(variantPath.String()); err != nil { - t.Fatal(err) - } else if string(p) != want { - t.Fatalf("variant: %q, want %q", string(p), want) - } - }) - - t.Run("open invalid", func(t *testing.T) { - base := check.MustAbs(t.TempDir()) - t.Cleanup(func() { opened = false }) - - variantPath := base.Append("variant") - if err := os.WriteFile(variantPath.String(), make([]byte, 129), 0400); err != nil { - t.Fatal(err) - } - - if _, err := pkg.Open( - t.Context(), nil, - base, nil, - ); !reflect.DeepEqual(err, pkg.ErrInvalidExtension) { - t.Fatalf("Open: error = %v", err) - } - }) - - t.Run("unsupported", func(t *testing.T) { - base := check.MustAbs(t.TempDir()) - t.Cleanup(func() { opened = false }) - - variantPath := base.Append("variant") - if err := os.WriteFile(variantPath.String(), []byte("rosa"), 0400); err != nil { - t.Fatal(err) - } - - if _, err := pkg.Open( - t.Context(), nil, - base, nil, - ); !reflect.DeepEqual(err, pkg.UnsupportedVariantError("rosa")) { - t.Fatalf("Open: error = %v", err) - } - }) -} |
