@@ -298,6 +298,117 @@ func TestSingleNode_RecoverFromInitialRollback(t *testing.T) {
298298 }
299299}
300300
301+ // Ensure that CommitJournal correctly computes the incremental checksum when
302+ // pages are modified multiple times.
303+ func TestSingleNode_JournalMultipleUpdates (t * testing.T ) {
304+ // This test only applies to the rollback journal, but it passes in WAL mode.
305+
306+ cmd := runMountCommand (t , newMountCommand (t , t .TempDir (), nil ))
307+ db := testingutil .OpenSQLDB (t , filepath .Join (cmd .Config .FUSE .Dir , "db" ))
308+
309+ // Disable page cache so dirty pages are written immediately.
310+ if _ , err := db .Exec (`PRAGMA cache_size = 0` ); err != nil {
311+ t .Fatal (err )
312+ }
313+
314+ if _ , err := db .Exec (`CREATE TABLE t (x)` ); err != nil {
315+ t .Fatal (err )
316+ }
317+ for i := 0 ; i < 500 ; i ++ {
318+ if _ , err := db .Exec (`INSERT INTO t VALUES (?)` , strings .Repeat ("x" , 60 )); err != nil {
319+ t .Fatal (err )
320+ }
321+ }
322+
323+ tx , err := db .Begin ()
324+ if err != nil {
325+ t .Fatal (err )
326+ }
327+ defer func () { _ = tx .Rollback () }()
328+
329+ // Update all pages (LiteFS will store the previous page checksum).
330+ if _ , err := tx .Exec (`UPDATE t SET x = ?` , strings .Repeat ("y" , 60 )); err != nil {
331+ t .Fatal (err )
332+ }
333+ // Update all pages again (LiteFS should not update the previous page checksum).
334+ if _ , err := tx .Exec (`UPDATE t SET x = ?` , strings .Repeat ("z" , 60 )); err != nil {
335+ t .Fatal (err )
336+ }
337+ if err := tx .Commit (); err != nil {
338+ t .Fatal (err )
339+ }
340+ }
341+
342+ // Ensure that CommitJournal correctly computes the checksum when the commit
343+ // truncates dirty pages.
344+ func TestSingleNode_JournalTruncateDirtyPages (t * testing.T ) {
345+ if testingutil .IsWALMode () {
346+ // The page count assertion will fail in WAL mode.
347+ t .Skip ("test only applies to rollback journal, skipping" )
348+ }
349+
350+ cmd := runMountCommand (t , newMountCommand (t , t .TempDir (), nil ))
351+ db := testingutil .OpenSQLDB (t , filepath .Join (cmd .Config .FUSE .Dir , "db" ))
352+
353+ // Make sure the database is truncated on commit.
354+ if _ , err := db .Exec (`PRAGMA auto_vacuum = FULL` ); err != nil {
355+ t .Fatal (err )
356+ }
357+
358+ if _ , err := db .Exec (`CREATE TABLE t (id INTEGER PRIMARY KEY, x)` ); err != nil {
359+ t .Fatal (err )
360+ }
361+ for i := 0 ; i < 500 ; i ++ {
362+ if _ , err := db .Exec (`INSERT INTO t (x) VALUES (?)` , strings .Repeat ("x" , 60 )); err != nil {
363+ t .Fatal (err )
364+ }
365+ }
366+
367+ var pageCount int
368+ if err := db .QueryRow (`PRAGMA page_count` ).Scan (& pageCount ); err != nil {
369+ t .Fatal (err )
370+ }
371+ t .Logf ("pre-commit pageCount = %d" , pageCount )
372+ if got , want := pageCount , 8 ; got <= want {
373+ t .Fatalf ("got %d pages, want more than %d" , got , want )
374+ }
375+
376+ tx , err := db .Begin ()
377+ if err != nil {
378+ t .Fatal (err )
379+ }
380+ defer func () { _ = tx .Rollback () }()
381+
382+ // Make all pages dirty.
383+ if _ , err := tx .Exec (`UPDATE t SET x = ?` , strings .Repeat ("y" , 60 )); err != nil {
384+ t .Fatal (err )
385+ }
386+ // Truncate the database.
387+ if _ , err := tx .Exec (`DELETE FROM t WHERE id > ?` , 100 ); err != nil {
388+ t .Fatal (err )
389+ }
390+ if err := tx .Commit (); err != nil {
391+ t .Fatal (err )
392+ }
393+
394+ var count int
395+ if err := db .QueryRow (`SELECT COUNT(*) FROM t` ).Scan (& count ); err != nil {
396+ t .Fatal (err )
397+ }
398+ if got , want := count , 100 ; got != want {
399+ t .Fatalf ("count=%d, want %d" , got , want )
400+ }
401+
402+ // Make sure the database was truncated.
403+ if err := db .QueryRow (`PRAGMA page_count` ).Scan (& pageCount ); err != nil {
404+ t .Fatal (err )
405+ }
406+ t .Logf ("post-commit pageCount = %d" , pageCount )
407+ if got , want := pageCount , 8 ; got >= want {
408+ t .Fatalf ("got %d pages, want less than %d" , got , want )
409+ }
410+ }
411+
301412func TestSingleNode_DropDB (t * testing.T ) {
302413 cmd0 := runMountCommand (t , newMountCommand (t , t .TempDir (), nil ))
303414 dsn := filepath .Join (cmd0 .Config .FUSE .Dir , "db" )
0 commit comments