internal/pkg: improve error resolution
All checks were successful
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m35s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m54s
Test / Hpkg (push) Successful in 4m31s
Test / Sandbox (race detector) (push) Successful in 5m1s
Test / Hakurei (race detector) (push) Successful in 5m57s
Test / Flake checks (push) Successful in 1m33s
All checks were successful
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m35s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m54s
Test / Hpkg (push) Successful in 4m31s
Test / Sandbox (race detector) (push) Successful in 5m1s
Test / Hakurei (race detector) (push) Successful in 5m57s
Test / Flake checks (push) Successful in 1m33s
This was taking way too long for early failures. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -1188,39 +1188,38 @@ func (e *CureError) Error() string { return e.Err.Error() }
|
|||||||
// A DependencyCureError wraps errors returned while curing dependencies.
|
// A DependencyCureError wraps errors returned while curing dependencies.
|
||||||
type DependencyCureError []*CureError
|
type DependencyCureError []*CureError
|
||||||
|
|
||||||
// sort sorts underlying errors by their identifier.
|
// unwrapM recursively expands underlying errors into a caller-supplied map.
|
||||||
func (e *DependencyCureError) sort() {
|
func (e *DependencyCureError) unwrapM(me map[unique.Handle[ID]]*CureError) {
|
||||||
var identBuf [2]ID
|
for _, err := range *e {
|
||||||
slices.SortFunc(*e, func(a, b *CureError) int {
|
if _e, ok := err.Err.(*DependencyCureError); ok {
|
||||||
identBuf[0], identBuf[1] = a.Ident.Value(), b.Ident.Value()
|
_e.unwrapM(me)
|
||||||
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
continue
|
||||||
})
|
}
|
||||||
|
me[err.Ident] = err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unwrap recursively expands and deduplicates underlying errors.
|
// unwrap recursively expands and deduplicates underlying errors.
|
||||||
func (e *DependencyCureError) unwrap() DependencyCureError {
|
func (e *DependencyCureError) unwrap() DependencyCureError {
|
||||||
errs := make(DependencyCureError, 0, len(*e))
|
me := make(map[unique.Handle[ID]]*CureError)
|
||||||
for _, err := range *e {
|
e.unwrapM(me)
|
||||||
if _e, ok := err.Err.(*DependencyCureError); ok {
|
errs := slices.AppendSeq(
|
||||||
errs = append(errs, _e.unwrap()...)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
me := make(map[unique.Handle[ID]]*CureError, len(errs))
|
|
||||||
for _, err := range errs {
|
|
||||||
me[err.Ident] = err
|
|
||||||
}
|
|
||||||
return slices.AppendSeq(
|
|
||||||
make(DependencyCureError, 0, len(me)),
|
make(DependencyCureError, 0, len(me)),
|
||||||
maps.Values(me),
|
maps.Values(me),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var identBuf [2]ID
|
||||||
|
slices.SortFunc(errs, func(a, b *CureError) int {
|
||||||
|
identBuf[0], identBuf[1] = a.Ident.Value(), b.Ident.Value()
|
||||||
|
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
||||||
|
})
|
||||||
|
|
||||||
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns a deduplicated slice of underlying errors.
|
// Unwrap returns a deduplicated slice of underlying errors.
|
||||||
func (e *DependencyCureError) Unwrap() []error {
|
func (e *DependencyCureError) Unwrap() []error {
|
||||||
errs := e.unwrap()
|
errs := e.unwrap()
|
||||||
errs.sort()
|
|
||||||
_errs := make([]error, len(errs))
|
_errs := make([]error, len(errs))
|
||||||
for i, err := range errs {
|
for i, err := range errs {
|
||||||
_errs[i] = err
|
_errs[i] = err
|
||||||
@@ -1231,7 +1230,6 @@ func (e *DependencyCureError) Unwrap() []error {
|
|||||||
// Error returns a user-facing multiline error message.
|
// Error returns a user-facing multiline error message.
|
||||||
func (e *DependencyCureError) Error() string {
|
func (e *DependencyCureError) Error() string {
|
||||||
errs := e.unwrap()
|
errs := e.unwrap()
|
||||||
errs.sort()
|
|
||||||
if len(errs) == 0 {
|
if len(errs) == 0 {
|
||||||
return "invalid dependency cure outcome"
|
return "invalid dependency cure outcome"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"unique"
|
"unique"
|
||||||
@@ -1137,6 +1138,40 @@ func TestDependencyCureError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) Dependencies() []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 TestDependencyCureErrorEarly(t *testing.T) {
|
||||||
|
checkWithCache(t, []cacheTestCase{
|
||||||
|
{"early", 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)
|
||||||
|
}
|
||||||
|
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user