internal/pkg: expose cure whence
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 3m1s
Test / ShareFS (push) Successful in 3m53s
Test / Hakurei (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m5s

Useful for cure determinism validation of KindExec.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-07-08 14:19:17 +09:00
parent aa5e77ef27
commit 3c6e9b3d05
7 changed files with 128 additions and 70 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ func TestArchiveArtifact(t *testing.T) {
cureMany(t, c, []cureStep{ cureMany(t, c, []cureStep{
{"sample", pkg.NewArchive( {"sample", pkg.NewArchive(
pkg.NewFile("", buf.Bytes()), pkg.NewFile("", buf.Bytes()),
), ignorePathname, expectsFS(want), nil}, ), ignorePathname, expectsFS(want), pkg.WNew, nil},
}) })
}, expectsFS{ }, expectsFS{
".": {Mode: fs.ModeDir | 0700}, ".": {Mode: fs.ModeDir | 0700},
+2 -2
View File
@@ -43,7 +43,7 @@ func TestDecompress(t *testing.T) {
&client, &client,
"file:///testdata", "file:///testdata",
pkg.Checksum{0xfd}, pkg.Checksum{0xfd},
), pkg.Gzip), nil, nil, &pkg.ChecksumMismatchError{ ), pkg.Gzip), nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: testdataChecksum, Got: testdataChecksum,
Want: pkg.Checksum{0xfd}, Want: pkg.Checksum{0xfd},
}}, }},
@@ -52,7 +52,7 @@ func TestDecompress(t *testing.T) {
&client, &client,
"file:///testdata", "file:///testdata",
testdataChecksum, testdataChecksum,
), pkg.Gzip), ignorePathname, expectsChecksum(sha512.Sum384([]byte{0})), nil}, ), pkg.Gzip), ignorePathname, expectsChecksum(sha512.Sum384([]byte{0})), pkg.WNew, nil},
}) })
}, expectsFS{ }, expectsFS{
".": {Mode: fs.ModeDir | 0700}, ".": {Mode: fs.ModeDir | 0700},
+10 -10
View File
@@ -84,7 +84,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WNew, nil},
{"substitution", pkg.NewExec( {"substitution", pkg.NewExec(
"exec-offline", "", new(wantOffline.hash()), 0, false, false, "exec-offline", "", new(wantOffline.hash()), 0, false, false,
@@ -108,7 +108,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WSubstitute, nil},
{"error passthrough", pkg.NewExec( {"error passthrough", pkg.NewExec(
"", "", nil, 0, false, true, "", "", nil, 0, false, true,
@@ -118,7 +118,7 @@ func TestExec(t *testing.T) {
[]string{"testtool"}, []string{"testtool"},
pkg.MustPath("/proc/nonexistent", false, failingArtifact), pkg.MustPath("/proc/nonexistent", false, failingArtifact),
), nil, nil, &pkg.DependencyCureError{ ), nil, nil, pkg.WNew, &pkg.DependencyCureError{
{ {
A: failingArtifact, A: failingArtifact,
Err: stub.UniqueError(0xcafe), Err: stub.UniqueError(0xcafe),
@@ -133,7 +133,7 @@ func TestExec(t *testing.T) {
[]string{"testtool"}, []string{"testtool"},
pkg.ExecPath{}, pkg.ExecPath{},
), nil, nil, pkg.ErrInvalidPaths}, ), nil, nil, pkg.WNew, pkg.ErrInvalidPaths},
}) })
// check init failure passthrough // check init failure passthrough
@@ -225,7 +225,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantNet, nil}, ), ignorePathname, wantNet, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
@@ -269,7 +269,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
@@ -316,7 +316,7 @@ func TestExec(t *testing.T) {
return os.MkdirAll(t.GetWorkDir().String(), 0700) return os.MkdirAll(t.GetWorkDir().String(), 0700)
}, },
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool), }), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
@@ -385,7 +385,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
@@ -438,7 +438,7 @@ func TestExec(t *testing.T) {
}, },
}), }),
pkg.MustPath("/opt", false, testtool), pkg.MustPath("/opt", false, testtool),
), ignorePathname, wantOffline, nil}, ), ignorePathname, wantOffline, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
@@ -503,7 +503,7 @@ func TestExec(t *testing.T) {
".": {Mode: fs.ModeDir | 0500}, ".": {Mode: fs.ModeDir | 0500},
"check": {Mode: 0400, Data: []byte("binfmt")}, "check": {Mode: 0400, Data: []byte("binfmt")},
}, nil}, }, pkg.WNew, nil},
}) })
destroyStatus(t, base, 2, 0) destroyStatus(t, base, 2, 0)
+1 -1
View File
@@ -18,7 +18,7 @@ func TestFile(t *testing.T) {
{"short", pkg.NewFile("null", []byte{0}), base.Append( {"short", pkg.NewFile("null", []byte{0}), base.Append(
"identifier", "identifier",
"3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi", "3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi",
), want, nil}, ), want, pkg.WNew, nil},
}) })
}, expectsFS{ }, expectsFS{
".": {Mode: fs.ModeDir | 0700}, ".": {Mode: fs.ModeDir | 0700},
+62 -7
View File
@@ -303,7 +303,7 @@ func (c *common) Open(a Artifact) (r io.ReadCloser, err error) {
} }
var pathname *check.Absolute var pathname *check.Absolute
if pathname, _, err = c.cache.cure(a, true); err != nil { if pathname, _, _, err = c.cache.cure(a, true); err != nil {
return return
} }
@@ -356,12 +356,12 @@ func (f *FContext) linkSubstitute(ids, substitutes string) (err error) {
return return
} }
// InvalidLookupError is the identifier of non-dependency [Artifact] looked up // InvalidLookupError is the identifier of non-input [Artifact] looked up
// via [FContext.GetArtifact] by a misbehaving [Artifact] implementation. // via [FContext.GetArtifact] by a misbehaving [Artifact] implementation.
type InvalidLookupError ID type InvalidLookupError ID
func (e InvalidLookupError) Error() string { func (e InvalidLookupError) Error() string {
return "attempting to look up non-dependency artifact " + Encode(e) return "attempting to look up non-input artifact " + Encode(e)
} }
var _ error = InvalidLookupError{} var _ error = InvalidLookupError{}
@@ -602,7 +602,7 @@ type cureRes struct {
checksum unique.Handle[Checksum] checksum unique.Handle[Checksum]
} }
// A pendingArtifactDep is a dependency [Artifact] pending concurrent curing, // A pendingArtifactDep is an input [Artifact] pending concurrent curing,
// subject to the cures limit. Values pointed to by result addresses are safe // subject to the cures limit. Values pointed to by result addresses are safe
// to access after the [sync.WaitGroup] associated with this pendingArtifactDep // to access after the [sync.WaitGroup] associated with this pendingArtifactDep
// is done. pendingArtifactDep must not be reused or modified after it is sent // is done. pendingArtifactDep must not be reused or modified after it is sent
@@ -676,7 +676,7 @@ const (
// suppressed regardless of [message.Msg] state. // suppressed regardless of [message.Msg] state.
CSuppressInit CSuppressInit
// CIgnoreSubstitutes disables content-based dependency substitution. // CIgnoreSubstitutes disables content-based input substitution.
CIgnoreSubstitutes CIgnoreSubstitutes
// CExternShallow arranges for only non-flood inputs to be fetched when // CExternShallow arranges for only non-flood inputs to be fetched when
@@ -733,7 +733,7 @@ type Cache struct {
parent context.Context parent context.Context
// For deriving curing context, must not be accessed directly. // For deriving curing context, must not be accessed directly.
toplevel atomic.Pointer[toplevel] toplevel atomic.Pointer[toplevel]
// For waiting on dependency curing goroutines. // For waiting on input curing goroutines.
wg sync.WaitGroup wg sync.WaitGroup
// Reports new cures and passed to [Artifact]. // Reports new cures and passed to [Artifact].
msg message.Msg msg message.Msg
@@ -1633,6 +1633,24 @@ func (c *Cache) Cure(a Artifact) (
return return
} }
pathname, checksum, _, err = c.cure(a, true)
return
}
// CureWhence is like Cure, but returns the whence value.
func (c *Cache) CureWhence(a Artifact) (
pathname *check.Absolute,
checksum unique.Handle[Checksum],
whence int,
err error,
) {
c.abortMu.RLock()
defer c.abortMu.RUnlock()
if err = c.toplevel.Load().ctx.Err(); err != nil {
return
}
return c.cure(a, true) return c.cure(a, true)
} }
@@ -1971,11 +1989,41 @@ func (e HangingInputError) Error() string {
return Encode(unique.Handle[ID](e).Value()) + " is unavailable" return Encode(unique.Handle[ID](e).Value()) + " is unavailable"
} }
const (
// WNew indicates a cure entering the implementation.
WNew = iota
// WCache indicates an [Artifact] present in the cache.
WCache
// WSubstitute indicates an [Artifact] hitting a content-based input
// substitution.
WSubstitute
// WExternal indicates a cure entering the external cache.
WExternal
)
// WhenceString returns a printable string for a whence value.
func WhenceString(whence int) string {
switch whence {
case WNew:
return "new"
case WCache:
return "cache"
case WSubstitute:
return "substitute"
case WExternal:
return "external"
default:
return "invalid whence " + strconv.Itoa(whence)
}
}
// cure implements Cure without acquiring a read lock on abortMu. cure must not // cure implements Cure without acquiring a read lock on abortMu. cure must not
// be entered during Abort. // be entered during Abort.
func (c *Cache) cure(a Artifact, curesExempt bool) ( func (c *Cache) cure(a Artifact, curesExempt bool) (
pathname *check.Absolute, pathname *check.Absolute,
checksum unique.Handle[Checksum], checksum unique.Handle[Checksum],
whence int,
err error, err error,
) { ) {
id := c.Ident(a) id := c.Ident(a)
@@ -2001,6 +2049,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
) )
ctx, done, checksum, err = c.loadOrStoreIdent(id) ctx, done, checksum, err = c.loadOrStoreIdent(id)
if done == nil { if done == nil {
whence = WCache
return return
} else { } else {
defer func() { c.finaliseIdent(done, id, checksum, err) }() defer func() { c.finaliseIdent(done, id, checksum, err) }()
@@ -2008,6 +2057,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
checksum, err = c.tryChecksum(pathname) checksum, err = c.tryChecksum(pathname)
if err == nil || !errors.Is(err, os.ErrNotExist) { if err == nil || !errors.Is(err, os.ErrNotExist) {
whence = WCache
return return
} }
@@ -2077,6 +2127,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
} }
} }
whence = WNew
if c.msg.IsVerbose() { if c.msg.IsVerbose() {
rn := reportName(a, id) rn := reportName(a, id)
c.msg.Verbosef("curing %s...", rn) c.msg.Verbosef("curing %s...", rn)
@@ -2095,6 +2146,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
// cure FileArtifact outside type switch to skip TContext initialisation // cure FileArtifact outside type switch to skip TContext initialisation
if f, ok := a.(FileArtifact); ok { if f, ok := a.(FileArtifact); ok {
if checksumFi != nil { if checksumFi != nil {
whence = WCache
if !checksumFi.Mode().IsRegular() { if !checksumFi.Mode().IsRegular() {
// unreachable // unreachable
err = InvalidFileModeError(checksumFi.Mode()) err = InvalidFileModeError(checksumFi.Mode())
@@ -2199,6 +2251,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
} }
if checksumFi != nil { if checksumFi != nil {
whence = WCache
if !checksumFi.Mode().IsDir() { if !checksumFi.Mode().IsDir() {
// unreachable // unreachable
err = InvalidFileModeError(checksumFi.Mode()) err = InvalidFileModeError(checksumFi.Mode())
@@ -2308,6 +2361,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
return return
} }
if substituteChecksum != zeroChecksum { if substituteChecksum != zeroChecksum {
whence = WSubstitute
checksum = substituteChecksum checksum = substituteChecksum
checksums = Encode(checksum.Value()) checksums = Encode(checksum.Value())
checksumPathname = c.base.Append( checksumPathname = c.base.Append(
@@ -2332,6 +2386,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
defer f.destroy(&err) defer f.destroy(&err)
if extern { if extern {
whence = WExternal
if checksum != zeroChecksum && externChecksum != checksum { if checksum != zeroChecksum && externChecksum != checksum {
err = &ChecksumMismatchError{externChecksum.Value(), checksum.Value()} err = &ChecksumMismatchError{externChecksum.Value(), checksum.Value()}
if c.msg.IsVerbose() { if c.msg.IsVerbose() {
@@ -2471,7 +2526,7 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
defer pending.Done() defer pending.Done()
var err error var err error
pending.resP.pathname, pending.resP.checksum, err = c.cure(pending.a, false) pending.resP.pathname, pending.resP.checksum, _, err = c.cure(pending.a, false)
if err == nil { if err == nil {
return return
} }
+47 -44
View File
@@ -627,6 +627,7 @@ type cureStep struct {
pathname *check.Absolute pathname *check.Absolute
output expectsKnown output expectsKnown
whence int
err error err error
} }
@@ -646,7 +647,7 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
for _, step := range steps { for _, step := range steps {
t.Log("cure step:", step.name) t.Log("cure step:", step.name)
if pathname, checksum, err := c.Cure(step.a); !reflect.DeepEqual(err, step.err) { if pathname, checksum, whence, err := c.CureWhence(step.a); !reflect.DeepEqual(err, step.err) {
faults, _err := c.ReadFaults(step.a) faults, _err := c.ReadFaults(step.a)
if _err != nil { if _err != nil {
t.Errorf("ReadFaults: error = %v", _err) t.Errorf("ReadFaults: error = %v", _err)
@@ -663,6 +664,8 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time())) t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time()))
} }
t.Fatalf("Cure: error = %v, want %v", err, step.err) 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) { } else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname) t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
} else if step.output == nil || checksum != makeChecksumH(step.output.hash()) { } else if step.output == nil || checksum != makeChecksumH(step.output.hash()) {
@@ -774,28 +777,28 @@ func TestCache(t *testing.T) {
identifier, identifier,
new(testdata.hash()), new(testdata.hash()),
testdata, nil, testdata, nil,
), wantPathname, testdata, nil}, ), wantPathname, testdata, pkg.WNew, nil},
{"identical content", newStubFile( {"identical content", newStubFile(
pkg.KindHTTPGet, pkg.KindHTTPGet,
identifier0, identifier0,
new(testdata.hash()), new(testdata.hash()),
testdata, nil, testdata, nil,
), wantPathname0, testdata, nil}, ), wantPathname0, testdata, pkg.WCache, nil},
{"existing entry", newStubFile( {"existing entry", newStubFile(
pkg.KindHTTPGet, pkg.KindHTTPGet,
identifier, identifier,
new(testdata.hash()), new(testdata.hash()),
testdata, nil, testdata, nil,
), wantPathname, testdata, nil}, ), wantPathname, testdata, pkg.WCache, nil},
{"checksum mismatch", newStubFile( {"checksum mismatch", newStubFile(
pkg.KindHTTPGet, pkg.KindHTTPGet,
pkg.ID{0xff, 0}, pkg.ID{0xff, 0},
new(pkg.Checksum), new(pkg.Checksum),
testdata, nil, testdata, nil,
), nil, nil, &pkg.ChecksumMismatchError{ ), nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: testdata.hash(), Got: testdata.hash(),
}}, }},
@@ -816,12 +819,12 @@ func TestCache(t *testing.T) {
0x36, 0x65, 0x59, 0x33, 0xec, 0x2b, 0x36, 0x65, 0x59, 0x33, 0xec, 0x2b,
0x41, 0x34, 0x65, 0x96, 0x68, 0x17, 0x41, 0x34, 0x65, 0x96, 0x68, 0x17,
0xa9, 0xc2, 0x08, 0xa1, 0x17, 0x17, 0xa9, 0xc2, 0x08, 0xa1, 0x17, 0x17,
}, nil}, }, pkg.WNew, nil},
{"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{ {"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{
kind: pkg.KindExec, kind: pkg.KindExec,
params: []byte("artifact overridden to be incomplete"), params: []byte("artifact overridden to be incomplete"),
}}, nil, nil, pkg.InvalidArtifactError(pkg.MustDecode( }}, nil, nil, pkg.WNew, pkg.InvalidArtifactError(pkg.MustDecode(
"E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ", "E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ",
))}, ))},
@@ -830,18 +833,18 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 1}, pkg.ID{0xff, 1},
nil, nil,
nil, stub.UniqueError(0xcafe), nil, stub.UniqueError(0xcafe),
), nil, nil, stub.UniqueError(0xcafe)}, ), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
{"error caching", newStubFile( {"error caching", newStubFile(
pkg.KindHTTPGet, pkg.KindHTTPGet,
pkg.ID{0xff, 1}, pkg.ID{0xff, 1},
nil, nil,
nil, nil, nil, nil,
), nil, nil, stub.UniqueError(0xcafe)}, ), nil, nil, pkg.WCache, stub.UniqueError(0xcafe)},
{"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{ {"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
}}}, nil, nil, pkg.InvalidFileModeError( }}}, nil, nil, pkg.WCache, pkg.InvalidFileModeError(
0400, 0400,
)}, )},
@@ -853,7 +856,7 @@ func TestCache(t *testing.T) {
cure: func(f *pkg.FContext) error { cure: func(f *pkg.FContext) error {
panic("attempting to cure impossible artifact") panic("attempting to cure impossible artifact")
}, },
}, nil, nil, &pkg.DependencyCureError{ }, nil, nil, pkg.WNew, &pkg.DependencyCureError{
{ {
A: failingFile, A: failingFile,
Err: struct { Err: struct {
@@ -875,7 +878,7 @@ func TestCache(t *testing.T) {
cureMany(t, c0, []cureStep{ cureMany(t, c0, []cureStep{
{"cache hit ident", overrideIdent{ {"cache hit ident", overrideIdent{
id: identifier, id: identifier,
}, wantPathname, testdata, nil}, }, wantPathname, testdata, pkg.WCache, nil},
{"cache miss checksum match", newStubFile( {"cache miss checksum match", newStubFile(
pkg.KindHTTPGet, pkg.KindHTTPGet,
@@ -886,7 +889,7 @@ func TestCache(t *testing.T) {
), base.Append( ), base.Append(
"identifier", "identifier",
pkg.Encode(testdata.hash()), pkg.Encode(testdata.hash()),
), testdata, nil}, ), testdata, pkg.WNew, nil},
}) })
// cure after close // cure after close
@@ -1016,30 +1019,30 @@ func TestCache(t *testing.T) {
{"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{ {"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: makeSample, cure: makeSample,
}}}, wantPathname, want, nil}, }}}, wantPathname, want, pkg.WNew, nil},
{"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{ {"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
}}}, wantPathname, want, nil}, }}}, wantPathname, want, pkg.WCache, nil},
{"identical checksum", overrideIdent{id0, &stubArtifact{ {"identical checksum", overrideIdent{id0, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: makeSample, cure: makeSample,
}}, wantPathname0, want, nil}, }}, wantPathname0, want, pkg.WNew, nil},
{"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{ {"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe)) return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe))
}, },
}}, nil, nil, stub.UniqueError(0xcafe)}, }}, nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
{"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{ {"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), nil) return makeGarbage(t.GetWorkDir(), nil)
}, },
}}}, nil, nil, &pkg.ChecksumMismatchError{ }}}, nil, nil, pkg.WNew, &pkg.ChecksumMismatchError{
Got: pkg.MustDecode( Got: pkg.MustDecode(
"CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT", "CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT",
), ),
@@ -1050,7 +1053,7 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 2}, pkg.ID{0xff, 2},
new(want.hash()), new(want.hash()),
testdata, nil, testdata, nil,
), nil, nil, pkg.InvalidFileModeError( ), nil, nil, pkg.WCache, pkg.InvalidFileModeError(
fs.ModeDir | 0500, fs.ModeDir | 0500,
)}, )},
@@ -1064,7 +1067,7 @@ func TestCache(t *testing.T) {
_, err = io.ReadAll(r) _, err = io.ReadAll(r)
return err return err
}, },
}}, nil, nil, &os.PathError{ }}, nil, nil, pkg.WNew, &os.PathError{
Op: "read", Op: "read",
Path: base.Append( Path: base.Append(
"checksum", "checksum",
@@ -1078,14 +1081,14 @@ func TestCache(t *testing.T) {
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return nil return nil
}, },
}}, nil, nil, pkg.NoOutputError{}}, }}, nil, nil, pkg.WNew, pkg.NoOutputError{}},
{"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{ {"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400) return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400)
}, },
}}, nil, nil, errors.New("non-file artifact produced regular file")}, }}, nil, nil, pkg.WNew, errors.New("non-file artifact produced regular file")},
{"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{ {"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
@@ -1095,7 +1098,7 @@ func TestCache(t *testing.T) {
t.GetWorkDir().String(), t.GetWorkDir().String(),
) )
}, },
}}, nil, nil, pkg.InvalidFileModeError( }}, nil, nil, pkg.WNew, pkg.InvalidFileModeError(
fs.ModeSymlink | 0777, fs.ModeSymlink | 0777,
)}, )},
@@ -1116,7 +1119,7 @@ func TestCache(t *testing.T) {
}, base.Append( }, base.Append(
"identifier", "identifier",
"xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-", "xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-",
), want, nil}, ), want, pkg.WNew, nil},
{"substitutable", &stubArtifactF{ {"substitutable", &stubArtifactF{
kind: pkg.KindExec, kind: pkg.KindExec,
@@ -1135,7 +1138,7 @@ func TestCache(t *testing.T) {
}, base.Append( }, base.Append(
"identifier", "identifier",
"k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f", "k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f",
), want, nil}, ), want, pkg.WSubstitute, nil},
}) })
if c0, err := unsafeOpen( if c0, err := unsafeOpen(
@@ -1164,7 +1167,7 @@ func TestCache(t *testing.T) {
}, base.Append( }, base.Append(
"identifier", "identifier",
"_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_", "_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_",
), want, nil}, ), want, pkg.WSubstitute, nil},
}) })
} }
@@ -1235,7 +1238,7 @@ func TestCache(t *testing.T) {
pkg.ID{0xff, 1}, pkg.ID{0xff, 1},
nil, nil,
nil, stub.UniqueError(0xbad), nil, stub.UniqueError(0xbad),
), nil, nil, stub.UniqueError(0xbad)}, ), nil, nil, pkg.WNew, stub.UniqueError(0xbad)},
{"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{ {"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
@@ -1246,7 +1249,7 @@ func TestCache(t *testing.T) {
0400, 0400,
) )
}, },
}}, nil, nil, errors.New( }}, nil, nil, pkg.WNew, errors.New(
"non-file artifact produced regular file", "non-file artifact produced regular file",
)}, )},
}) })
@@ -1363,14 +1366,14 @@ func TestCache(t *testing.T) {
}}}, base.Append( }}}, base.Append(
"identifier", "identifier",
pkg.Encode(pkg.ID{0xff, 0}), pkg.Encode(pkg.ID{0xff, 0}),
), want, nil}, ), want, pkg.WNew, nil},
{"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{ {"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad)) return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad))
}, },
}}}, nil, nil, stub.UniqueError(0xbad)}, }}}, nil, nil, pkg.WNew, stub.UniqueError(0xbad)},
{"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{ {"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
kind: pkg.KindTar, kind: pkg.KindTar,
@@ -1380,7 +1383,7 @@ func TestCache(t *testing.T) {
}}}, base.Append( }}}, base.Append(
"identifier", "identifier",
pkg.Encode(pkg.ID{0xff, 1}), pkg.Encode(pkg.ID{0xff, 1}),
), want, nil}, ), want, pkg.WNew, nil},
}) })
}, expectsFS{ }, expectsFS{
".": {Mode: fs.ModeDir | 0700}, ".": {Mode: fs.ModeDir | 0700},
@@ -1408,7 +1411,7 @@ func TestCache(t *testing.T) {
), base.Append( ), base.Append(
"identifier", "identifier",
pkg.Encode(pkg.Checksum{0xfe, 0}), pkg.Encode(pkg.Checksum{0xfe, 0}),
), expectsChecksum{0xff, 0}, nil}, ), expectsChecksum{0xff, 0}, pkg.WNew, nil},
}) })
for _, p := range [][]string{ for _, p := range [][]string{
@@ -1485,7 +1488,7 @@ func TestCache(t *testing.T) {
), expectsFS{ ), expectsFS{
".": {Mode: fs.ModeDir | 0500}, ".": {Mode: fs.ModeDir | 0500},
"result": {Mode: 0444}, "result": {Mode: 0444},
}, nil}, }, pkg.WNew, nil},
{"substituted", substituted, base.Append( {"substituted", substituted, base.Append(
"identifier", "identifier",
@@ -1493,7 +1496,7 @@ func TestCache(t *testing.T) {
), expectsFS{ ), expectsFS{
".": {Mode: fs.ModeDir | 0500}, ".": {Mode: fs.ModeDir | 0500},
"result": {Mode: 0444}, "result": {Mode: 0444},
}, nil}, }, pkg.WSubstitute, nil},
}) })
}, expectsFS{ }, expectsFS{
".": {Mode: fs.ModeDir | 0700}, ".": {Mode: fs.ModeDir | 0700},
@@ -1586,14 +1589,14 @@ func TestCache(t *testing.T) {
{"extern", a, base.Append( {"extern", a, base.Append(
"identifier", "identifier",
pkg.Encode(wantIdent.Value()), pkg.Encode(wantIdent.Value()),
), wantOutput, nil}, ), wantOutput, pkg.WExternal, nil},
{"substitute", _a, base.Append( {"substitute", _a, base.Append(
"identifier", "identifier",
pkg.Encode(_wantIdent.Value()), pkg.Encode(_wantIdent.Value()),
), _wantOutput, nil}, ), _wantOutput, pkg.WExternal, nil},
{"mismatch", kca, nil, nil, &pkg.ChecksumMismatchError{ {"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{
Got: wantChecksum, Got: wantChecksum,
}}, }},
}) })
@@ -1717,27 +1720,27 @@ func TestCache(t *testing.T) {
{"extern", a, base.Append( {"extern", a, base.Append(
"identifier", "identifier",
pkg.Encode(wantIdent.Value()), pkg.Encode(wantIdent.Value()),
), wantOutput, nil}, ), wantOutput, pkg.WExternal, nil},
{"flood shallow extern", fia, base.Append( {"flood shallow extern", fia, base.Append(
"identifier", "identifier",
pkg.Encode(fiaIdent.Value()), pkg.Encode(fiaIdent.Value()),
), wantOutput, nil}, ), wantOutput, pkg.WExternal, nil},
{"substitute", _a, base.Append( {"substitute", _a, base.Append(
"identifier", "identifier",
pkg.Encode(_wantIdent.Value()), pkg.Encode(_wantIdent.Value()),
), _wantOutput, nil}, ), _wantOutput, pkg.WExternal, nil},
{"flood shallow local", flia, base.Append( {"flood shallow local", flia, base.Append(
"identifier", "identifier",
pkg.Encode(fliaIdent.Value()), pkg.Encode(fliaIdent.Value()),
), wantOutput, nil}, ), wantOutput, pkg.WExternal, nil},
{"flood shallow hanging", fhia, nil, nil, {"flood shallow hanging", fhia, nil, nil,
pkg.HangingInputError(c.Ident(h))}, pkg.WNew, pkg.HangingInputError(c.Ident(h))},
{"mismatch", kca, nil, nil, &pkg.ChecksumMismatchError{ {"mismatch", kca, nil, nil, pkg.WExternal, &pkg.ChecksumMismatchError{
Got: wantChecksum, Got: wantChecksum,
}}, }},
}) })
@@ -1781,7 +1784,7 @@ func TestErrors(t *testing.T) {
}{ }{
{"InvalidLookupError", pkg.InvalidLookupError{ {"InvalidLookupError", pkg.InvalidLookupError{
0xff, 0xf0, 0xff, 0xf0,
}, "attempting to look up non-dependency artifact __AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}, }, "attempting to look up non-input artifact __AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"},
{"InvalidArtifactError", pkg.InvalidArtifactError{ {"InvalidArtifactError", pkg.InvalidArtifactError{
0xff, 0xfd, 0xff, 0xfd,
+5 -5
View File
@@ -212,24 +212,24 @@ func checkTarHTTP(
&client, &client,
"file:///testdata", "file:///testdata",
testdataChecksum, testdataChecksum,
), pkg.Gzip)), ignorePathname, want, nil}, ), pkg.Gzip)), ignorePathname, want, pkg.WNew, nil},
{"directory", pkg.NewTar(pkg.NewDecompress( {"directory", pkg.NewTar(pkg.NewDecompress(
&tarDir, &tarDir,
pkg.Gzip, pkg.Gzip,
)), ignorePathname, want, nil}, )), ignorePathname, want, pkg.WNew, nil},
{"multiple entries", pkg.NewTar(pkg.NewDecompress( {"multiple entries", pkg.NewTar(pkg.NewDecompress(
&tarDirMulti, &tarDirMulti,
pkg.Gzip, pkg.Gzip,
)), nil, nil, errors.New( )), nil, nil, pkg.WNew, errors.New(
"input directory does not contain a single regular file", "input directory does not contain a single regular file",
)}, )},
{"bad type", pkg.NewTar(pkg.NewDecompress( {"bad type", pkg.NewTar(pkg.NewDecompress(
&tarDirType, &tarDirType,
pkg.Gzip, pkg.Gzip,
)), nil, nil, errors.New( )), nil, nil, pkg.WNew, errors.New(
"input directory does not contain a single regular file", "input directory does not contain a single regular file",
)}, )},
@@ -239,6 +239,6 @@ func checkTarHTTP(
cure: func(t *pkg.TContext) error { cure: func(t *pkg.TContext) error {
return stub.UniqueError(0xcafe) return stub.UniqueError(0xcafe)
}, },
}), nil, nil, stub.UniqueError(0xcafe)}, }), nil, nil, pkg.WNew, stub.UniqueError(0xcafe)},
}) })
} }