Update the changesetfuzz program to fuzz changeset schemas as well as data.
FossilOrigin-Name: 141a93c843d501d8bb640228645ead0a83870c1c11e9d4b07ed24b296c69a0b8
This commit is contained in:
parent
f095a1affb
commit
005d4c61c1
@ -67,6 +67,30 @@
|
||||
** 7. An UPDATE change that modifies N table columns may be modified so
|
||||
** that it updates N-1 columns, so long as (N>1).
|
||||
**
|
||||
** 8. The "indirect" flag may be toggled for any change.
|
||||
**
|
||||
** Entire group of changes may also be operated on:
|
||||
**
|
||||
** 9. Duplicate an existing group.
|
||||
**
|
||||
** 10. Remove an existing group.
|
||||
**
|
||||
** 11. The positions of two groups may be exchanged.
|
||||
**
|
||||
** There are also schema changes:
|
||||
**
|
||||
** 12. A non-PK column may be added to a table. In this case a NULL
|
||||
** value is appended to all records.
|
||||
**
|
||||
** 13. A PK column may be added to a table. In this case a non-NULL
|
||||
** value is appended to all INSERT, DELETE and UPDATE old.* records.
|
||||
** An "undefined" is appended to new.* UPDATE records.
|
||||
**
|
||||
** 14. A column may be removed from a table. In this case the corresponding
|
||||
** field is removed from all records. In cases where this leaves an UPDATE
|
||||
** with no non-PK, non-undefined fields, the entire change is removed. If
|
||||
** the table has more than on PK column, the column removed may be part of
|
||||
** the PK.
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
@ -80,14 +104,22 @@
|
||||
#define FUZZ_VALUE_MOD 2 /* Modify content by 1 bit */
|
||||
#define FUZZ_VALUE_RND 3 /* Replace with pseudo-random value */
|
||||
|
||||
#define FUZZ_CHANGE_DUP 4
|
||||
#define FUZZ_CHANGE_DEL 5
|
||||
#define FUZZ_CHANGE_TYPE 6
|
||||
#define FUZZ_CHANGE_FIELD 7
|
||||
#define FUZZ_CHANGE_DUP 4 /* Duplicate an existing change */
|
||||
#define FUZZ_CHANGE_DEL 5 /* Completely remove one change */
|
||||
#define FUZZ_CHANGE_TYPE 6 /* Change the type of one change */
|
||||
#define FUZZ_CHANGE_FIELD 7 /* Change an UPDATE to modify fewer columns */
|
||||
#define FUZZ_CHANGE_INDIRECT 8 /* Toggle the "indirect" flag of a change */
|
||||
|
||||
#define FUZZ_GROUP_DUP 9 /* Duplicate a change group */
|
||||
#define FUZZ_GROUP_DEL 10 /* Delete an entire change group */
|
||||
#define FUZZ_GROUP_SWAP 11 /* Exchange the position of two groups */
|
||||
|
||||
#define FUZZ_COLUMN_ADD 12 /* Add column to table definition */
|
||||
#define FUZZ_COLUMN_ADDPK 13 /* Add PK column to table definition */
|
||||
#define FUZZ_COLUMN_DEL 14 /* Remove column from table definition */
|
||||
|
||||
#if 0
|
||||
#define FUZZ_COLUMN_ADD 1 /* Add column to table definition */
|
||||
#define FUZZ_COLUMN_DEL 2 /* Remove column from table definition */
|
||||
#define FUZZ_PK_ADD 3 /* Add a PK column */
|
||||
#define FUZZ_PK_DEL 4 /* Delete a PK column */
|
||||
#define FUZZ_NAME_CHANGE 5 /* Change a table name */
|
||||
@ -274,8 +306,8 @@ typedef struct FuzzChange FuzzChange;
|
||||
struct FuzzChangeset {
|
||||
FuzzChangesetGroup **apGroup; /* Array of groups in changeset */
|
||||
int nGroup; /* Number of items in list pGroup */
|
||||
u8 *aVal[FUZZER_AVAL_SZ]; /* Array of first few values in changeset */
|
||||
int nVal; /* Number of used slots in aVal[] */
|
||||
u8 **apVal; /* Array of all values in changeset */
|
||||
int nVal; /* Number of used slots in apVal[] */
|
||||
int nChange; /* Number of changes in changeset */
|
||||
int nUpdate; /* Number of UPDATE changes in changeset */
|
||||
};
|
||||
@ -287,7 +319,6 @@ struct FuzzChangesetGroup {
|
||||
u8 *aChange; /* Buffer containing array of changes */
|
||||
int szChange; /* Size of buffer aChange[] in bytes */
|
||||
int nChange; /* Number of changes in buffer aChange[] */
|
||||
FuzzChangesetGroup *pNextGroup;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -295,11 +326,12 @@ struct FuzzChangesetGroup {
|
||||
*/
|
||||
struct FuzzChange {
|
||||
int eType; /* One of the FUZZ_* constants above */
|
||||
int iChange; /* Change to modify */
|
||||
int iChange; /* Change or UPDATE to modify */
|
||||
int iGroup; /* Group to modify */
|
||||
int iDelete; /* Field to remove (FUZZ_COLUMN_DEL) */
|
||||
u8 *pSub1;
|
||||
u8 *pSub2;
|
||||
u8 aSub[128]; /* Substitute value */
|
||||
|
||||
int iCurrent; /* Current change number */
|
||||
};
|
||||
|
||||
@ -444,9 +476,13 @@ static int fuzzParseRecord(u8 **ppRec, u8 *pEnd, FuzzChangeset *pParse){
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nCol && p<pEnd; i++){
|
||||
int sz;
|
||||
if( pParse->nVal<FUZZER_AVAL_SZ ){
|
||||
pParse->aVal[pParse->nVal++] = p;
|
||||
if( (pParse->nVal & (pParse->nVal-1))==0 ){
|
||||
int nNew = pParse->nVal ? pParse->nVal*2 : 4;
|
||||
u8 **apNew = (u8**)sqlite3_realloc(pParse->apVal, nNew*sizeof(u8*));
|
||||
if( apNew==0 ) return SQLITE_NOMEM;
|
||||
pParse->apVal = apNew;
|
||||
}
|
||||
pParse->apVal[pParse->nVal++] = p;
|
||||
rc = fuzzChangeSize(p, &sz);
|
||||
p += sz;
|
||||
}
|
||||
@ -627,7 +663,7 @@ static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){
|
||||
int iSub;
|
||||
|
||||
memset(pChange, 0, sizeof(FuzzChange));
|
||||
pChange->eType = fuzzRandomInt(7) + FUZZ_VALUE_SUB;
|
||||
pChange->eType = fuzzRandomInt(14) + FUZZ_VALUE_SUB;
|
||||
|
||||
assert( pChange->eType==FUZZ_VALUE_SUB
|
||||
|| pChange->eType==FUZZ_VALUE_MOD
|
||||
@ -636,23 +672,54 @@ static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){
|
||||
|| pChange->eType==FUZZ_CHANGE_DEL
|
||||
|| pChange->eType==FUZZ_CHANGE_TYPE
|
||||
|| pChange->eType==FUZZ_CHANGE_FIELD
|
||||
|| pChange->eType==FUZZ_CHANGE_INDIRECT
|
||||
|| pChange->eType==FUZZ_GROUP_DUP
|
||||
|| pChange->eType==FUZZ_GROUP_DEL
|
||||
|| pChange->eType==FUZZ_GROUP_SWAP
|
||||
|| pChange->eType==FUZZ_COLUMN_ADD
|
||||
|| pChange->eType==FUZZ_COLUMN_ADDPK
|
||||
|| pChange->eType==FUZZ_COLUMN_DEL
|
||||
);
|
||||
|
||||
pChange->iGroup = fuzzRandomInt(pParse->nGroup);
|
||||
pChange->iChange = fuzzRandomInt(pParse->nChange);
|
||||
if( pChange->eType==FUZZ_CHANGE_FIELD ){
|
||||
if( pParse->nUpdate==0 ) return -1;
|
||||
pChange->iChange = fuzzRandomInt(pParse->nUpdate);
|
||||
}
|
||||
|
||||
pChange->iDelete = -1;
|
||||
if( pChange->eType==FUZZ_COLUMN_DEL ){
|
||||
FuzzChangesetGroup *pGrp = pParse->apGroup[pChange->iGroup];
|
||||
int i;
|
||||
pChange->iDelete = fuzzRandomInt(pGrp->nCol);
|
||||
for(i=pGrp->nCol-1; i>=0; i--){
|
||||
if( pGrp->aPK[i] && pChange->iDelete!=i ) break;
|
||||
}
|
||||
if( i<0 ) return -1;
|
||||
}
|
||||
|
||||
if( pChange->eType==FUZZ_GROUP_SWAP ){
|
||||
FuzzChangesetGroup *pGrp;
|
||||
int iGrp = pChange->iGroup;
|
||||
if( pParse->nGroup==1 ) return -1;
|
||||
while( iGrp==pChange->iGroup ){
|
||||
iGrp = fuzzRandomInt(pParse->nGroup);
|
||||
}
|
||||
pGrp = pParse->apGroup[pChange->iGroup];
|
||||
pParse->apGroup[pChange->iGroup] = pParse->apGroup[iGrp];
|
||||
pParse->apGroup[iGrp] = pGrp;
|
||||
}
|
||||
|
||||
if( pChange->eType==FUZZ_VALUE_SUB
|
||||
|| pChange->eType==FUZZ_VALUE_MOD
|
||||
|| pChange->eType==FUZZ_VALUE_RND
|
||||
){
|
||||
iSub = fuzzRandomInt(pParse->nVal);
|
||||
pChange->pSub1 = pParse->aVal[iSub];
|
||||
pChange->pSub1 = pParse->apVal[iSub];
|
||||
if( pChange->eType==FUZZ_VALUE_SUB ){
|
||||
iSub = fuzzRandomInt(pParse->nVal);
|
||||
pChange->pSub2 = pParse->aVal[iSub];
|
||||
pChange->pSub2 = pParse->apVal[iSub];
|
||||
}else{
|
||||
pChange->pSub2 = pChange->aSub;
|
||||
}
|
||||
@ -724,16 +791,18 @@ static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){
|
||||
|
||||
static int fuzzCopyChange(
|
||||
FuzzChangeset *pParse,
|
||||
FuzzChangesetGroup *pGrp,
|
||||
int iGrp,
|
||||
FuzzChange *pFuzz,
|
||||
u8 **pp, u8 **ppOut /* IN/OUT: Input and output pointers */
|
||||
){
|
||||
FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
|
||||
u8 *p = *pp;
|
||||
u8 *pOut = *ppOut;
|
||||
u8 eType = p++[0];
|
||||
int iRec;
|
||||
int nRec = (eType==SQLITE_UPDATE ? 2 : 1);
|
||||
int iUndef = -1;
|
||||
int nUpdate = 0;
|
||||
|
||||
u8 eNew = eType;
|
||||
if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_TYPE ){
|
||||
@ -774,9 +843,16 @@ static int fuzzCopyChange(
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the change type and indirect flag */
|
||||
/* Copy the change type and indirect flag. If the fuzz mode is
|
||||
** FUZZ_CHANGE_INDIRECT, and the current change is the one selected for
|
||||
** fuzzing, invert the indirect flag. */
|
||||
*(pOut++) = eNew;
|
||||
if( pFuzz->eType==FUZZ_CHANGE_INDIRECT && pFuzz->iCurrent==pFuzz->iChange ){
|
||||
*(pOut++) = !(*(p++));
|
||||
}else{
|
||||
*(pOut++) = *(p++);
|
||||
}
|
||||
|
||||
for(iRec=0; iRec<nRec; iRec++){
|
||||
int i;
|
||||
for(i=0; i<pGrp->nCol; i++){
|
||||
@ -793,7 +869,7 @@ static int fuzzCopyChange(
|
||||
|
||||
if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){
|
||||
while( pCopy[0]==0x00 ){
|
||||
pCopy = pParse->aVal[fuzzRandomInt(pParse->nVal)];
|
||||
pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
|
||||
}
|
||||
}else if( p[0]==0x00 && pCopy[0]!=0x00 ){
|
||||
return -1;
|
||||
@ -801,15 +877,37 @@ static int fuzzCopyChange(
|
||||
if( pGrp->aPK[i]>0 && pCopy[0]==0x05 ) return -1;
|
||||
}
|
||||
|
||||
if( pFuzz->iGroup!=iGrp || i!=pFuzz->iDelete ){
|
||||
if( eNew==eType || eType!=SQLITE_UPDATE || iRec==0 ){
|
||||
fuzzChangeSize(pCopy, &sz);
|
||||
memcpy(pOut, pCopy, sz);
|
||||
pOut += sz;
|
||||
nUpdate += (pGrp->aPK[i]==0 && pCopy[0]!=0x00);
|
||||
}
|
||||
}
|
||||
|
||||
fuzzChangeSize(p, &sz);
|
||||
p += sz;
|
||||
}
|
||||
|
||||
if( iGrp==pFuzz->iGroup ){
|
||||
if( pFuzz->eType==FUZZ_COLUMN_ADD ){
|
||||
*(pOut++) = 0x05;
|
||||
}else if( pFuzz->eType==FUZZ_COLUMN_ADDPK ){
|
||||
if( iRec==1 ){
|
||||
*(pOut++) = 0x00;
|
||||
}else{
|
||||
u8 *pNew;
|
||||
int szNew;
|
||||
do {
|
||||
pNew = pParse->apVal[fuzzRandomInt(pParse->nVal)];
|
||||
}while( pNew[0]==0x00 || pNew[0]==0x05 );
|
||||
fuzzChangeSize(pNew, &szNew);
|
||||
memcpy(pOut, pNew, szNew);
|
||||
pOut += szNew;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pFuzz->iCurrent==pFuzz->iChange ){
|
||||
@ -818,8 +916,8 @@ static int fuzzCopyChange(
|
||||
memcpy(pOut, *ppOut, nByte);
|
||||
pOut += nByte;
|
||||
}
|
||||
|
||||
if( pFuzz->eType==FUZZ_CHANGE_DEL ){
|
||||
if( pGrp->nChange==1 ) return -1;
|
||||
pOut = *ppOut;
|
||||
}
|
||||
if( eNew!=eType && eNew==SQLITE_UPDATE ){
|
||||
@ -838,6 +936,15 @@ static int fuzzCopyChange(
|
||||
}
|
||||
}
|
||||
|
||||
/* If a column is being deleted from this group, and this change was an
|
||||
** UPDATE, and there are now no non-PK, non-undefined columns in the
|
||||
** change, remove it altogether. */
|
||||
if( pFuzz->eType==FUZZ_COLUMN_DEL && pFuzz->iGroup==iGrp
|
||||
&& eType==SQLITE_UPDATE && nUpdate==0
|
||||
){
|
||||
pOut = *ppOut;
|
||||
}
|
||||
|
||||
*pp = p;
|
||||
*ppOut = pOut;
|
||||
pFuzz->iCurrent += (eType==SQLITE_UPDATE || pFuzz->eType!=FUZZ_CHANGE_FIELD);
|
||||
@ -859,21 +966,73 @@ static int fuzzDoOneFuzz(
|
||||
for(iGrp=0; rc==SQLITE_OK && iGrp<pParse->nGroup; iGrp++){
|
||||
FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
|
||||
int nTab = strlen(pGrp->zTab) + 1;
|
||||
u8 *p;
|
||||
int j;
|
||||
int nRep = 1;
|
||||
|
||||
/* If this is the group to delete for a FUZZ_GROUP_DEL change, jump to
|
||||
** the next group. Unless this is the only group in the changeset - in
|
||||
** that case this change cannot be applied.
|
||||
**
|
||||
** Or, if this is a FUZZ_GROUP_DUP, set nRep to 2 to output two
|
||||
** copies of the group. */
|
||||
if( change.iGroup==iGrp ){
|
||||
if( change.eType==FUZZ_GROUP_DEL ){
|
||||
if( pParse->nGroup==1 ) rc = -1;
|
||||
continue;
|
||||
}
|
||||
else if( change.eType==FUZZ_GROUP_DUP ){
|
||||
nRep = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0; j<nRep; j++){
|
||||
int i;
|
||||
u8 *pSaved;
|
||||
u8 *p = pGrp->aChange;
|
||||
int nCol = pGrp->nCol;
|
||||
int iPKDel = 0;
|
||||
if( iGrp==change.iGroup ){
|
||||
if( change.eType==FUZZ_COLUMN_ADD
|
||||
|| change.eType==FUZZ_COLUMN_ADDPK
|
||||
){
|
||||
nCol++;
|
||||
}else if( change.eType==FUZZ_COLUMN_DEL ){
|
||||
nCol--;
|
||||
iPKDel = pGrp->aPK[change.iDelete];
|
||||
}
|
||||
}
|
||||
|
||||
/* Output a table header */
|
||||
pOut++[0] = 'T';
|
||||
pOut += fuzzPutVarint(pOut, pGrp->nCol);
|
||||
memcpy(pOut, pGrp->aPK, pGrp->nCol);
|
||||
pOut += pGrp->nCol;
|
||||
pOut += fuzzPutVarint(pOut, nCol);
|
||||
|
||||
for(i=0; i<pGrp->nCol; i++){
|
||||
if( iGrp!=change.iGroup || i!=change.iDelete ){
|
||||
u8 v = pGrp->aPK[i];
|
||||
if( iPKDel && v>iPKDel ) v--;
|
||||
*(pOut++) = v;
|
||||
}
|
||||
}
|
||||
if( nCol>pGrp->nCol ){
|
||||
if( change.eType==FUZZ_COLUMN_ADD ){
|
||||
*(pOut++) = 0x00;
|
||||
}else{
|
||||
u8 max = 0;
|
||||
for(i=0; i<pGrp->nCol; i++){
|
||||
if( pGrp->aPK[i]>max ) max = pGrp->aPK[i];
|
||||
}
|
||||
*(pOut++) = max+1;
|
||||
}
|
||||
}
|
||||
memcpy(pOut, pGrp->zTab, nTab);
|
||||
pOut += nTab;
|
||||
|
||||
/* Output the change array */
|
||||
p = pGrp->aChange;
|
||||
/* Output the change array. */
|
||||
pSaved = pOut;
|
||||
for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){
|
||||
rc = fuzzCopyChange(pParse, pGrp, &change, &p, &pOut);
|
||||
rc = fuzzCopyChange(pParse, iGrp, &change, &p, &pOut);
|
||||
}
|
||||
if( pOut==pSaved ) rc = -1;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@ -916,7 +1075,7 @@ int main(int argc, char **argv){
|
||||
fuzzRandomSeed((unsigned int)iSeed);
|
||||
for(i=0; rc==SQLITE_OK && i<nRepeat; i++){
|
||||
char *zOut = sqlite3_mprintf("%s-%d", zInput, i);
|
||||
fuzzDoOneFuzz(zOut, pBuf, &changeset);
|
||||
rc = fuzzDoOneFuzz(zOut, pBuf, &changeset);
|
||||
sqlite3_free(zOut);
|
||||
}
|
||||
fuzzFree(pBuf);
|
||||
@ -927,6 +1086,7 @@ int main(int argc, char **argv){
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "error while processing changeset: %d\n", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
15
manifest
15
manifest
@ -1,5 +1,5 @@
|
||||
C Add\spreliminary\sversion\sof\s"changesetfuzz"\sprogram.\sFor\sfuzzing\schangeset\sdata\nwithout\screating\scorrupt\schangesets.
|
||||
D 2018-11-05T20:37:33.019
|
||||
C Update\sthe\schangesetfuzz\sprogram\sto\sfuzz\schangeset\sschemas\sas\swell\sas\sdata.
|
||||
D 2018-11-06T20:08:03.912
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in d298b31769d4c737887102462cd45684786b09f2a626a80b3e413790fb436219
|
||||
@ -391,7 +391,7 @@ F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
|
||||
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
|
||||
F ext/session/changesetfuzz.c 1e56326c4b76a6f1802ca73629409ce1eb10d60a388a43d8e7c74b33b1f4725c
|
||||
F ext/session/changesetfuzz.c 27aec2e060043eb7377d7075e20959c85c57a41f4f72c30f8bace12cc9b9af69
|
||||
F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e
|
||||
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
|
||||
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
|
||||
@ -1777,10 +1777,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 11d98414eac467affb0b3cf0c7e5cc3d43184fc2b6e7e898bb5277b51ea9e1fa
|
||||
R 147d5d75296309ad726c7c64dc2b1650
|
||||
T *branch * changesetfuzz
|
||||
T *sym-changesetfuzz *
|
||||
T -sym-trunk *
|
||||
P 81ac8745faac0bda8d68ac113f1938f0e25208642e8ceb2af452680086454cb5
|
||||
R 2ce6a540d3c541564d5607a6269445d4
|
||||
U dan
|
||||
Z e5d17ad373a9d021c09070dfd9d8422e
|
||||
Z 7a3bd8208ab7b3ca6eb82773978332aa
|
||||
|
@ -1 +1 @@
|
||||
81ac8745faac0bda8d68ac113f1938f0e25208642e8ceb2af452680086454cb5
|
||||
141a93c843d501d8bb640228645ead0a83870c1c11e9d4b07ed24b296c69a0b8
|
Loading…
Reference in New Issue
Block a user