]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add simple tests for the sessions module rebase API.
authordan <dan@noemail.net>
Thu, 15 Mar 2018 19:25:40 +0000 (19:25 +0000)
committerdan <dan@noemail.net>
Thu, 15 Mar 2018 19:25:40 +0000 (19:25 +0000)
FossilOrigin-Name: cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211

ext/session/sessionrebase.test
ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index 403b3320d05a18a36c568618e776dbcf63972e6e..9085068922ad116c0e32111ff3a8baa0f2847658 100644 (file)
@@ -121,5 +121,131 @@ do_apply_v2_test 1.3.2 {
   {DELETE t1 0 X. {i 1 {} {}} {}}
 }
 
+#-------------------------------------------------------------------------
+# Test cases 2.* - simple tests of rebasing actual changesets.
+#
+#    2.1.1 - 1u2u1r
+#    2.1.2 - 1u2u2r
+#    2.1.3 - 1d2d
+#    2.1.4 - 1d2u1r
+#    2.1.5 - 1d2u2r !!
+#    2.1.6 - 1u2d1r
+
+proc xConflictAbort {args} {
+  return "ABORT"
+}
+
+# Take a copy of database test.db in file test.db2. Execute $sql1
+# against test.db and $sql2 against test.db2. Capture a changeset
+# for each. Then send the test.db2 changeset to test.db and apply
+# it with the conflict handlers in $conflict_handler. Patch the
+# test.db changeset and then execute it against test.db2. Test that
+# the two databases come out the same.
+#
+proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
+
+  forcedelete test.db2 test.db2-journal test.db2-wal
+  forcecopy test.db test.db2
+  sqlite3 db2 test.db2
+
+  db eval BEGIN
+
+  sqlite3session S1 db main
+  S1 attach *
+  execsql $sql1 db
+  set c1 [S1 changeset]
+  S1 delete
+
+  sqlite3session S2 db2 main
+  S2 attach *
+  execsql $sql2 db2
+  set c2 [S2 changeset]
+  S2 delete
+
+  set ::lConflict $conflict_handler
+  set rebase [sqlite3changeset_apply_v2 db $c2 xConflict]
+  #puts [changeset_to_list $rebase]
+
+  sqlite3rebaser_create R
+  R configure $rebase
+  set c1r [R rebase $c1]
+  R delete
+  #puts [changeset_to_list $c1r]
+
+  sqlite3changeset_apply_v2 db2 $c1r xConflictAbort
+
+  uplevel [list do_test $tn.1 [list compare_db db db2] {}]
+  db2 close
+
+  if {$testsql!=""} {
+    uplevel [list do_execsql_test $tn.2 $testsql $testres]
+  }
+
+  db eval ROLLBACK
+}
+
+reset_db
+do_execsql_test 2.1.0 {
+  CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT);
+  INSERT INTO t1 VALUES(1, 'one');
+  INSERT INTO t1 VALUES(2, 'two');
+  INSERT INTO t1 VALUES(3, 'three');
+}
+do_rebase_test 2.1.1 {
+  UPDATE t1 SET b = 'two.1' WHERE a=2;
+} {
+  UPDATE t1 SET b = 'two.2' WHERE a=2;
+} {
+  OMIT
+} { SELECT * FROM t1 } {1 one 2 two.1 3 three}
+
+do_rebase_test 2.1.2 {
+  UPDATE t1 SET b = 'two.1' WHERE a=2;
+} {
+  UPDATE t1 SET b = 'two.2' WHERE a=2;
+} {
+  REPLACE
+} { SELECT * FROM t1 } {1 one 2 two.2 3 three}
+
+do_rebase_test 2.1.3 {
+  DELETE FROM t1 WHERE a=3;
+} {
+  DELETE FROM t1 WHERE a=3;
+} {
+  OMIT
+} { SELECT * FROM t1 } {1 one 2 two}
+
+do_rebase_test 2.1.4 {
+  DELETE FROM t1 WHERE a=1;
+} {
+  UPDATE t1 SET b='one.2' WHERE a=1
+} {
+  OMIT
+} { SELECT * FROM t1 } {2 two 3 three}
+
+#do_rebase_test 2.1.5 {
+  #DELETE FROM t1 WHERE a=1;
+#} {
+  #UPDATE t1 SET b='one.2' WHERE a=1
+#} {
+  #REPLACE
+#} { SELECT * FROM t1 } {2 two 3 three}
+
+do_rebase_test 2.1.6 {
+  UPDATE t1 SET b='three.1' WHERE a=3;
+} {
+  DELETE FROM t1 WHERE a=3;
+} {
+  OMIT
+} { SELECT * FROM t1 } {1 one 2 two 3 three.1}
+
+do_rebase_test 2.1.7 {
+  UPDATE t1 SET b='three.1' WHERE a=3;
+} {
+  DELETE FROM t1 WHERE a=3;
+} {
+  REPLACE
+} { SELECT * FROM t1 } {1 one 2 two}
 
 finish_test
