internal/pkg: deduplicate unwrapped input errors
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m47s
Test / Hakurei (push) Successful in 4m27s
Test / Sandbox (race detector) (push) Successful in 5m50s
Test / Hakurei (race detector) (push) Successful in 6m58s
Test / ShareFS (push) Successful in 7m7s
Test / Flake checks (push) Successful in 1m8s
Test / Create distribution (push) Successful in 55s
Test / Sandbox (push) Successful in 2m47s
Test / Hakurei (push) Successful in 4m27s
Test / Sandbox (race detector) (push) Successful in 5m50s
Test / Hakurei (race detector) (push) Successful in 6m58s
Test / ShareFS (push) Successful in 7m7s
Test / Flake checks (push) Successful in 1m8s
This avoids repeating errors belonging to multiple instances of the same artifact in different locations in memory. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
+27
-8
@@ -15,6 +15,7 @@ import (
|
|||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"iter"
|
||||||
"maps"
|
"maps"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@@ -1723,8 +1724,9 @@ retry:
|
|||||||
// An InputError describes inputs of a [FloodArtifact] which had failed to cure.
|
// An InputError describes inputs of a [FloodArtifact] which had failed to cure.
|
||||||
type InputError map[Artifact]error
|
type InputError map[Artifact]error
|
||||||
|
|
||||||
// Error returns a user-facing, deterministic text representation of e.
|
// unwrap returns an iterator over sorted, deduplicated [Artifact] and their
|
||||||
func (e InputError) Error() string {
|
// corresponding identifier.
|
||||||
|
func (e InputError) unwrap() iter.Seq2[Artifact, unique.Handle[ID]] {
|
||||||
ir := NewIR()
|
ir := NewIR()
|
||||||
|
|
||||||
type input struct {
|
type input struct {
|
||||||
@@ -1741,20 +1743,37 @@ func (e InputError) Error() string {
|
|||||||
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
|
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
|
||||||
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
||||||
})
|
})
|
||||||
|
p = slices.CompactFunc(p, func(a, b input) bool { return a.id == b.id })
|
||||||
|
|
||||||
|
return func(yield func(Artifact, unique.Handle[ID]) bool) {
|
||||||
|
for _, i := range p {
|
||||||
|
if !yield(i.a, i.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns a user-facing, deterministic text representation of e.
|
||||||
|
func (e InputError) Error() string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
buf.WriteString("errors curing inputs:")
|
buf.WriteString("errors curing inputs:")
|
||||||
for _, i := range p {
|
for a, id := range e.unwrap() {
|
||||||
buf.WriteString("\n\t" +
|
buf.WriteString("\n\t")
|
||||||
reportName(i.a, i.id) + ": " +
|
buf.WriteString(reportName(a, id))
|
||||||
e[i.a].Error())
|
buf.WriteString(": ")
|
||||||
|
buf.WriteString(e[a].Error())
|
||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns a slice of underlying errors in unspecified order.
|
// Unwrap returns a slice of underlying errors sorted by identifier.
|
||||||
func (e InputError) Unwrap() []error {
|
func (e InputError) Unwrap() []error {
|
||||||
return slices.AppendSeq(make([]error, 0, len(e)), maps.Values(e))
|
errs := make([]error, 0, len(e))
|
||||||
|
for a := range e.unwrap() {
|
||||||
|
errs = append(errs, e[a])
|
||||||
|
}
|
||||||
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// enterCure must be called before entering an [Artifact] implementation.
|
// enterCure must be called before entering an [Artifact] implementation.
|
||||||
|
|||||||
+17
-14
@@ -11,7 +11,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"maps"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -1979,6 +1978,22 @@ func TestInputError(t *testing.T) {
|
|||||||
stub.UniqueError(0xbad09),
|
stub.UniqueError(0xbad09),
|
||||||
stub.UniqueError(0xbad0f),
|
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 {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -1988,19 +2003,7 @@ func TestInputError(t *testing.T) {
|
|||||||
t.Errorf("Error:\n%s\nwant\n%s", got, tc.want)
|
t.Errorf("Error:\n%s\nwant\n%s", got, tc.want)
|
||||||
}
|
}
|
||||||
|
|
||||||
unwrap, unwrapM := tc.err.Unwrap(), make(map[error]struct{})
|
if unwrap := tc.err.Unwrap(); !reflect.DeepEqual(unwrap, tc.unwrap) {
|
||||||
for _, a := range unwrap {
|
|
||||||
unwrapM[a] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
wantUnwrapM := make(map[error]struct{})
|
|
||||||
for _, a := range tc.unwrap {
|
|
||||||
wantUnwrapM[a] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(unwrap) != len(unwrapM) ||
|
|
||||||
len(tc.unwrap) != len(wantUnwrapM) ||
|
|
||||||
!maps.Equal(unwrapM, wantUnwrapM) {
|
|
||||||
t.Errorf("Unwrap: %#v, want %#v", unwrap, tc.unwrap)
|
t.Errorf("Unwrap: %#v, want %#v", unwrap, tc.unwrap)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user