Update the changesetfuzz program to fuzz changeset schemas as well as data.

FossilOrigin-Name: 141a93c843d501d8bb640228645ead0a83870c1c11e9d4b07ed24b296c69a0b8
This commit is contained in:
dan 2018-11-06 20:08:03 +00:00
parent f095a1affb
commit 005d4c61c1
3 changed files with 209 additions and 52 deletions

View File

@ -62,11 +62,35 @@
** (as both the old.* and new.* records of the new UPDATE change). If an
** UPDATE is changed to a DELETE or INSERT, the new.* record is discarded
** and any "undefined" fields replaced with pseudo-randomly generated
** values.
** values.
**
** 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"
@ -76,18 +100,26 @@
#include <assert.h>
#include <ctype.h>
#define FUZZ_VALUE_SUB 1 /* Replace one value with a copy of another */
#define FUZZ_VALUE_MOD 2 /* Modify content by 1 bit */
#define FUZZ_VALUE_RND 3 /* Replace with pseudo-random value */
#define FUZZ_VALUE_SUB 1 /* Replace one value with a copy of another */
#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;
*(pOut++) = *(p++);
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( eNew==eType || eType!=SQLITE_UPDATE || iRec==0 ){
fuzzChangeSize(pCopy, &sz);
memcpy(pOut, pCopy, sz);
pOut += sz;
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 i;
int j;
int nRep = 1;
/* Output a table header */
pOut++[0] = 'T';
pOut += fuzzPutVarint(pOut, pGrp->nCol);
memcpy(pOut, pGrp->aPK, pGrp->nCol);
pOut += pGrp->nCol;
memcpy(pOut, pGrp->zTab, nTab);
pOut += nTab;
/* 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;
}
}
/* Output the change array */
p = pGrp->aChange;
for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){
rc = fuzzCopyChange(pParse, pGrp, &change, &p, &pOut);
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, 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. */
pSaved = pOut;
for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){
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;
}

View File

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

View File

@ -1 +1 @@
81ac8745faac0bda8d68ac113f1938f0e25208642e8ceb2af452680086454cb5
141a93c843d501d8bb640228645ead0a83870c1c11e9d4b07ed24b296c69a0b8