+
index ad898e8844cf0a812ba78c2437e4d3d0a7cd4f89..45803c7b2c63fa994d33c515783cdbcbe9cdea1e 100644 (file)
@@ -4278,10 +4278,18 @@ static int sessionChangesetApply(
       sqlite3_finalize(sApply.pUpdate); 
       sqlite3_finalize(sApply.pInsert);
       sqlite3_finalize(sApply.pSelect);
-      memset(&sApply, 0, sizeof(sApply));
       sApply.db = db;
+      sApply.pDelete = 0;
+      sApply.pUpdate = 0;
+      sApply.pInsert = 0;
+      sApply.pSelect = 0;
+      sApply.nCol = 0;
+      sApply.azCol = 0;
+      sApply.abPK = 0;
+      sApply.bStat1 = 0;
       sApply.bDeferConstraints = 1;
       sApply.bRebaseStarted = 0;
+      memset(&sApply.constraints, 0, sizeof(SessionBuffer));
 
       /* If an xFilter() callback was specified, invoke it now. If the 
       ** xFilter callback returns zero, skip this table. If it returns
@@ -4658,7 +4666,6 @@ static int sessionChangesetToHash(
   int rc = SQLITE_OK;
   SessionTable *pTab = 0;
 
-
   while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
     const char *zNew;
     int nCol;
@@ -5010,9 +5017,12 @@ static void sessionAppendRecordMerge(
           pOut += nn1;
         }
       }
-      a1 += n1;
-      a2 += n2;
+      a1 += nn1;
+      a2 += nn2;
     }
+
+    pBuf->nBuf = pOut-pBuf->aBuf;
+    assert( pBuf->nBuf<=pBuf->nAlloc );
   }
 }
 
@@ -5031,7 +5041,7 @@ static int sessionRebase(
   SessionTable *pTab = 0;
   SessionBuffer sOut = {0,0,0};
 
-  while( SQLITE_OK==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){
+  while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){
     SessionChange *pChange = 0;
 
     if( bNew ){
@@ -5078,8 +5088,11 @@ static int sessionRebase(
             if( pIter->op==SQLITE_INSERT ){
               sessionAppendBlob(&sOut, aRec, nRec, &rc);
             }else{
+              u8 *pCsr = aRec;
+              sessionSkipRecord(&pCsr, pIter->nCol);
               sessionAppendRecordMerge(&sOut, pIter->nCol, 1,
-                  aRec, nRec, pChange->aRecord, pChange->nRecord, &rc
+                  pCsr, nRec-(pCsr-aRec), 
+                  pChange->aRecord, pChange->nRecord, &rc
               );
             }
           }
@@ -5143,6 +5156,8 @@ int sqlite3rebaser_create(sqlite3_rebaser **ppNew){
   pNew = sqlite3_malloc(sizeof(sqlite3_rebaser));
   if( pNew==0 ){
     rc = SQLITE_NOMEM;
+  }else{
+    memset(pNew, 0, sizeof(sqlite3_rebaser));
   }
   *ppNew = pNew;
   return rc;
@@ -5208,7 +5223,7 @@ int sqlite3rebaser_rebase_strm(
 /* 
 ** Destroy a rebaser object 
 */
-void sqlite3rebaser_destroy(sqlite3_rebaser *p){
+void sqlite3rebaser_delete(sqlite3_rebaser *p){
   if( p ){
     sessionDeleteTable(p->grp.pList);
     sqlite3_free(p);
index a7281bd4e7b11d25c121605cc57b9e23f3198e14..ee002b008f5766fe5bbfc01f7a8be1d63c06b2ce 100644 (file)
@@ -1235,7 +1235,7 @@ int sqlite3rebaser_rebase(
 );
 
 /* Destroy a rebaser object */
-void sqlite3rebaser_destroy(sqlite3_rebaser *p); 
+void sqlite3rebaser_delete(sqlite3_rebaser *p); 
 
 /*
 ** CAPI3REF: Streaming Versions of API functions.
index 7b08267b537610e8059215b8a2eefe587338a4d4..bdd144b5fc22b81a2d7c2c8c9f1a5973f4f97761 100644 (file)
 #  endif
 #endif
 
+#ifndef SQLITE_AMALGAMATION
+  typedef unsigned char u8;
+#endif
+
 typedef struct TestSession TestSession;
 struct TestSession {
   sqlite3_session *pSession;
@@ -1063,6 +1067,125 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
   return TCL_OK;
 }
 
+/*
+** tclcmd: CMD configure REBASE-BLOB
+** tclcmd: CMD rebase CHANGESET
+** tclcmd: CMD delete
+*/
+static int SQLITE_TCLAPI test_rebaser_cmd(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  struct RebaseSubcmd {
+    const char *zSub;
+    int nArg;
+    const char *zMsg;
+    int iSub;
+  } aSub[] = {
+    { "configure",    1, "REBASE-BLOB" }, /* 0 */
+    { "delete",       0, ""            }, /* 1 */
+    { "rebase",       1, "CHANGESET"   }, /* 2 */
+    { 0 }
+  };
+
+  sqlite3_rebaser *p = (sqlite3_rebaser*)clientData;
+  int iSub;
+  int rc;
+
+  if( objc<2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIndexFromObjStruct(interp, 
+      objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
+  );
+  if( rc!=TCL_OK ) return rc;
+  if( objc!=2+aSub[iSub].nArg ){
+    Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
+    return TCL_ERROR;
+  }
+
+  assert( iSub==0 || iSub==1 || iSub==2 );
+  assert( rc==SQLITE_OK );
+  switch( iSub ){
+    case 0: {   /* configure */
+      int nRebase = 0;
+      unsigned char *pRebase = Tcl_GetByteArrayFromObj(objv[2], &nRebase);
+      rc = sqlite3rebaser_configure(p, nRebase, pRebase);
+      break;
+    }
+
+    case 1:     /* delete */
+      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
+      break;
+
+    default: {  /* rebase */
+      TestStreamInput sStr;                 /* Input stream */
+      TestSessionsBlob sOut;                /* Output blob */
+
+      memset(&sStr, 0, sizeof(sStr));
+      memset(&sOut, 0, sizeof(sOut));
+      sStr.aData = Tcl_GetByteArrayFromObj(objv[2], &sStr.nData);
+      sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
+
+      if( sStr.nStream ){
+        rc = sqlite3rebaser_rebase_strm(p, 
+            testStreamInput, (void*)&sStr,
+            testStreamOutput, (void*)&sOut
+        );
+      }else{
+        rc = sqlite3rebaser_rebase(p, sStr.nData, sStr.aData, &sOut.n, &sOut.p);
+      }
+
+      if( rc==SQLITE_OK ){
+        Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(sOut.p, sOut.n));
+      }
+      sqlite3_free(sOut.p);
+      break;
+    }
+  }
+
+  if( rc!=SQLITE_OK ){
+    return test_session_error(interp, rc, 0);
+  }
+  return TCL_OK;
+}
+
+static void SQLITE_TCLAPI test_rebaser_del(void *clientData){
+  sqlite3_rebaser *p = (sqlite3_rebaser*)clientData;
+  sqlite3rebaser_delete(p);
+}
+
+/*
+** tclcmd: sqlite3rebaser_create NAME
+*/
+static int SQLITE_TCLAPI test_sqlite3rebaser_create(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int rc;
+  sqlite3_rebaser *pNew = 0;
+  if( objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "NAME");
+    return SQLITE_ERROR;
+  }
+
+  rc = sqlite3rebaser_create(&pNew);
+  if( rc!=SQLITE_OK ){
+    return test_session_error(interp, rc, 0);
+  }
+
+  Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]), test_rebaser_cmd,
+      (ClientData)pNew, test_rebaser_del
+  );
+  Tcl_SetObjResult(interp, objv[1]);
+  return TCL_OK;
+}
+
 int TestSession_Init(Tcl_Interp *interp){
   struct Cmd {
     const char *zCmd;
@@ -1077,6 +1200,7 @@ int TestSession_Init(Tcl_Interp *interp){
     { "sqlite3changeset_apply_replace_all", 
       test_sqlite3changeset_apply_replace_all },
     { "sql_exec_changeset", test_sql_exec_changeset },
+    { "sqlite3rebaser_create", test_sqlite3rebaser_create },
   };
   int i;
 
index b887be3c0afdbcdd17da026b73cb7f6d68266fc8..4948fb7f5397523c222214eb9cd3ca47418f914d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\slargely\suntested\sAPIs\sfor\srebasing\schangesets.
-D 2018-03-14T21:06:58.004
+C Add\ssimple\stests\sfor\sthe\ssessions\smodule\srebase\sAPI.
+D 2018-03-15T19:25:40.859
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
@@ -400,12 +400,12 @@ F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28
 F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
 F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
-F ext/session/sessionrebase.test b4ac7545e3c69deaeab061c2bf36ad9e99aa6c38db94c340d7e48a230a9d4be8
+F ext/session/sessionrebase.test d3a33c733e5564afe517252167d8f456a04601b047246d85f1e84bf319c2897f
 F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
 F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
-F ext/session/sqlite3session.c 16561ad7eb8270bd3d2ee42c434043e68831bbd452fbea82d83922a1066a7cc8
-F ext/session/sqlite3session.h 74ba48151f3593a66a975ac095d7b53efa6c1e12fe83a903e10bf8d85a1429dd
-F ext/session/test_session.c 8c04dc8cada82bd4e12f18ada3e35b56a8fd4d8dee7caac324ae28091c2b492f
+F ext/session/sqlite3session.c 94b960a94d5e6b2117215a7b1057b3db74ca1222dded2a94588f8ccac5a7d929
+F ext/session/sqlite3session.h 8cb9992411344b9e906a394d2213f58da7b3942ae57e7936d1ec3fe26277dfc0
+F ext/session/test_session.c f253742ea01b089326f189b5ae15a5b55c1c9e97452e4a195ee759ba51b404d5
 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
@@ -1713,7 +1713,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 445bfe977d9f3a891e08ef33237862ed047fe83e134ef3ed8b47ee0f5abd8cd6
-R 485a23056d6edbdb25721aa9069ac291
+P 39915b683b3f8d3bf872af1dede96bf2818b488a8638a1d248395023fc4bd0ef
+R 749942968b245595723def17d4b1a08a
 U dan
-Z e2563dee69381fb6fb02a6ddaa823fec
+Z 85fdd8cb2cf7c970dbbe7369d1e2a257
index 7b1553cdcdf3b7277b70bf9bf84ad3aa1f04bd4c..02df08f087d7e155cd8cb79f69e5b2dd71f582f6 100644 (file)
@@ -1 +1 @@
-39915b683b3f8d3bf872af1dede96bf2818b488a8638a1d248395023fc4bd0ef
\ No newline at end of file
+cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211
\ No newline at end of file