diff --git a/checksum.go b/checksum.go index 67e8d86..a676ae2 100644 --- a/checksum.go +++ b/checksum.go @@ -137,7 +137,7 @@ func ChecksumReader(r io.Reader, pageSize int) (Checksum, error) { chksum = ChecksumFlag | (chksum ^ ChecksumPage(pgno, data)) } } - return chksum, nil + return ChecksumFlag | chksum, nil } // ParseChecksum parses a 16-character hex string into a checksum. diff --git a/cmd/ltx/apply_test.go b/cmd/ltx/apply_test.go index 1b8c065..0081714 100644 --- a/cmd/ltx/apply_test.go +++ b/cmd/ltx/apply_test.go @@ -111,6 +111,38 @@ func TestApplyCommand_SnapshotOverExistingDatabase(t *testing.T) { } } +func TestApplyCommand_ChecksumDeletion(t *testing.T) { + const pageSize = 512 + + dir := t.TempDir() + dbPath := filepath.Join(dir, "db") + ltxPath := filepath.Join(dir, "deletion.ltx") + initial := bytes.Repeat([]byte{0xbc}, pageSize) + if err := os.WriteFile(dbPath, initial, 0o666); err != nil { + t.Fatal(err) + } + writeApplyTestLTX(t, ltxPath, <x.FileSpec{ + Header: ltx.Header{ + Version: ltx.Version, + PageSize: pageSize, + Commit: 0, + MinTXID: 2, + MaxTXID: 2, + PreApplyChecksum: ltx.ChecksumPage(1, initial), + }, + Trailer: ltx.Trailer{PostApplyChecksum: ltx.ChecksumFlag}, + }) + + if err := NewApplyCommand().Run(context.Background(), []string{"-db", dbPath, ltxPath}); err != nil { + t.Fatal(err) + } + if got, err := os.ReadFile(dbPath); err != nil { + t.Fatal(err) + } else if len(got) != 0 { + t.Fatalf("database size=%d, want 0", len(got)) + } +} + func writeApplyTestLTX(t *testing.T, path string, spec *ltx.FileSpec) { t.Helper() diff --git a/ltx_test.go b/ltx_test.go index c7f594d..88fa98f 100644 --- a/ltx_test.go +++ b/ltx_test.go @@ -403,6 +403,14 @@ func TestParseFilename(t *testing.T) { } func TestChecksumReader(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + if chksum, err := ltx.ChecksumReader(bytes.NewReader(nil), 512); err != nil { + t.Fatal(err) + } else if got, want := chksum, ltx.ChecksumFlag; got != want { + t.Fatalf("got=%x, want %x", got, want) + } + }) + t.Run("OK", func(t *testing.T) { r := io.MultiReader( bytes.NewReader(bytes.Repeat([]byte("\x01"), 512)), @@ -418,8 +426,10 @@ func TestChecksumReader(t *testing.T) { t.Run("ErrUnexpectedEOF", func(t *testing.T) { r := bytes.NewReader(bytes.Repeat([]byte("\x01"), 512)) - if _, err := ltx.ChecksumReader(r, 1024); err != io.ErrUnexpectedEOF { + if chksum, err := ltx.ChecksumReader(r, 1024); err != io.ErrUnexpectedEOF { t.Fatal(err) + } else if got, want := chksum, ltx.Checksum(0); got != want { + t.Fatalf("got=%x, want %x", got, want) } }) }