From 3078c41ce74d7c04a7db3e47cdc00a5d49496887 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 2 Jan 2026 15:39:42 +0900 Subject: internal/pkg: encode entry in custom format The fact that Gob serialisation is deterministic is an implementation detail. This change replaces Gob with a simple custom format. Signed-off-by: Ophestra --- internal/pkg/dir_test.go | 77 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 18 deletions(-) (limited to 'internal/pkg/dir_test.go') diff --git a/internal/pkg/dir_test.go b/internal/pkg/dir_test.go index 2e3b9079..7bc877d1 100644 --- a/internal/pkg/dir_test.go +++ b/internal/pkg/dir_test.go @@ -1,7 +1,9 @@ package pkg_test import ( + "bytes" "io/fs" + "reflect" "testing" "testing/fstest" @@ -12,36 +14,75 @@ func TestFlatten(t *testing.T) { t.Parallel() testCases := []struct { - name string - fsys fs.FS - want pkg.Checksum + name string + fsys fs.FS + entries []pkg.FlatEntry + sum pkg.Checksum }{ {"sample cache file", fstest.MapFS{ ".": {Mode: 020000000700}, "checksum": {Mode: 020000000700}, - "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0x0}}, - "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0x0, 0x0, 0x0, 0x0, 0xad, 0xb, 0x0, 0x4, 0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xca, 0x0, 0x0}}, + "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}}, + "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, "identifier": {Mode: 020000000700}, - "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0x0}}, - "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0x0, 0x0, 0x0, 0x0, 0xad, 0xb, 0x0, 0x4, 0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xca, 0x0, 0x0}}, - "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: 0400, Data: []byte{0x0, 0x0, 0x0, 0x0, 0xad, 0xb, 0x0, 0x4, 0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xca, 0x0, 0x0}}, - "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: 0400, Data: []byte{0x0, 0x0, 0x0, 0x0, 0xad, 0xb, 0x0, 0x4, 0xfe, 0xfe, 0x0, 0x0, 0xfe, 0xca, 0x0, 0x0}}, - }, pkg.MustDecode("lvK4lY9bQUFscHpxqHmiPvptjUwOgn3BFhzCXZMeupkY1n22WUPSuh7pswEvVZrx")}, + "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}}, + "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + }, []pkg.FlatEntry{ + {Mode: 020000000700, Path: "."}, + + {Mode: 020000000700, Path: "checksum"}, + {Mode: 0400, Path: "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + {Mode: 0400, Path: "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}}, + + {Mode: 020000000700, Path: "identifier"}, + {Mode: 0400, Path: "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + {Mode: 0400, Path: "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + {Mode: 0400, Path: "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}}, + {Mode: 0400, Path: "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}}, + }, pkg.MustDecode("ZNSQH-mjhtIbFvi51lQ0UjatjoS8_5ILrBPNWlO2LWTq9P6MJEnekYzP0esUJnVr")}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { t.Parallel() - if got, err := pkg.HashFS(tc.fsys, "."); err != nil { - t.Fatalf("HashFS: error = %v", err) - } else if got != tc.want { - t.Fatalf("HashFS: %v", &pkg.ChecksumMismatchError{ - Got: got, - Want: tc.want, - }) - } + t.Run("roundtrip", func(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + if _, err := pkg.Flatten(tc.fsys, ".", &buf); err != nil { + t.Fatalf("Flatten: error = %v", err) + } + + s := pkg.NewDirScanner(bytes.NewReader(buf.Bytes())) + var got []pkg.FlatEntry + for s.Scan() { + got = append(got, *s.Entry()) + } + if err := s.Err(); err != nil { + t.Fatalf("Err: error = %v", err) + } + + if !reflect.DeepEqual(got, tc.entries) { + t.Fatalf("Scan: %#v, want %#v", got, tc.entries) + } + }) + + t.Run("hash", func(t *testing.T) { + t.Parallel() + + if got, err := pkg.HashFS(tc.fsys, "."); err != nil { + t.Fatalf("HashFS: error = %v", err) + } else if got != tc.sum { + t.Fatalf("HashFS: %v", &pkg.ChecksumMismatchError{ + Got: got, + Want: tc.sum, + }) + } + }) }) } } -- cgit v1.3.1