Add simple tests for the sessions module rebase API.
FossilOrigin-Name: cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211
This commit is contained in:
parent
c0a499eaad
commit
f1b40e8305
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
18
manifest
18
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
|
||||
|
@ -1 +1 @@
|
||||
39915b683b3f8d3bf872af1dede96bf2818b488a8638a1d248395023fc4bd0ef
|
||||
cf0d1abb44cf170d747e9c11f49ec03a29f00ab4821c613ca1e05b883a568211
|
Loading…
Reference in New Issue
Block a user