diff --git a/internal/pkg/dir_test.go b/internal/pkg/dir_test.go index 6d94391..e91a953 100644 --- a/internal/pkg/dir_test.go +++ b/internal/pkg/dir_test.go @@ -61,14 +61,14 @@ func TestFlatten(t *testing.T) { {Mode: fs.ModeDir | 0700, Path: "work"}, }, pkg.MustDecode("St9rlE-mGZ5gXwiv_hzQ_B8bZP-UUvSNmf4nHUZzCMOumb6hKnheZSe0dmnuc4Q2")}, - {"sample load or store", fstest.MapFS{ + {"sample http get cure", fstest.MapFS{ ".": {Mode: fs.ModeDir | 0700}, "checksum": {Mode: fs.ModeDir | 0700}, "checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")}, + "identifier/NqVORkT6L9HX6Za7kT2zcibY10qFqBaxEjPiYFrBQX-ZFr3yxCzJxbKOP0zVjeWb": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")}, "work": {Mode: fs.ModeDir | 0700}, }, []pkg.FlatEntry{ @@ -78,10 +78,10 @@ func TestFlatten(t *testing.T) { {Mode: 0400, Path: "checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU", Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")}, {Mode: fs.ModeDir | 0700, Path: "identifier"}, - {Mode: fs.ModeSymlink | 0777, Path: "identifier/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU", Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")}, + {Mode: fs.ModeSymlink | 0777, Path: "identifier/NqVORkT6L9HX6Za7kT2zcibY10qFqBaxEjPiYFrBQX-ZFr3yxCzJxbKOP0zVjeWb", Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")}, {Mode: fs.ModeDir | 0700, Path: "work"}, - }, pkg.MustDecode("4WHaMvRRcCac1uAyXnEklEd2YaNQBj6rXlfMntX9GgYLij3By1znv5QYPGJHYQIH")}, + }, pkg.MustDecode("bqtn69RkV5E7V7GhhgCFjcvbxmaqrO8DywamM4Tyjf10F6EJBHjXiIa_tFRtF4iN")}, {"sample directory step simple", fstest.MapFS{ ".": {Mode: fs.ModeDir | 0700}, @@ -200,7 +200,7 @@ func TestFlatten(t *testing.T) { "checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o/work": {Mode: fs.ModeDir | 0500}, "identifier": {Mode: fs.ModeDir | 0700}, - "identifier/NXP3807i7T1WaRom4ycvaIL8BzBU0awC7eW2_baV9hVS_NpRQMsJApnh0CPNNO8y": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o")}, + "identifier/-P_1iw6yVq_letMHncqcExSE0bYcDhYI5OdY6b1wKASf-Corufvj__XTBUq2Qd2a": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o")}, "work": {Mode: fs.ModeDir | 0700}, }, []pkg.FlatEntry{ @@ -220,10 +220,10 @@ func TestFlatten(t *testing.T) { {Mode: fs.ModeDir | 0500, Path: "checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o/work"}, {Mode: fs.ModeDir | 0700, Path: "identifier"}, - {Mode: fs.ModeSymlink | 0777, Path: "identifier/NXP3807i7T1WaRom4ycvaIL8BzBU0awC7eW2_baV9hVS_NpRQMsJApnh0CPNNO8y", Data: []byte("../checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o")}, + {Mode: fs.ModeSymlink | 0777, Path: "identifier/-P_1iw6yVq_letMHncqcExSE0bYcDhYI5OdY6b1wKASf-Corufvj__XTBUq2Qd2a", Data: []byte("../checksum/yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o")}, {Mode: fs.ModeDir | 0700, Path: "work"}, - }, pkg.MustDecode("p1HdTOQhIeWzpXdZ45xo00H9CFeXNIvazxOhBAfExlhFO64zt7TUbxoLJ2eAL5oc")}, + }, pkg.MustDecode("lmVlYEGNFkwGVpzzS8KYjGBVB6FCyPtk9ViX88zen0GgTKLgGqO6eFxb4dpcP6bR")}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/internal/pkg/net.go b/internal/pkg/net.go index fb90221..74eeca5 100644 --- a/internal/pkg/net.go +++ b/internal/pkg/net.go @@ -11,10 +11,14 @@ import ( "hakurei.app/container/check" ) -// An httpArtifact is an [Artifact] backed by an [http] request. +// An httpArtifact is an [Artifact] backed by a [http] url string. The method is +// hardcoded as [http.MethodGet]. Request body is not allowed because it cannot +// be deterministically represented by Params. type httpArtifact struct { - // Caller-supplied request. - req *http.Request + // Caller-supplied context. + ctx context.Context + // Caller-supplied url string. + url string // Caller-supplied checksum of the response body. This is validated during // curing and the first call to Data. @@ -30,15 +34,6 @@ type httpArtifact struct { mu sync.Mutex } -// NewHTTP returns a new [File] backed by the supplied client and request. If -// c is nil, [http.DefaultClient] is used instead. -func NewHTTP(c *http.Client, req *http.Request, checksum Checksum) File { - if c == nil { - c = http.DefaultClient - } - return &httpArtifact{req: req, checksum: checksum, doFunc: c.Do} -} - // NewHTTPGet returns a new [File] backed by the supplied client. A GET request // is set up for url. If c is nil, [http.DefaultClient] is used instead. func NewHTTPGet( @@ -46,24 +41,22 @@ func NewHTTPGet( c *http.Client, url string, checksum Checksum, -) (File, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err +) File { + if ctx == nil { + ctx = context.Background() } - return NewHTTP(c, req, checksum), nil + if c == nil { + c = http.DefaultClient + } + return &httpArtifact{ctx: ctx, url: url, checksum: checksum, doFunc: c.Do} } // Kind returns the hardcoded [Kind] constant. -func (a *httpArtifact) Kind() Kind { return KindHTTP } +func (a *httpArtifact) Kind() Kind { return KindHTTPGet } -// ID returns the caller-supplied hash of the response body. -func (a *httpArtifact) ID() ID { return a.checksum } - -// Params is unreachable. -func (a *httpArtifact) Params() []byte { - panic("not implemented") -} +// Params returns the backing url string. Context is not represented as it does +// not affect [Cache.Cure] outcome. +func (a *httpArtifact) Params() []byte { return []byte(a.url) } // Dependencies returns a nil slice. func (a *httpArtifact) Dependencies() []Artifact { return nil } @@ -82,8 +75,14 @@ func (e ResponseStatusError) Error() string { // do sends the caller-supplied request on the caller-supplied [http.Client] // and reads its response body to EOF and returns the resulting bytes. func (a *httpArtifact) do() (data []byte, err error) { + var req *http.Request + req, err = http.NewRequestWithContext(a.ctx, http.MethodGet, a.url, nil) + if err != nil { + return + } + var resp *http.Response - if resp, err = a.doFunc(a.req); err != nil { + if resp, err = a.doFunc(req); err != nil { return } diff --git a/internal/pkg/net_test.go b/internal/pkg/net_test.go index 2e2e2ce..da1a75d 100644 --- a/internal/pkg/net_test.go +++ b/internal/pkg/net_test.go @@ -2,7 +2,6 @@ package pkg_test import ( "crypto/sha512" - "encoding/base64" "net/http" "reflect" "testing" @@ -12,7 +11,7 @@ import ( "hakurei.app/internal/pkg" ) -func TestHTTP(t *testing.T) { +func TestHTTPGet(t *testing.T) { t.Parallel() const testdata = "\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69" @@ -23,8 +22,6 @@ func TestHTTP(t *testing.T) { return (pkg.Checksum)(h.Sum(nil)) }() - testdataChecksumString := base64.URLEncoding.EncodeToString(testdataChecksum[:]) - var transport http.Transport client := http.Client{Transport: &transport} transport.RegisterProtocol("file", http.NewFileTransportFS(fstest.MapFS{ @@ -33,75 +30,66 @@ func TestHTTP(t *testing.T) { checkWithCache(t, []cacheTestCase{ {"direct", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - var got []byte - if f, err := pkg.NewHTTPGet( + f := pkg.NewHTTPGet( t.Context(), &client, "file:///testdata", testdataChecksum, - ); err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } else if got, err = f.Data(); err != nil { + ) + wantIdent := pkg.KindHTTPGet.Ident([]byte("file:///testdata")) + if got, err := f.Data(); err != nil { t.Fatalf("Data: error = %v", err) } else if string(got) != testdata { t.Fatalf("Data: %x, want %x", got, testdata) - } else if gotIdent := pkg.Ident(f); gotIdent != testdataChecksum { - t.Fatalf("Ident: %x, want %x", gotIdent, testdataChecksum) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdent)) } // check direct validation - wantErrMismatch := &pkg.ChecksumMismatchError{ - Got: testdataChecksum, - } - if f, err := pkg.NewHTTPGet( + f = pkg.NewHTTPGet( t.Context(), &client, "file:///testdata", pkg.Checksum{}, - ); err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } else if _, err = f.Data(); !reflect.DeepEqual(err, wantErrMismatch) { + ) + wantErrMismatch := &pkg.ChecksumMismatchError{ + Got: testdataChecksum, + } + if _, err := f.Data(); !reflect.DeepEqual(err, wantErrMismatch) { t.Fatalf("Data: error = %#v, want %#v", err, wantErrMismatch) - } else if gotIdent := pkg.Ident(f); gotIdent != (pkg.Checksum{}) { - t.Fatalf("Ident: %x, want %x", gotIdent, pkg.Checksum{}) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdent)) } // check direct response error - wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound) - if f, err := pkg.NewHTTPGet( + f = pkg.NewHTTPGet( t.Context(), &client, "file:///nonexistent", pkg.Checksum{}, - ); err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } else if _, err = f.Data(); !reflect.DeepEqual(err, wantErrNotFound) { + ) + wantIdentNonexistent := pkg.KindHTTPGet.Ident([]byte("file:///nonexistent")) + wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound) + if _, err := f.Data(); !reflect.DeepEqual(err, wantErrNotFound) { t.Fatalf("Data: error = %#v, want %#v", err, wantErrNotFound) - } else if gotIdent := pkg.Ident(f); gotIdent != (pkg.Checksum{}) { - t.Fatalf("Ident: %x, want %x", gotIdent, pkg.Checksum{}) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdentNonexistent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdentNonexistent)) } }, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")}, {"cure", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { - f, err := pkg.NewHTTPGet( + f := pkg.NewHTTPGet( t.Context(), &client, "file:///testdata", testdataChecksum, ) - if err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } - + wantIdent := pkg.KindHTTPGet.Ident([]byte("file:///testdata")) wantPathname := base.Append( "identifier", - testdataChecksumString, + pkg.Encode(wantIdent), ) - var ( - pathname *check.Absolute - checksum pkg.Checksum - ) - if pathname, checksum, err = c.Cure(f); err != nil { + if pathname, checksum, err := c.Cure(f); err != nil { t.Fatalf("Cure: error = %v", err) } else if !pathname.Is(wantPathname) { t.Fatalf("Cure: %q, want %q", pathname, wantPathname) @@ -109,45 +97,43 @@ func TestHTTP(t *testing.T) { t.Fatalf("Cure: %x, want %x", checksum, testdataChecksum) } - var got []byte - if got, err = f.Data(); err != nil { + if got, err := f.Data(); err != nil { t.Fatalf("Data: error = %v", err) } else if string(got) != testdata { t.Fatalf("Data: %x, want %x", got, testdata) - } else if gotIdent := pkg.Ident(f); gotIdent != testdataChecksum { - t.Fatalf("Ident: %x, want %x", gotIdent, testdataChecksum) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdent)) } // check load from cache - if f, err = pkg.NewHTTPGet( + f = pkg.NewHTTPGet( t.Context(), &client, "file:///testdata", testdataChecksum, - ); err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } else if got, err = f.Data(); err != nil { + ) + if got, err := f.Data(); err != nil { t.Fatalf("Data: error = %v", err) } else if string(got) != testdata { t.Fatalf("Data: %x, want %x", got, testdata) - } else if gotIdent := pkg.Ident(f); gotIdent != testdataChecksum { - t.Fatalf("Ident: %x, want %x", gotIdent, testdataChecksum) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdent)) } // check error passthrough - wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound) - if f, err = pkg.NewHTTPGet( + f = pkg.NewHTTPGet( t.Context(), &client, "file:///nonexistent", pkg.Checksum{}, - ); err != nil { - t.Fatalf("NewHTTPGet: error = %v", err) - } else if _, _, err = c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) { + ) + wantIdentNonexistent := pkg.KindHTTPGet.Ident([]byte("file:///nonexistent")) + wantErrNotFound := pkg.ResponseStatusError(http.StatusNotFound) + if _, _, err := c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) { t.Fatalf("Pathname: error = %#v, want %#v", err, wantErrNotFound) - } else if gotIdent := pkg.Ident(f); gotIdent != (pkg.Checksum{}) { - t.Fatalf("Ident: %x, want %x", gotIdent, pkg.Checksum{}) + } else if gotIdent := pkg.Ident(f); gotIdent != wantIdentNonexistent { + t.Fatalf("Ident: %s, want %s", pkg.Encode(gotIdent), pkg.Encode(wantIdentNonexistent)) } - }, pkg.MustDecode("4WHaMvRRcCac1uAyXnEklEd2YaNQBj6rXlfMntX9GgYLij3By1znv5QYPGJHYQIH")}, + }, pkg.MustDecode("bqtn69RkV5E7V7GhhgCFjcvbxmaqrO8DywamM4Tyjf10F6EJBHjXiIa_tFRtF4iN")}, }) } diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 4ab3125..b50dc48 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -141,8 +141,8 @@ func Ident(a Artifact) ID { type Kind uint64 const ( - // KindHTTP is the kind of [Artifact] returned by [NewHTTP]. - KindHTTP Kind = iota + // KindHTTPGet is the kind of [Artifact] returned by [NewHTTPGet]. + KindHTTPGet Kind = iota // KindTar is the kind of artifact returned by [NewTar]. KindTar ) diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go index 1479e2e..edd5f07 100644 --- a/internal/pkg/pkg_test.go +++ b/internal/pkg/pkg_test.go @@ -279,28 +279,28 @@ func TestCache(t *testing.T) { cureMany(t, c, []cureStep{ {"initial file", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, identifier, &testdataChecksum, []byte(testdata), nil, ), wantPathname, testdataChecksum, nil}, {"identical content", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, identifier0, &testdataChecksum, []byte(testdata), nil, ), wantPathname0, testdataChecksum, nil}, {"existing entry", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, identifier, &testdataChecksum, []byte(testdata), nil, ), wantPathname, testdataChecksum, nil}, {"checksum mismatch", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.ID{0xff, 0}, new(pkg.Checksum), []byte(testdata), nil, @@ -309,7 +309,7 @@ func TestCache(t *testing.T) { }}, {"store without validation", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.MustDecode("vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX"), nil, []byte{0}, nil, @@ -328,14 +328,14 @@ func TestCache(t *testing.T) { }, nil}, {"error passthrough", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.ID{0xff, 1}, nil, nil, stub.UniqueError(0xcafe), ), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)}, {"error caching", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.ID{0xff, 1}, nil, nil, nil, @@ -357,7 +357,7 @@ func TestCache(t *testing.T) { }, wantPathname, testdataChecksum, nil}, {"cache miss checksum match", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, testdataChecksum, nil, []byte(testdata), @@ -493,7 +493,7 @@ func TestCache(t *testing.T) { }}, {"cache hit bad type", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.ID{0xff, 2}, &wantChecksum, []byte(testdata), nil, @@ -571,7 +571,7 @@ func TestCache(t *testing.T) { // check cache activity while a cure is blocking cureMany(t, c, []cureStep{ {"error passthrough", newStubFile( - pkg.KindHTTP, + pkg.KindHTTPGet, pkg.ID{0xff, 1}, nil, nil, stub.UniqueError(0xbad), diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go index 2b9aacd..24411c5 100644 --- a/internal/pkg/tar.go +++ b/internal/pkg/tar.go @@ -43,12 +43,8 @@ func NewHTTPGetTar( url string, checksum Checksum, compression uint64, -) (Artifact, error) { - f, err := NewHTTPGet(ctx, hc, url, checksum) - if err != nil { - return nil, err - } - return NewTar(f, compression), nil +) Artifact { + return NewTar(NewHTTPGet(ctx, hc, url, checksum), compression) } // Kind returns the hardcoded [Kind] constant. diff --git a/internal/pkg/tar_test.go b/internal/pkg/tar_test.go index 309a1c7..feff9c1 100644 --- a/internal/pkg/tar_test.go +++ b/internal/pkg/tar_test.go @@ -74,12 +74,13 @@ func TestTar(t *testing.T) { h := sha512.New384() h.Write([]byte{byte(pkg.KindTar), 0, 0, 0, 0, 0, 0, 0}) h.Write([]byte{pkg.TarGzip, 0, 0, 0, 0, 0, 0, 0}) - h.Write([]byte{byte(pkg.KindHTTP), 0, 0, 0, 0, 0, 0, 0}) - h.Write(testdataChecksum[:]) + h.Write([]byte{byte(pkg.KindHTTPGet), 0, 0, 0, 0, 0, 0, 0}) + httpIdent := pkg.KindHTTPGet.Ident([]byte("file:///testdata")) + h.Write(httpIdent[:]) return pkg.ID(h.Sum(nil)) }() - a, err := pkg.NewHTTPGetTar( + a := pkg.NewHTTPGetTar( t.Context(), &client, "file:///testdata", @@ -87,16 +88,10 @@ func TestTar(t *testing.T) { pkg.TarGzip, ) - if err != nil { - t.Fatalf("NewHTTPGetTar: error = %v", err) - } else if id := pkg.Ident(a); id != wantIdent { + if id := pkg.Ident(a); id != wantIdent { t.Fatalf("Ident: %s, want %s", pkg.Encode(id), pkg.Encode(wantIdent)) } - var ( - pathname *check.Absolute - checksum pkg.Checksum - ) wantPathname := base.Append( "identifier", pkg.Encode(wantIdent), @@ -104,7 +99,7 @@ func TestTar(t *testing.T) { wantChecksum := pkg.MustDecode( "yJlSb2A3jxaMLuKqwp1GwHOguAHddS9MjygF9ICEeegKfRvgLPdPmNh8mva47f8o", ) - if pathname, checksum, err = c.Cure(a); err != nil { + if pathname, checksum, err := c.Cure(a); err != nil { t.Fatalf("Cure: error = %v", err) } else if !pathname.Is(wantPathname) { t.Fatalf("Cure: %q, want %q", pathname, wantPathname) @@ -114,6 +109,6 @@ func TestTar(t *testing.T) { Want: wantChecksum, }) } - }, pkg.MustDecode("p1HdTOQhIeWzpXdZ45xo00H9CFeXNIvazxOhBAfExlhFO64zt7TUbxoLJ2eAL5oc")}, + }, pkg.MustDecode("lmVlYEGNFkwGVpzzS8KYjGBVB6FCyPtk9ViX88zen0GgTKLgGqO6eFxb4dpcP6bR")}, }) }