]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance existing snapshot tests to serialize/deserialize snapshots. No new
authordan <dan@noemail.net>
Fri, 18 Nov 2016 14:38:41 +0000 (14:38 +0000)
committerdan <dan@noemail.net>
Fri, 18 Nov 2016 14:38:41 +0000 (14:38 +0000)
tests.

FossilOrigin-Name: 16b9bf92741e4c62874cffd7c6a61763c5054c7a

manifest
manifest.uuid
src/test1.c
test/snapshot.test

index 9c806b3a89c89fbf913a41d6a8f1a9adfa9d49ce..c5597fb6467f65f4e3871c4ade1b247e91734d51 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\schanges\stoward\smaking\ssnapshots\sserializable.
-D 2016-11-15T17:37:56.374
+C Enhance\sexisting\ssnapshot\stests\sto\sserialize/deserialize\ssnapshots.\sNo\snew\ntests.
+D 2016-11-18T14:38:41.852
 F Makefile.in 6b572807415d3f0a379cebc9461416d8df4a12c8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc bb4d970894abbbe0e88d00aac29bd52af8bc95f4
@@ -397,7 +397,7 @@ F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
 F src/tclsqlite.c aef87dcd8cb66564d560ab48d43d19ac812a1eab
-F src/test1.c f52bed152c97be23be794efa234374d0de593eeb
+F src/test1.c 58de30ed902f78531cf5cf52b883a26d107208c4
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -1102,7 +1102,7 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
 F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
-F test/snapshot.test a19465046168b4420b5afeed37c3214e42a49f4a
+F test/snapshot.test bb34cc38828bf2e86a49207995fa7dfacd303832
 F test/snapshot_fault.test 062ff0438a074978d45e9f9a92e7ad459b74ee73
 F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
 F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1534,10 +1534,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 663473850c4274270445b3771911fa773a8c405f
-R 1784ed6bcadef61e22ad39533122ebea
-T *branch * serializable-snapshot
-T *sym-serializable-snapshot *
-T -sym-trunk *
-U drh
-Z 8a16f1f47c269929c7f968ee35b8cb55
+P b6a81fa1fc1fb78a65894129851a4ec3986640de
+R 17ac6d49deba8d40db4fa5f6ce7fc2ca
+U dan
+Z cee5f11eb9093786088be3369dcd2153
index 5e74943d27a8e06ae669e191d3bec1e51d516c46..6af23f5732e713c6bf0a89a8921bec8e1776fdf0 100644 (file)
@@ -1 +1 @@
-b6a81fa1fc1fb78a65894129851a4ec3986640de
\ No newline at end of file
+16b9bf92741e4c62874cffd7c6a61763c5054c7a
\ No newline at end of file
index 18b6b295c2e80fb5a20e9d8c77425a2d0ab63fbf..e31ad95f40b2ee50ba96aac116fa11052887ec34 100644 (file)
@@ -2388,6 +2388,113 @@ static int SQLITE_TCLAPI test_snapshot_cmp(
 }
 #endif /* SQLITE_ENABLE_SNAPSHOT */
 
+#ifdef SQLITE_ENABLE_SNAPSHOT
+/*
+** Usage: sqlite3_snapshot_get_blob DB DBNAME
+*/
+static int SQLITE_TCLAPI test_snapshot_get_blob(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int rc;
+  sqlite3 *db;
+  char *zName;
+  sqlite3_snapshot *pSnapshot = 0;
+
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+  zName = Tcl_GetString(objv[2]);
+
+  rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
+  if( rc!=SQLITE_OK ){
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+    return TCL_ERROR;
+  }else{
+    Tcl_SetObjResult(interp, 
+        Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot))
+    );
+    sqlite3_snapshot_free(pSnapshot);
+  }
+  return TCL_OK;
+}
+#endif /* SQLITE_ENABLE_SNAPSHOT */
+
+#ifdef SQLITE_ENABLE_SNAPSHOT
+  /*
+  ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
+*/
+static int SQLITE_TCLAPI test_snapshot_open_blob(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int rc;
+  sqlite3 *db;
+  char *zName;
+  unsigned char *pBlob;
+  int nBlob;
+
+  if( objc!=4 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+  zName = Tcl_GetString(objv[2]);
+  pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob);
+  if( nBlob!=sizeof(sqlite3_snapshot) ){
+    Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
+    return TCL_ERROR;
+  }
+  rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob);
+  if( rc!=SQLITE_OK ){
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+    return TCL_ERROR;
+  }
+  return TCL_OK;
+}
+#endif /* SQLITE_ENABLE_SNAPSHOT */
+
+#ifdef SQLITE_ENABLE_SNAPSHOT
+/*
+** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
+*/
+static int SQLITE_TCLAPI test_snapshot_cmp_blob(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int res;
+  unsigned char *p1;
+  unsigned char *p2;
+  int n1;
+  int n2;
+
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
+    return TCL_ERROR;
+  }
+
+  p1 = Tcl_GetByteArrayFromObj(objv[1], &n1);
+  p2 = Tcl_GetByteArrayFromObj(objv[2], &n2);
+
+  if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){
+    Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
+    return TCL_ERROR;
+  }
+
+  res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2);
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
+  return TCL_OK;
+}
+#endif /* SQLITE_ENABLE_SNAPSHOT */
+
 /*
 ** Usage: sqlite3_delete_database FILENAME
 */
