Add simple tests for the sessions module rebase API.

FossilOrigin-Name: cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211
This commit is contained in:
dan 2018-03-15 19:25:40 +00:00
parent c0a499eaad
commit f1b40e8305
6 changed files with 283 additions and 18 deletions

View 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

View 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);

View 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.

View File

@ -14,6 +14,10 @@
# 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;

View File

@ -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

View File

@ -1 +1 @@
39915b683b3f8d3bf872af1dede96bf2818b488a8638a1d248395023fc4bd0ef
cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211