diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-01-02 00:59:37 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-01-02 12:57:19 +0900 |
| commit | e9de5d3aca533ec27839661b2d311b4fcb7a13fb (patch) | |
| tree | 31bf9378cef638cbb8dd0d1dfc74c5bc10214300 /internal/pkg/pkg_test.go | |
| parent | 993afde840834dbaf4fd46d057e605a806b4a31c (diff) | |
internal/pkg: implement caching for files
This change contains primitives for validating and caching single-file artifacts.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/pkg_test.go')
| -rw-r--r-- | internal/pkg/pkg_test.go | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go new file mode 100644 index 00000000..c73049e5 --- /dev/null +++ b/internal/pkg/pkg_test.go @@ -0,0 +1,327 @@ +package pkg_test + +import ( + "bytes" + "crypto/sha512" + "encoding/base64" + "io/fs" + "os" + "path/filepath" + "reflect" + "syscall" + "testing" + + "hakurei.app/container" + "hakurei.app/container/check" + "hakurei.app/container/stub" + "hakurei.app/internal/pkg" +) + +func TestCache(t *testing.T) { + t.Parallel() + + const testdata = "" + + "\x00\x00\x00\x00" + + "\xad\x0b\x00" + + "\x04" + + "\xfe\xfe\x00\x00" + + "\xfe\xca\x00\x00" + + testdataChecksum := func() pkg.Checksum { + h := sha512.New384() + h.Write([]byte(testdata)) + return (pkg.Checksum)(h.Sum(nil)) + }() + + testdataChecksumString := base64.URLEncoding.EncodeToString(testdataChecksum[:]) + + testCases := []struct { + name string + early func(t *testing.T, base *check.Absolute) + f func(t *testing.T, base *check.Absolute, c *pkg.Cache) + check func(t *testing.T, base *check.Absolute) + }{ + {"file", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { + wantErrNonexistent := &os.PathError{ + Op: "open", + Path: base.Append( + "identifier", + testdataChecksumString, + ).String(), + Err: syscall.ENOENT, + } + if _, _, err := c.LoadFile(testdataChecksum); !reflect.DeepEqual(err, wantErrNonexistent) { + t.Fatalf("LoadFile: error = %#v, want %#v", err, wantErrNonexistent) + } + + 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", + ) + + // initial store + if pathname, err := c.StoreFile( + identifier, + []byte(testdata), + &testdataChecksum, + true, + ); err != nil { + t.Fatalf("StoreFile: error = %v", err) + } else if !pathname.Is(wantPathname) { + t.Fatalf("StoreFile: pathname = %q, want %q", pathname, wantPathname) + } + + // load or store, identical content + if pathname, data, store, err := c.LoadOrStoreFile(identifier0, func() ([]byte, error) { + return []byte(testdata), nil + }, &testdataChecksum, true); err != nil { + t.Fatalf("LoadOrStoreFile: error = %v", err) + } else if !pathname.Is(wantPathname0) { + t.Fatalf("LoadOrStoreFile: pathname = %q, want %q", pathname, wantPathname0) + } else if string(data) != testdata { + t.Fatalf("LoadOrStoreFile: data = %x, want %x", data, testdata) + } else if !store { + t.Fatal("LoadOrStoreFile did not store nonpresent entry") + } + + // load or store, existing entry + if pathname, data, store, err := c.LoadOrStoreFile(identifier, func() ([]byte, error) { + return []byte(testdata), nil + }, &testdataChecksum, true); err != nil { + t.Fatalf("LoadOrStoreFile: error = %v", err) + } else if !pathname.Is(wantPathname) { + t.Fatalf("LoadOrStoreFile: pathname = %q, want %q", pathname, wantPathname) + } else if string(data) != testdata { + t.Fatalf("LoadOrStoreFile: data = %x, want %x", data, testdata) + } else if store { + t.Fatal("LoadOrStoreFile stored over present entry") + } + + // load, existing entry + if pathname, data, err := c.LoadFile(identifier0); err != nil { + t.Fatalf("LoadFile: error = %v", err) + } else if !pathname.Is(wantPathname0) { + t.Fatalf("LoadFile: pathname = %q, want %q", pathname, wantPathname0) + } else if string(data) != testdata { + t.Fatalf("LoadFile: data = %x, want %x", data, testdata) + } + + // checksum mismatch + wantErrChecksum := &pkg.ChecksumMismatchError{ + Got: testdataChecksum, + } + if _, err := c.StoreFile( + testdataChecksum, + []byte(testdata), + new(pkg.Checksum), + true, + ); !reflect.DeepEqual(err, wantErrChecksum) { + t.Fatalf("StoreFile: error = %#v, want %#v", err, wantErrChecksum) + } + + // verify failed store + if _, _, err := c.LoadFile(testdataChecksum); !reflect.DeepEqual(err, wantErrNonexistent) { + t.Fatalf("LoadFile: error = %#v, want %#v", err, wantErrNonexistent) + } + + // store, same identifier + wantPathnameF := base.Append( + "identifier", + testdataChecksumString, + ) + if pathname, err := c.StoreFile( + testdataChecksum, + []byte(testdata), + &testdataChecksum, + true, + ); err != nil { + t.Fatalf("StoreFile: error = %v", err) + } else if !pathname.Is(wantPathnameF) { + t.Fatalf("StoreFile: pathname = %q, want %q", pathname, wantPathnameF) + } + + // load, same identifier + if pathname, data, err := c.LoadFile(testdataChecksum); err != nil { + t.Fatalf("LoadFile: error = %v", err) + } else if !pathname.Is(wantPathnameF) { + t.Fatalf("LoadFile: pathname = %q, want %q", pathname, wantPathnameF) + } else if string(data) != testdata { + t.Fatalf("LoadFile: data = %x, want %x", data, testdata) + } + + // store without validation + wantChecksum := pkg.Checksum{ + 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, + } + var gotChecksum pkg.Checksum + wantPathnameG := base.Append( + "identifier", + base64.URLEncoding.EncodeToString(wantChecksum[:]), + ) + if pathname, err := c.StoreFile( + wantChecksum, + []byte{0}, + &gotChecksum, + false, + ); err != nil { + t.Fatalf("StoreFile: error = %#v", err) + } else if !pathname.Is(wantPathnameG) { + t.Fatalf("StoreFile: pathname = %q, want %q", pathname, wantPathnameG) + } else if gotChecksum != wantChecksum { + t.Fatalf("StoreFile: buf = %x, want %x", gotChecksum, wantChecksum) + } + + // makeData passthrough + var zeroIdent pkg.ID + wantErrPassthrough := stub.UniqueError(0xcafe) + if _, _, _, err := c.LoadOrStoreFile(zeroIdent, func() ([]byte, error) { + return nil, wantErrPassthrough + }, new(pkg.Checksum), true); !reflect.DeepEqual(err, wantErrPassthrough) { + t.Fatalf("LoadOrStoreFile: error = %#v, want %#v", err, wantErrPassthrough) + } + + // verify failed store + wantErrNonexistentZero := &os.PathError{ + Op: "open", + Path: base.Append( + "identifier", + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + ).String(), + Err: syscall.ENOENT, + } + if _, _, err := c.LoadFile(zeroIdent); !reflect.DeepEqual(err, wantErrNonexistentZero) { + t.Fatalf("LoadFile: error = %#v, want %#v", err, wantErrNonexistentZero) + } + }, func(t *testing.T, base *check.Absolute) { + wantChecksum := pkg.MustDecode( + "lvK4lY9bQUFscHpxqHmiPvptjUwOgn3BFhzCXZMeupkY1n22WUPSuh7pswEvVZrx", + ) + if checksum, err := pkg.HashDir(base); err != nil { + t.Fatalf("HashDir: error = %v", err) + } else if checksum != wantChecksum { + t.Fatalf("HashDir: %v", &pkg.ChecksumMismatchError{ + Got: checksum, + Want: wantChecksum, + }) + } + }}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + base := check.MustAbs(t.TempDir()) + if err := os.Chmod(base.String(), 0700); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + if err := filepath.WalkDir(base.String(), func(path string, d fs.DirEntry, err error) error { + if err != nil { + t.Error(err) + return nil + } + if !d.IsDir() { + return nil + } + return os.Chmod(path, 0700) + }); err != nil { + t.Fatal(err) + } + }) + + if c, err := pkg.New(base); err != nil { + t.Fatalf("New: error = %v", err) + } else { + if tc.early != nil { + tc.early(t, base) + } + tc.f(t, base, c) + tc.check(t, base) + } + }) + } +} + +func TestErrors(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + err error + want string + }{ + {"ChecksumMismatchError", &pkg.ChecksumMismatchError{ + Want: (pkg.Checksum)(bytes.Repeat([]byte{ + 0x75, 0xe6, 0x9d, 0x6d, 0xe7, 0x9f, + }, 8)), + }, "got AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + " instead of deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"}, + } + 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 TestNew(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.New(check.MustAbs(container.Nonexistent)); !reflect.DeepEqual(err, wantErr) { + t.Errorf("New: 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.New(tempDir.Append("cache")); !reflect.DeepEqual(err, wantErr) { + t.Errorf("New: error = %#v, want %#v", err, wantErr) + } + }) +} |