@@ -7539,6 +7646,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_snapshot_open", test_snapshot_open, 0 },
      { "sqlite3_snapshot_free", test_snapshot_free, 0 },
      { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
+     { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 },
+     { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
+     { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
 #endif
      { "sqlite3_delete_database", test_delete_database, 0 },
   };
index b2d61941a716ca00a61ef21171b8cb3b0a66b8d0..1143c149623512bfd650d9ceee8e794c6ca24e61 100644 (file)
@@ -26,413 +26,448 @@ if {[permutation]=="inmemory_journal"} {
   return
 }
 
-#-------------------------------------------------------------------------
-# Check some error conditions in snapshot_get(). It is an error if:
-#
-#  1) snapshot_get() is called on a non-WAL database, or
-#  2) there is an open write transaction on the database.
-#
-do_execsql_test 1.0 {
-  CREATE TABLE t1(a, b);
-  INSERT INTO t1 VALUES(1, 2);
-  INSERT INTO t1 VALUES(3, 4);
-}
-
-do_test 1.1.1 {
-  execsql { BEGIN; SELECT * FROM t1; }
-  list [catch { sqlite3_snapshot_get db main } msg] $msg
-} {1 SQLITE_ERROR}
-do_execsql_test 1.1.2 COMMIT
-
-do_test 1.2.1 {
-  execsql {
-    PRAGMA journal_mode = WAL;
-    BEGIN;
-      INSERT INTO t1 VALUES(5, 6);
-      INSERT INTO t1 VALUES(7, 8);
+foreach {tn tcl} {
+  1 {
+    proc snapshot_get {DB DBNAME} {
+      uplevel [list sqlite3_snapshot_get $DB $DBNAME]
+    }
+    proc snapshot_open {DB DBNAME SNAPSHOT} {
+      uplevel [list sqlite3_snapshot_open $DB $DBNAME $SNAPSHOT]
+    }
+    proc snapshot_free {SNAPSHOT} {
+      uplevel [list sqlite3_snapshot_free $SNAPSHOT]
+    }
+    proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} {
+      uplevel [list sqlite3_snapshot_cmp $SNAPSHOT1 $SNAPSHOT2]
+    }
   }
-  list [catch { sqlite3_snapshot_get db main } msg] $msg
-} {1 SQLITE_ERROR}
-do_execsql_test 1.3.2 COMMIT
 
-#-------------------------------------------------------------------------
-# Check that a simple case works. Reuse the database created by the
-# block of tests above.
-#
-do_execsql_test 2.1.0 {
-  BEGIN;
-    SELECT * FROM t1;
-} {1 2 3 4 5 6 7 8}
-
-do_test 2.1.1 {
-  set snapshot [sqlite3_snapshot_get db main]
-  execsql {
-    COMMIT;
-    INSERT INTO t1 VALUES(9, 10);
-    SELECT * FROM t1;
+  2 {
+    proc snapshot_get {DB DBNAME} {
+      uplevel [list sqlite3_snapshot_get_blob $DB $DBNAME]
+    }
+    proc snapshot_open {DB DBNAME SNAPSHOT} {
+      uplevel [list sqlite3_snapshot_open_blob $DB $DBNAME $SNAPSHOT]
+    }
+    proc snapshot_free {SNAPSHOT} {
+    }
+    proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} {
+      uplevel [list sqlite3_snapshot_cmp_blob $SNAPSHOT1 $SNAPSHOT2]
+    }
   }
-} {1 2 3 4 5 6 7 8 9 10}
-
-do_test 2.1.2 {
-  execsql BEGIN
-  sqlite3_snapshot_open db main $snapshot
-  execsql {
-    SELECT * FROM t1;
+} {
+
+  reset_db
+  eval $tcl
+
+  #-------------------------------------------------------------------------
+  # Check some error conditions in snapshot_get(). It is an error if:
+  #
+  #  1) snapshot_get() is called on a non-WAL database, or
+  #  2) there is an open write transaction on the database.
+  #
+  do_execsql_test $tn.1.0 {
+    CREATE TABLE t1(a, b);
+    INSERT INTO t1 VALUES(1, 2);
+    INSERT INTO t1 VALUES(3, 4);
   }
-} {1 2 3 4 5 6 7 8}
 
-do_test 2.1.3 {
-  sqlite3_snapshot_free $snapshot
-  execsql COMMIT
-} {}
-
-do_test 2.2.0 {
-  sqlite3 db2 test.db
-  execsql {
+  do_test $tn.1.1.1 {
+    execsql { BEGIN; SELECT * FROM t1; }
+    list [catch { snapshot_get db main } msg] $msg
+  } {1 SQLITE_ERROR}
+  do_execsql_test 1.1.2 COMMIT
+
+  do_test $tn.1.2.1 {
+    execsql {
+      PRAGMA journal_mode = WAL;
+      BEGIN;
+        INSERT INTO t1 VALUES(5, 6);
+        INSERT INTO t1 VALUES(7, 8);
+    }
+    list [catch { snapshot_get db main } msg] $msg
+  } {1 SQLITE_ERROR}
+  do_execsql_test $tn.1.3.2 COMMIT
+
+  #-------------------------------------------------------------------------
+  # Check that a simple case works. Reuse the database created by the
+  # block of tests above.
+  #
+  do_execsql_test $tn.2.1.0 {
     BEGIN;
       SELECT * FROM t1;
-  } db2
-} {1 2 3 4 5 6 7 8 9 10}
-
-do_test 2.2.1 {
-  set snapshot [sqlite3_snapshot_get db2 main]
-  execsql {
-    INSERT INTO t1 VALUES(11, 12);
-    SELECT * FROM t1;
-  }
-} {1 2 3 4 5 6 7 8 9 10 11 12}
+  } {1 2 3 4 5 6 7 8}
 
-do_test 2.2.2 {
-  execsql BEGIN
-  sqlite3_snapshot_open db main $snapshot
-  execsql {
-    SELECT * FROM t1;
-  }
-} {1 2 3 4 5 6 7 8 9 10}
+  do_test $tn.2.1.1 {
+    set snapshot [snapshot_get db main]
+    execsql {
+      COMMIT;
+      INSERT INTO t1 VALUES(9, 10);
+      SELECT * FROM t1;
+    }
+  } {1 2 3 4 5 6 7 8 9 10}
 
-do_test 2.2.3 {
-  sqlite3_snapshot_free $snapshot
-  execsql COMMIT
-  execsql COMMIT db2
-  db2 close
-} {}
-
-do_test 2.3.1 {
-  execsql { DELETE FROM t1 WHERE a>6 }
-  set snapshot [sqlite3_snapshot_get db main]
-  execsql {
-    INSERT INTO t1 VALUES('a', 'b');
-    INSERT INTO t1 VALUES('c', 'd');
-    SELECT * FROM t1;
-  }
-} {1 2 3 4 5 6 a b c d}
-do_test 2.3.2 {
-  execsql BEGIN
-  sqlite3_snapshot_open db main $snapshot
-  execsql { SELECT * FROM t1 }
-} {1 2 3 4 5 6}
-
-do_test 2.3.3 {
-  catchsql {
-    INSERT INTO t1 VALUES('x','y')
-  }
-} {1 {database is locked}}
-do_test 2.3.4 {
-  execsql COMMIT
-  sqlite3_snapshot_free $snapshot
-} {}
-
-#-------------------------------------------------------------------------
-# Check some errors in sqlite3_snapshot_open(). It is an error if:
-#
-#   1) the db is in auto-commit mode,
-#   2) the db has an open (read or write) transaction,
-#   3) the db is not a wal database,
-#
-# Reuse the database created by earlier tests.
-#
-do_execsql_test 3.0.0 {
-  CREATE TABLE t2(x, y);
-  INSERT INTO t2 VALUES('a', 'b');
-  INSERT INTO t2 VALUES('c', 'd');
-  BEGIN;
-    SELECT * FROM t2;
-} {a b c d}
-do_test 3.0.1 {
-  set snapshot [sqlite3_snapshot_get db main]
-  execsql { COMMIT }
-  execsql { INSERT INTO t2 VALUES('e', 'f'); }
-} {}
-
-do_test 3.1 {
-  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
-} {1 SQLITE_ERROR}
-
-do_test 3.2.1 {
-  execsql {
+  do_test $tn.2.1.2 {
+    execsql BEGIN
+    snapshot_open db main $snapshot
+    execsql {
+      SELECT * FROM t1;
+    }
+  } {1 2 3 4 5 6 7 8}
+
+  do_test $tn.2.1.3 {
+    snapshot_free $snapshot
+    execsql COMMIT
+  } {}
+
+  do_test $tn.2.2.0 {
+    sqlite3 db2 test.db
+    execsql {
+      BEGIN;
+        SELECT * FROM t1;
+    } db2
+  } {1 2 3 4 5 6 7 8 9 10}
+
+  do_test $tn.2.2.1 {
+    set snapshot [snapshot_get db2 main]
+    execsql {
+      INSERT INTO t1 VALUES(11, 12);
+      SELECT * FROM t1;
+    }
+  } {1 2 3 4 5 6 7 8 9 10 11 12}
+
+  do_test $tn.2.2.2 {
+    execsql BEGIN
+    snapshot_open db main $snapshot
+    execsql {
+      SELECT * FROM t1;
+    }
+  } {1 2 3 4 5 6 7 8 9 10}
+
+  do_test $tn.2.2.3 {
+    snapshot_free $snapshot
+    execsql COMMIT
+    execsql COMMIT db2
+    db2 close
+  } {}
+
+  do_test $tn.2.3.1 {
+    execsql { DELETE FROM t1 WHERE a>6 }
+    set snapshot [snapshot_get db main]
+    execsql {
+      INSERT INTO t1 VALUES('a', 'b');
+      INSERT INTO t1 VALUES('c', 'd');
+      SELECT * FROM t1;
+    }
+  } {1 2 3 4 5 6 a b c d}
+  do_test $tn.2.3.2 {
+    execsql BEGIN
+    snapshot_open db main $snapshot
+    execsql { SELECT * FROM t1 }
+  } {1 2 3 4 5 6}
+
+  do_test $tn.2.3.3 {
+    catchsql {
+      INSERT INTO t1 VALUES('x','y')
+    }
+  } {1 {database is locked}}
+  do_test $tn.2.3.4 {
+    execsql COMMIT
+    snapshot_free $snapshot
+  } {}
+
+  #-------------------------------------------------------------------------
+  # Check some errors in snapshot_open(). It is an error if:
+  #
+  #   1) the db is in auto-commit mode,
+  #   2) the db has an open (read or write) transaction,
+  #   3) the db is not a wal database,
+  #
+  # Reuse the database created by earlier tests.
+  #
+  do_execsql_test $tn.3.0.0 {
+    CREATE TABLE t2(x, y);
+    INSERT INTO t2 VALUES('a', 'b');
+    INSERT INTO t2 VALUES('c', 'd');
     BEGIN;
       SELECT * FROM t2;
-  }
-} {a b c d e f}
-do_test 3.2.2 {
-  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
-} {1 SQLITE_ERROR}
-
-do_test 3.2.3 {
-  execsql {
-    COMMIT;
-    BEGIN;
-      INSERT INTO t2 VALUES('g', 'h');
-  }
-  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
-} {1 SQLITE_ERROR}
-do_execsql_test 3.2.4 COMMIT
-
-do_test 3.3.1 {
-  execsql { PRAGMA journal_mode = DELETE }
-  execsql { BEGIN }
-  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
-} {1 SQLITE_ERROR}
-
-do_test 3.3.2 {
-  sqlite3_snapshot_free $snapshot
-  execsql COMMIT
-} {}
-
-#-------------------------------------------------------------------------
-# Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot
-# no longer exists because the wal file has been checkpointed.
-#
-#   1. Reading a snapshot from the middle of a wal file is not possible
-#      after the wal file has been checkpointed.
-#
-#   2. That a snapshot from the end of a wal file can not be read once
-#      the wal file has been wrapped.
-#
-do_execsql_test 4.1.0 {
-  PRAGMA journal_mode = wal;
-  CREATE TABLE t3(i, j);
-  INSERT INTO t3 VALUES('o', 't');
-  INSERT INTO t3 VALUES('t', 'f');
-  BEGIN;
-    SELECT * FROM t3;
-} {wal o t t f}
-
-do_test 4.1.1 {
-  set snapshot [sqlite3_snapshot_get db main]
-  execsql COMMIT
-} {}
-do_test 4.1.2 {
-  execsql { 
-    INSERT INTO t3 VALUES('f', 's'); 
-    BEGIN;
-  }
-  sqlite3_snapshot_open db main $snapshot
-  execsql { SELECT * FROM t3 }
-} {o t t f}
-
-do_test 4.1.3 {
-  execsql { 
-    COMMIT;
-    PRAGMA wal_checkpoint;
-    BEGIN;
-  }
-  list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
-} {1 SQLITE_BUSY_SNAPSHOT}
-do_test 4.1.4 {
-  sqlite3_snapshot_free $snapshot
-  execsql COMMIT
-} {}
-
-do_test 4.2.1 {
-  execsql {
-    INSERT INTO t3 VALUES('s', 'e');
-    INSERT INTO t3 VALUES('n', 't');
+  } {a b c d}
+  do_test $tn.3.0.1 {
+    set snapshot [snapshot_get db main]
+    execsql { COMMIT }
+    execsql { INSERT INTO t2 VALUES('e', 'f'); }
+  } {}
+
+  do_test $tn.3.1 {
+    list [catch {snapshot_open db main $snapshot } msg] $msg
+  } {1 SQLITE_ERROR}
+
+  do_test $tn.3.2.1 {
+    execsql {
+      BEGIN;
+        SELECT * FROM t2;
+    }
+  } {a b c d e f}
+  do_test $tn.3.2.2 {
+    list [catch {snapshot_open db main $snapshot } msg] $msg
+  } {1 SQLITE_ERROR}
+
+  do_test $tn.3.2.3 {
+    execsql {
+      COMMIT;
+      BEGIN;
+        INSERT INTO t2 VALUES('g', 'h');
+    }
+    list [catch {snapshot_open db main $snapshot } msg] $msg
+  } {1 SQLITE_ERROR}
+  do_execsql_test 3.2.4 COMMIT
+
+  do_test $tn.3.3.1 {
+    execsql { PRAGMA journal_mode = DELETE }
+    execsql { BEGIN }
+    list [catch {snapshot_open db main $snapshot } msg] $msg
+  } {1 SQLITE_ERROR}
+
+  do_test $tn.$tn.3.3.2 {
+    snapshot_free $snapshot
+    execsql COMMIT
+  } {}
+
+  #-------------------------------------------------------------------------
+  # Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot
+  # no longer exists because the wal file has been checkpointed.
+  #
+  #   1. Reading a snapshot from the middle of a wal file is not possible
+  #      after the wal file has been checkpointed.
+  #
+  #   2. That a snapshot from the end of a wal file can not be read once
+  #      the wal file has been wrapped.
+  #
+  do_execsql_test $tn.4.1.0 {
+    PRAGMA journal_mode = wal;
+    CREATE TABLE t3(i, j);
+    INSERT INTO t3 VALUES('o', 't');
+    INSERT INTO t3 VALUES('t', 'f');
     BEGIN;
       SELECT * FROM t3;
-  }
-} {o t t f f s s e n t}
-do_test 4.2.2 {
-  set snapshot [sqlite3_snapshot_get db main]
-  execsql {
-    COMMIT;
-    PRAGMA wal_checkpoint;
-    BEGIN;
-  }
-  sqlite3_snapshot_open db main $snapshot
-  execsql { SELECT * FROM t3 }
-} {o t t f f s s e n t}
-do_test 4.2.3 {
-  execsql {
-    COMMIT;
-    INSERT INTO t3 VALUES('e', 't');
+  } {wal o t t f}
+
+  do_test $tn.4.1.1 {
+    set snapshot [snapshot_get db main]
+    execsql COMMIT
+  } {}
+  do_test $tn.4.1.2 {
+    execsql { 
+      INSERT INTO t3 VALUES('f', 's'); 
+      BEGIN;
+    }
+    snapshot_open db main $snapshot
+    execsql { SELECT * FROM t3 }
+  } {o t t f}
+
+  do_test $tn.4.1.3 {
+    execsql { 
+      COMMIT;
+      PRAGMA wal_checkpoint;
+      BEGIN;
+    }
+    list [catch {snapshot_open db main $snapshot} msg] $msg
+  } {1 SQLITE_BUSY_SNAPSHOT}
+  do_test $tn.4.1.4 {
+    snapshot_free $snapshot
+    execsql COMMIT
+  } {}
+
+  do_test $tn.4.2.1 {
+    execsql {
+      INSERT INTO t3 VALUES('s', 'e');
+      INSERT INTO t3 VALUES('n', 't');
+      BEGIN;
+        SELECT * FROM t3;
+    }
+  } {o t t f f s s e n t}
+  do_test $tn.4.2.2 {
+    set snapshot [snapshot_get db main]
+    execsql {
+      COMMIT;
+      PRAGMA wal_checkpoint;
+      BEGIN;
+    }
+    snapshot_open db main $snapshot
+    execsql { SELECT * FROM t3 }
+  } {o t t f f s s e n t}
+  do_test $tn.4.2.3 {
+    execsql {
+      COMMIT;
+      INSERT INTO t3 VALUES('e', 't');
+      BEGIN;
+    }
+    list [catch {snapshot_open db main $snapshot} msg] $msg
+  } {1 SQLITE_BUSY_SNAPSHOT}
+  do_test $tn.4.2.4 {
+    snapshot_free $snapshot
+  } {}
+
+  #-------------------------------------------------------------------------
+  # Check that SQLITE_BUSY is returned if a checkpoint is running when
+  # sqlite3_snapshot_open() is called.
+  #
+  reset_db
+  db close
+  testvfs tvfs
+  sqlite3 db test.db -vfs tvfs
+
+  do_execsql_test $tn.5.1 {
+    PRAGMA journal_mode = wal;
+    CREATE TABLE x1(x, xx, xxx);
+    INSERT INTO x1 VALUES('z', 'zz', 'zzz');
     BEGIN;
+      SELECT * FROM x1;
+  } {wal z zz zzz}
+
+  do_test $tn.5.2 {
+    set ::snapshot [snapshot_get db main]
+    sqlite3 db2 test.db -vfs tvfs
+    execsql {
+      INSERT INTO x1 VALUES('a', 'aa', 'aaa');
+      COMMIT;
+    }
+  } {}
+
+  set t53 0
+  proc write_callback {args} {
+    do_test $tn.5.3.[incr ::t53] {
+      execsql BEGIN
+      list [catch { snapshot_open db main $::snapshot } msg] $msg
+    } {1 SQLITE_BUSY}
+    catchsql COMMIT
   }
-  list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
-} {1 SQLITE_BUSY_SNAPSHOT}
-do_test 4.2.4 {
-  sqlite3_snapshot_free $snapshot
-} {}
-
-#-------------------------------------------------------------------------
-# Check that SQLITE_BUSY is returned if a checkpoint is running when
-# sqlite3_snapshot_open() is called.
-#
-reset_db
-db close
-testvfs tvfs
-sqlite3 db test.db -vfs tvfs
-
-do_execsql_test 5.1 {
-  PRAGMA journal_mode = wal;
-  CREATE TABLE x1(x, xx, xxx);
-  INSERT INTO x1 VALUES('z', 'zz', 'zzz');
-  BEGIN;
-    SELECT * FROM x1;
-} {wal z zz zzz}
-
-do_test 5.2 {
-  set ::snapshot [sqlite3_snapshot_get db main]
-  sqlite3 db2 test.db -vfs tvfs
-  execsql {
-    INSERT INTO x1 VALUES('a', 'aa', 'aaa');
-    COMMIT;
-  }
-} {}
-
-set t53 0
-proc write_callback {args} {
-  do_test 5.3.[incr ::t53] {
-    execsql BEGIN
-    list [catch { sqlite3_snapshot_open db main $::snapshot } msg] $msg
-  } {1 SQLITE_BUSY}
-  catchsql COMMIT
-}
 
-tvfs filter xWrite
-tvfs script write_callback
-db2 eval { PRAGMA wal_checkpoint }
-db close
-db2 close
-tvfs delete
-sqlite3_snapshot_free $snapshot
-
-#-------------------------------------------------------------------------
-# Test that sqlite3_snapshot_get() may be called immediately after
-# "BEGIN; PRAGMA user_version;". And that sqlite3_snapshot_open() may
-# be called after opening the db handle and running the script
-# "PRAGMA user_version; BEGIN".
-reset_db
-do_execsql_test 6.1 {
-  PRAGMA journal_mode = wal;
-  CREATE TABLE x1(x, xx, xxx);
-  INSERT INTO x1 VALUES('z', 'zz', 'zzz');
-  BEGIN;
-    PRAGMA user_version;
-} {wal 0}
-do_test 6.2 {
-  set ::snapshot [sqlite3_snapshot_get db main]
-  execsql {
-    INSERT INTO x1 VALUES('a', 'aa', 'aaa');
-    COMMIT;
-  }
-} {}
-do_test 6.3 {
-  sqlite3 db2 test.db 
-  db2 eval "PRAGMA user_version ; BEGIN"
-  sqlite3_snapshot_open db2 main $::snapshot
-  db2 eval { SELECT * FROM x1 }
-} {z zz zzz}
-do_test 6.4 {
+  tvfs filter xWrite
+  tvfs script write_callback
+  db2 eval { PRAGMA wal_checkpoint }
+  db close
   db2 close
-  sqlite3 db2 test.db 
-  db2 eval "PRAGMA application_id"
-  db2 eval "BEGIN"
-  sqlite3_snapshot_open db2 main $::snapshot
-  db2 eval { SELECT * FROM x1 }
-} {z zz zzz}
-
-do_test 6.5 {
-  db2 close
-  sqlite3 db2 test.db 
-  db2 eval "BEGIN"
-  list [catch {sqlite3_snapshot_open db2 main $::snapshot} msg] $msg
-} {1 SQLITE_ERROR}
-
-sqlite3_snapshot_free $snapshot
-
-#-------------------------------------------------------------------------
-# The following tests investigate the sqlite3_snapshot_cmp() API.
-#
-
-# Compare snapshots $p1 and $p2, checking that the result is $r.
-#
-proc do_snapshot_cmp_test {tn p1 p2 r} {
-  uplevel [list do_test $tn.1 [list sqlite3_snapshot_cmp $p1 $p2] $r]
-  uplevel [list do_test $tn.2 [list sqlite3_snapshot_cmp $p2 $p1] [expr $r*-1]]
-  uplevel [list do_test $tn.3 [list sqlite3_snapshot_cmp $p1 $p1] 0]
-  uplevel [list do_test $tn.4 [list sqlite3_snapshot_cmp $p2 $p2] 0]
-}
-
-catch { db2 close }
-reset_db
-
-do_execsql_test 7.1 {
-  PRAGMA journal_mode = wal;
-  CREATE TABLE t1(x);
-} wal
-
-do_test 7.1.2 {
-  execsql { BEGIN ; PRAGMA application_id }
-  set p1 [sqlite3_snapshot_get db main]
-  execsql {
-    INSERT INTO t1 VALUES(10);
-    COMMIT;
-  }
-  execsql { BEGIN ; PRAGMA application_id }
-  set p2 [sqlite3_snapshot_get db main]
-  execsql COMMIT
-} {}
-
-do_snapshot_cmp_test 7.1.3 $p1 $p2 -1
-sqlite3_snapshot_free $p1
-sqlite3_snapshot_free $p2
-
-do_execsql_test 7.2.1 {
-  INSERT INTO t1 VALUES(11);
-  INSERT INTO t1 VALUES(12);
-  INSERT INTO t1 VALUES(13);
-  BEGIN; 
-    PRAGMA application_id;
-} {0}
-do_test 7.2.2 {
-  set p1 [sqlite3_snapshot_get db main]
-  execsql {
-    COMMIT;
-    INSERT INTO t1 VALUES(14);
-    PRAGMA wal_checkpoint;
+  tvfs delete
+  snapshot_free $snapshot
+
+  #-------------------------------------------------------------------------
+  # Test that sqlite3_snapshot_get() may be called immediately after
+  # "BEGIN; PRAGMA user_version;". And that sqlite3_snapshot_open() may
+  # be called after opening the db handle and running the script
+  # "PRAGMA user_version; BEGIN".
+  reset_db
+  do_execsql_test $tn.6.1 {
+    PRAGMA journal_mode = wal;
+    CREATE TABLE x1(x, xx, xxx);
+    INSERT INTO x1 VALUES('z', 'zz', 'zzz');
     BEGIN;
-      PRAGMA application_id;
+      PRAGMA user_version;
+  } {wal 0}
+  do_test $tn.6.2 {
+    set ::snapshot [snapshot_get db main]
+    execsql {
+      INSERT INTO x1 VALUES('a', 'aa', 'aaa');
+      COMMIT;
+    }
+  } {}
+  do_test $tn.6.3 {
+    sqlite3 db2 test.db 
+    db2 eval "PRAGMA user_version ; BEGIN"
+    snapshot_open db2 main $::snapshot
+    db2 eval { SELECT * FROM x1 }
+  } {z zz zzz}
+  do_test $tn.6.4 {
+    db2 close
+    sqlite3 db2 test.db 
+    db2 eval "PRAGMA application_id"
+    db2 eval "BEGIN"
+    snapshot_open db2 main $::snapshot
+    db2 eval { SELECT * FROM x1 }
+  } {z zz zzz}
+
+  do_test $tn.6.5 {
+    db2 close
+    sqlite3 db2 test.db 
+    db2 eval "BEGIN"
+    list [catch {snapshot_open db2 main $::snapshot} msg] $msg
+  } {1 SQLITE_ERROR}
+
+  snapshot_free $snapshot
+
+  #-------------------------------------------------------------------------
+  # The following tests investigate the sqlite3_snapshot_cmp() API.
+  #
+
+  # Compare snapshots $p1 and $p2, checking that the result is $r.
+  #
+  proc do_snapshot_cmp_test {tn p1 p2 r} {
+    uplevel [list do_test $tn.1 [list snapshot_cmp $p1 $p2] $r]
+    uplevel [list do_test $tn.2 [list snapshot_cmp $p2 $p1] [expr $r*-1]]
+    uplevel [list do_test $tn.3 [list snapshot_cmp $p1 $p1] 0]
+    uplevel [list do_test $tn.4 [list snapshot_cmp $p2 $p2] 0]
   }
-  set p2 [sqlite3_snapshot_get db main]
-  execsql COMMIT
-} {}
 
-do_snapshot_cmp_test 7.2.3 $p1 $p2 -1
-sqlite3_snapshot_free $p2
-
-do_test 7.3.1 {
-  execsql {
-    INSERT INTO t1 VALUES(14);
-    BEGIN;
+  catch { db2 close }
+  reset_db
+
+  do_execsql_test $tn.7.1 {
+    PRAGMA journal_mode = wal;
+    CREATE TABLE t1(x);
+  } wal
+
+  do_test $tn.7.1.2 {
+    execsql { BEGIN ; PRAGMA application_id }
+    set p1 [snapshot_get db main]
+    execsql {
+      INSERT INTO t1 VALUES(10);
+      COMMIT;
+    }
+    execsql { BEGIN ; PRAGMA application_id }
+    set p2 [snapshot_get db main]
+    execsql COMMIT
+  } {}
+
+  do_snapshot_cmp_test $tn.7.1.3 $p1 $p2 -1
+  snapshot_free $p1
+  snapshot_free $p2
+
+  do_execsql_test $tn.7.2.1 {
+    INSERT INTO t1 VALUES(11);
+    INSERT INTO t1 VALUES(12);
+    INSERT INTO t1 VALUES(13);
+    BEGIN; 
       PRAGMA application_id;
-  }
-  set p2 [sqlite3_snapshot_get db main]
-  execsql COMMIT
-} {}
-
-do_snapshot_cmp_test 7.3.2 $p1 $p2 -1
-sqlite3_snapshot_free $p1
-sqlite3_snapshot_free $p2
+  } {0}
+  do_test $tn.7.2.2 {
+    set p1 [snapshot_get db main]
+    execsql {
+      COMMIT;
+      INSERT INTO t1 VALUES(14);
+      PRAGMA wal_checkpoint;
+      BEGIN;
+        PRAGMA application_id;
+    }
+    set p2 [snapshot_get db main]
+    execsql COMMIT
+  } {}
+
+  do_snapshot_cmp_test $tn.7.2.3 $p1 $p2 -1
+  snapshot_free $p2
+
+  do_test $tn.7.3.1 {
+    execsql {
+      INSERT INTO t1 VALUES(14);
+      BEGIN;
+        PRAGMA application_id;
+    }
+    set p2 [snapshot_get db main]
+    execsql COMMIT
+  } {}
+
+  do_snapshot_cmp_test $tn.7.3.2 $p1 $p2 -1
+  snapshot_free $p1
+  snapshot_free $p2
+}
 
 finish_test