modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/lsm1/lsm-test/lsmtest1.c (about) 1 2 #include "lsmtest.h" 3 4 #define DATA_SEQUENTIAL TEST_DATASOURCE_SEQUENCE 5 #define DATA_RANDOM TEST_DATASOURCE_RANDOM 6 7 typedef struct Datatest1 Datatest1; 8 typedef struct Datatest2 Datatest2; 9 10 /* 11 ** An instance of the following structure contains parameters used to 12 ** customize the test function in this file. Test procedure: 13 ** 14 ** 1. Create a data-source based on the "datasource definition" vars. 15 ** 16 ** 2. Insert nRow key value pairs into the database. 17 ** 18 ** 3. Delete all keys from the database. Deletes are done in the same 19 ** order as the inserts. 20 ** 21 ** During steps 2 and 3 above, after each Datatest1.nVerify inserts or 22 ** deletes, the following: 23 ** 24 ** a. Run Datasource.nTest key lookups and check the results are as expected. 25 ** 26 ** b. If Datasource.bTestScan is true, run a handful (8) of range 27 ** queries (scanning forwards and backwards). Check that the results 28 ** are as expected. 29 ** 30 ** c. Close and reopen the database. Then run (a) and (b) again. 31 */ 32 struct Datatest1 { 33 /* Datasource definition */ 34 DatasourceDefn defn; 35 36 /* Test procedure parameters */ 37 int nRow; /* Number of rows to insert then delete */ 38 int nVerify; /* How often to verify the db contents */ 39 int nTest; /* Number of keys to test (0==all) */ 40 int bTestScan; /* True to do scan tests */ 41 }; 42 43 /* 44 ** An instance of the following data structure is used to describe the 45 ** second type of test case in this file. The chief difference between 46 ** these tests and those described by Datatest1 is that these tests also 47 ** experiment with range-delete operations. Tests proceed as follows: 48 ** 49 ** 1. Open the datasource described by Datatest2.defn. 50 ** 51 ** 2. Open a connection on an empty database. 52 ** 53 ** 3. Do this Datatest2.nIter times: 54 ** 55 ** a) Insert Datatest2.nWrite key-value pairs from the datasource. 56 ** 57 ** b) Select two pseudo-random keys and use them as the start 58 ** and end points of a range-delete operation. 59 ** 60 ** c) Verify that the contents of the database are as expected (see 61 ** below for details). 62 ** 63 ** d) Close and then reopen the database handle. 64 ** 65 ** e) Verify that the contents of the database are still as expected. 66 ** 67 ** The inserts and range deletes are run twice - once on the database being 68 ** tested and once using a control system (sqlite3, kc etc. - something that 69 ** works). In order to verify that the contents of the db being tested are 70 ** correct, the test runs a bunch of scans and lookups on both the test and 71 ** control databases. If the results are the same, the test passes. 72 */ 73 struct Datatest2 { 74 DatasourceDefn defn; 75 int nRange; 76 int nWrite; /* Number of writes per iteration */ 77 int nIter; /* Total number of iterations to run */ 78 }; 79 80 /* 81 ** Generate a unique name for the test case pTest with database system 82 ** zSystem. 83 */ 84 static char *getName(const char *zSystem, int bRecover, Datatest1 *pTest){ 85 char *zRet; 86 char *zData; 87 zData = testDatasourceName(&pTest->defn); 88 zRet = testMallocPrintf("data.%s.%s.rec=%d.%d.%d", 89 zSystem, zData, bRecover, pTest->nRow, pTest->nVerify 90 ); 91 testFree(zData); 92 return zRet; 93 } 94 95 int testControlDb(TestDb **ppDb){ 96 #ifdef HAVE_KYOTOCABINET 97 return tdb_open("kyotocabinet", "tmp.db", 1, ppDb); 98 #else 99 return tdb_open("sqlite3", "", 1, ppDb); 100 #endif 101 } 102 103 void testDatasourceFetch( 104 TestDb *pDb, /* Database handle */ 105 Datasource *pData, 106 int iKey, 107 int *pRc /* IN/OUT: Error code */ 108 ){ 109 void *pKey; int nKey; /* Database key to query for */ 110 void *pVal; int nVal; /* Expected result of query */ 111 112 testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal); 113 testFetch(pDb, pKey, nKey, pVal, nVal, pRc); 114 } 115 116 /* 117 ** This function is called to test that the contents of database pDb 118 ** are as expected. In this case, expected is defined as containing 119 ** key-value pairs iFirst through iLast, inclusive, from data source 120 ** pData. In other words, a loop like the following could be used to 121 ** construct a database with identical contents from scratch. 122 ** 123 ** for(i=iFirst; i<=iLast; i++){ 124 ** testDatasourceEntry(pData, i, &pKey, &nKey, &pVal, &nVal); 125 ** // insert (pKey, nKey) -> (pVal, nVal) into database 126 ** } 127 ** 128 ** The key domain consists of keys 0 to (nRow-1), inclusive, from 129 ** data source pData. For both scan and lookup tests, keys are selected 130 ** pseudo-randomly from within this set. 131 ** 132 ** This function runs nLookupTest lookup tests and nScanTest scan tests. 133 ** 134 ** A lookup test consists of selecting a key from the domain and querying 135 ** pDb for it. The test fails if the presence of the key and, if present, 136 ** the associated value do not match the expectations defined above. 137 ** 138 ** A scan test involves selecting a key from the domain and running 139 ** the following queries: 140 ** 141 ** 1. Scan all keys equal to or greater than the key, in ascending order. 142 ** 2. Scan all keys equal to or smaller than the key, in descending order. 143 ** 144 ** Additionally, if nLookupTest is greater than zero, the following are 145 ** run once: 146 ** 147 ** 1. Scan all keys in the db, in ascending order. 148 ** 2. Scan all keys in the db, in descending order. 149 ** 150 ** As you would assume, the test fails if the returned values do not match 151 ** expectations. 152 */ 153 void testDbContents( 154 TestDb *pDb, /* Database handle being tested */ 155 Datasource *pData, /* pDb contains data from here */ 156 int nRow, /* Size of key domain */ 157 int iFirst, /* Index of first key from pData in pDb */ 158 int iLast, /* Index of last key from pData in pDb */ 159 int nLookupTest, /* Number of lookup tests to run */ 160 int nScanTest, /* Number of scan tests to run */ 161 int *pRc /* IN/OUT: Error code */ 162 ){ 163 int j; 164 int rc = *pRc; 165 166 if( rc==0 && nScanTest ){ 167 TestDb *pDb2 = 0; 168 169 /* Open a control db (i.e. one that we assume works) */ 170 rc = testControlDb(&pDb2); 171 172 for(j=iFirst; rc==0 && j<=iLast; j++){ 173 void *pKey; int nKey; /* Database key to insert */ 174 void *pVal; int nVal; /* Database value to insert */ 175 testDatasourceEntry(pData, j, &pKey, &nKey, &pVal, &nVal); 176 rc = tdb_write(pDb2, pKey, nKey, pVal, nVal); 177 } 178 179 if( rc==0 ){ 180 int iKey1; 181 int iKey2; 182 void *pKey1; int nKey1; /* Start key */ 183 void *pKey2; int nKey2; /* Final key */ 184 185 iKey1 = testPrngValue((iFirst<<8) + (iLast<<16)) % nRow; 186 iKey2 = testPrngValue((iLast<<8) + (iFirst<<16)) % nRow; 187 testDatasourceEntry(pData, iKey1, &pKey2, &nKey1, 0, 0); 188 pKey1 = testMalloc(nKey1+1); 189 memcpy(pKey1, pKey2, nKey1+1); 190 testDatasourceEntry(pData, iKey2, &pKey2, &nKey2, 0, 0); 191 192 testScanCompare(pDb2, pDb, 0, 0, 0, 0, 0, &rc); 193 testScanCompare(pDb2, pDb, 0, 0, 0, pKey2, nKey2, &rc); 194 testScanCompare(pDb2, pDb, 0, pKey1, nKey1, 0, 0, &rc); 195 testScanCompare(pDb2, pDb, 0, pKey1, nKey1, pKey2, nKey2, &rc); 196 testScanCompare(pDb2, pDb, 1, 0, 0, 0, 0, &rc); 197 testScanCompare(pDb2, pDb, 1, 0, 0, pKey2, nKey2, &rc); 198 testScanCompare(pDb2, pDb, 1, pKey1, nKey1, 0, 0, &rc); 199 testScanCompare(pDb2, pDb, 1, pKey1, nKey1, pKey2, nKey2, &rc); 200 testFree(pKey1); 201 } 202 tdb_close(pDb2); 203 } 204 205 /* Test some lookups. */ 206 for(j=0; rc==0 && j<nLookupTest; j++){ 207 int iKey; /* Datasource key to test */ 208 void *pKey; int nKey; /* Database key to query for */ 209 void *pVal; int nVal; /* Expected result of query */ 210 211 if( nLookupTest>=nRow ){ 212 iKey = j; 213 }else{ 214 iKey = testPrngValue(j + (iFirst<<8) + (iLast<<16)) % nRow; 215 } 216 217 testDatasourceEntry(pData, iKey, &pKey, &nKey, &pVal, &nVal); 218 if( iFirst>iKey || iKey>iLast ){ 219 pVal = 0; 220 nVal = -1; 221 } 222 223 testFetch(pDb, pKey, nKey, pVal, nVal, &rc); 224 } 225 226 *pRc = rc; 227 } 228 229 /* 230 ** This function should be called during long running test cases to output 231 ** the progress dots (...) to stdout. 232 */ 233 void testCaseProgress(int i, int n, int nDot, int *piDot){ 234 int iDot = *piDot; 235 while( iDot < ( ((nDot*2+1) * i) / (n*2) ) ){ 236 printf("."); 237 fflush(stdout); 238 iDot++; 239 } 240 *piDot = iDot; 241 } 242 243 int testCaseNDot(void){ return 20; } 244 245 #if 0 246 static void printScanCb( 247 void *pCtx, void *pKey, int nKey, void *pVal, int nVal 248 ){ 249 printf("%s\n", (char *)pKey); 250 fflush(stdout); 251 } 252 #endif 253 254 void testReopenRecover(TestDb **ppDb, int *pRc){ 255 if( *pRc==0 ){ 256 const char *zLib = tdb_library_name(*ppDb); 257 const char *zDflt = tdb_default_db(zLib); 258 testCopyLsmdb(zDflt, "bak.db"); 259 testClose(ppDb); 260 testCopyLsmdb("bak.db", zDflt); 261 *pRc = tdb_open(zLib, 0, 0, ppDb); 262 } 263 } 264 265 266 static void doDataTest1( 267 const char *zSystem, /* Database system to test */ 268 int bRecover, 269 Datatest1 *p, /* Structure containing test parameters */ 270 int *pRc /* OUT: Error code */ 271 ){ 272 int i; 273 int iDot; 274 int rc = LSM_OK; 275 Datasource *pData; 276 TestDb *pDb; 277 278 /* Start the test case, open a database and allocate the datasource. */ 279 pDb = testOpen(zSystem, 1, &rc); 280 pData = testDatasourceNew(&p->defn); 281 282 i = 0; 283 iDot = 0; 284 while( rc==LSM_OK && i<p->nRow ){ 285 286 /* Insert some data */ 287 testWriteDatasourceRange(pDb, pData, i, p->nVerify, &rc); 288 i += p->nVerify; 289 290 /* Check that the db content is correct. */ 291 testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc); 292 293 if( bRecover ){ 294 testReopenRecover(&pDb, &rc); 295 }else{ 296 testReopen(&pDb, &rc); 297 } 298 299 /* Check that the db content is still correct. */ 300 testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc); 301 302 /* Update the progress dots... */ 303 testCaseProgress(i, p->nRow, testCaseNDot()/2, &iDot); 304 } 305 306 i = 0; 307 iDot = 0; 308 while( rc==LSM_OK && i<p->nRow ){ 309 310 /* Delete some entries */ 311 testDeleteDatasourceRange(pDb, pData, i, p->nVerify, &rc); 312 i += p->nVerify; 313 314 /* Check that the db content is correct. */ 315 testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc); 316 317 /* Close and reopen the database. */ 318 if( bRecover ){ 319 testReopenRecover(&pDb, &rc); 320 }else{ 321 testReopen(&pDb, &rc); 322 } 323 324 /* Check that the db content is still correct. */ 325 testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc); 326 327 /* Update the progress dots... */ 328 testCaseProgress(i, p->nRow, testCaseNDot()/2, &iDot); 329 } 330 331 /* Free the datasource, close the database and finish the test case. */ 332 testDatasourceFree(pData); 333 tdb_close(pDb); 334 testCaseFinish(rc); 335 *pRc = rc; 336 } 337 338 339 void test_data_1( 340 const char *zSystem, /* Database system name */ 341 const char *zPattern, /* Run test cases that match this pattern */ 342 int *pRc /* IN/OUT: Error code */ 343 ){ 344 Datatest1 aTest[] = { 345 { {DATA_RANDOM, 500,600, 1000,2000}, 1000, 100, 10, 0}, 346 { {DATA_RANDOM, 20,25, 100,200}, 1000, 250, 1000, 1}, 347 { {DATA_RANDOM, 8,10, 100,200}, 1000, 250, 1000, 1}, 348 { {DATA_RANDOM, 8,10, 10,20}, 1000, 250, 1000, 1}, 349 { {DATA_RANDOM, 8,10, 1000,2000}, 1000, 250, 1000, 1}, 350 { {DATA_RANDOM, 8,100, 10000,20000}, 100, 25, 100, 1}, 351 { {DATA_RANDOM, 80,100, 10,20}, 1000, 250, 1000, 1}, 352 { {DATA_RANDOM, 5000,6000, 10,20}, 100, 25, 100, 1}, 353 { {DATA_SEQUENTIAL, 5,10, 10,20}, 1000, 250, 1000, 1}, 354 { {DATA_SEQUENTIAL, 5,10, 100,200}, 1000, 250, 1000, 1}, 355 { {DATA_SEQUENTIAL, 5,10, 1000,2000}, 1000, 250, 1000, 1}, 356 { {DATA_SEQUENTIAL, 5,100, 10000,20000}, 100, 25, 100, 1}, 357 { {DATA_RANDOM, 10,10, 100,100}, 100000, 1000, 100, 0}, 358 { {DATA_SEQUENTIAL, 10,10, 100,100}, 100000, 1000, 100, 0}, 359 }; 360 361 int i; 362 int bRecover; 363 364 for(bRecover=0; bRecover<2; bRecover++){ 365 if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break; 366 for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){ 367 char *zName = getName(zSystem, bRecover, &aTest[i]); 368 if( testCaseBegin(pRc, zPattern, "%s", zName) ){ 369 doDataTest1(zSystem, bRecover, &aTest[i], pRc); 370 } 371 testFree(zName); 372 } 373 } 374 } 375 376 void testCompareDb( 377 Datasource *pData, 378 int nData, 379 int iSeed, 380 TestDb *pControl, 381 TestDb *pDb, 382 int *pRc 383 ){ 384 int i; 385 386 static int nCall = 0; 387 nCall++; 388 389 testScanCompare(pControl, pDb, 0, 0, 0, 0, 0, pRc); 390 testScanCompare(pControl, pDb, 1, 0, 0, 0, 0, pRc); 391 392 if( *pRc==0 ){ 393 int iKey1; 394 int iKey2; 395 void *pKey1; int nKey1; /* Start key */ 396 void *pKey2; int nKey2; /* Final key */ 397 398 iKey1 = testPrngValue(iSeed) % nData; 399 iKey2 = testPrngValue(iSeed+1) % nData; 400 testDatasourceEntry(pData, iKey1, &pKey2, &nKey1, 0, 0); 401 pKey1 = testMalloc(nKey1+1); 402 memcpy(pKey1, pKey2, nKey1+1); 403 testDatasourceEntry(pData, iKey2, &pKey2, &nKey2, 0, 0); 404 405 testScanCompare(pControl, pDb, 0, 0, 0, pKey2, nKey2, pRc); 406 testScanCompare(pControl, pDb, 0, pKey1, nKey1, 0, 0, pRc); 407 testScanCompare(pControl, pDb, 0, pKey1, nKey1, pKey2, nKey2, pRc); 408 testScanCompare(pControl, pDb, 1, 0, 0, pKey2, nKey2, pRc); 409 testScanCompare(pControl, pDb, 1, pKey1, nKey1, 0, 0, pRc); 410 testScanCompare(pControl, pDb, 1, pKey1, nKey1, pKey2, nKey2, pRc); 411 testFree(pKey1); 412 } 413 414 for(i=0; i<nData && *pRc==0; i++){ 415 void *pKey; int nKey; 416 testDatasourceEntry(pData, i, &pKey, &nKey, 0, 0); 417 testFetchCompare(pControl, pDb, pKey, nKey, pRc); 418 } 419 } 420 421 static void doDataTest2( 422 const char *zSystem, /* Database system to test */ 423 int bRecover, 424 Datatest2 *p, /* Structure containing test parameters */ 425 int *pRc /* OUT: Error code */ 426 ){ 427 TestDb *pDb; 428 TestDb *pControl; 429 Datasource *pData; 430 int i; 431 int rc = LSM_OK; 432 int iDot = 0; 433 434 /* Start the test case, open a database and allocate the datasource. */ 435 pDb = testOpen(zSystem, 1, &rc); 436 pData = testDatasourceNew(&p->defn); 437 rc = testControlDb(&pControl); 438 439 if( tdb_lsm(pDb) ){ 440 int nBuf = 32 * 1024 * 1024; 441 lsm_config(tdb_lsm(pDb), LSM_CONFIG_AUTOFLUSH, &nBuf); 442 } 443 444 for(i=0; rc==0 && i<p->nIter; i++){ 445 void *pKey1; int nKey1; 446 void *pKey2; int nKey2; 447 int ii; 448 int nRange = MIN(p->nIter*p->nWrite, p->nRange); 449 450 for(ii=0; rc==0 && ii<p->nWrite; ii++){ 451 int iKey = (i*p->nWrite + ii) % p->nRange; 452 testWriteDatasource(pControl, pData, iKey, &rc); 453 testWriteDatasource(pDb, pData, iKey, &rc); 454 } 455 456 testDatasourceEntry(pData, i+1000000, &pKey1, &nKey1, 0, 0); 457 pKey1 = testMallocCopy(pKey1, nKey1); 458 testDatasourceEntry(pData, i+2000000, &pKey2, &nKey2, 0, 0); 459 460 testDeleteRange(pDb, pKey1, nKey1, pKey2, nKey2, &rc); 461 testDeleteRange(pControl, pKey1, nKey1, pKey2, nKey2, &rc); 462 testFree(pKey1); 463 464 testCompareDb(pData, nRange, i, pControl, pDb, &rc); 465 if( bRecover ){ 466 testReopenRecover(&pDb, &rc); 467 }else{ 468 testReopen(&pDb, &rc); 469 } 470 testCompareDb(pData, nRange, i, pControl, pDb, &rc); 471 472 /* Update the progress dots... */ 473 testCaseProgress(i, p->nIter, testCaseNDot(), &iDot); 474 } 475 476 testClose(&pDb); 477 testClose(&pControl); 478 testDatasourceFree(pData); 479 testCaseFinish(rc); 480 *pRc = rc; 481 } 482 483 static char *getName2(const char *zSystem, int bRecover, Datatest2 *pTest){ 484 char *zRet; 485 char *zData; 486 zData = testDatasourceName(&pTest->defn); 487 zRet = testMallocPrintf("data2.%s.%s.rec=%d.%d.%d.%d", 488 zSystem, zData, bRecover, pTest->nRange, pTest->nWrite, pTest->nIter 489 ); 490 testFree(zData); 491 return zRet; 492 } 493 494 void test_data_2( 495 const char *zSystem, /* Database system name */ 496 const char *zPattern, /* Run test cases that match this pattern */ 497 int *pRc /* IN/OUT: Error code */ 498 ){ 499 Datatest2 aTest[] = { 500 /* defn, nRange, nWrite, nIter */ 501 { {DATA_RANDOM, 20,25, 100,200}, 10000, 10, 50 }, 502 { {DATA_RANDOM, 20,25, 100,200}, 10000, 200, 50 }, 503 { {DATA_RANDOM, 20,25, 100,200}, 100, 10, 1000 }, 504 { {DATA_RANDOM, 20,25, 100,200}, 100, 200, 50 }, 505 }; 506 507 int i; 508 int bRecover; 509 510 for(bRecover=0; bRecover<2; bRecover++){ 511 if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break; 512 for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){ 513 char *zName = getName2(zSystem, bRecover, &aTest[i]); 514 if( testCaseBegin(pRc, zPattern, "%s", zName) ){ 515 doDataTest2(zSystem, bRecover, &aTest[i], pRc); 516 } 517 testFree(zName); 518 } 519 } 520 } 521 522 /************************************************************************* 523 ** Test case data3.* 524 */ 525 526 typedef struct Datatest3 Datatest3; 527 struct Datatest3 { 528 int nRange; /* Keys are between 1 and this value, incl. */ 529 int nIter; /* Number of iterations */ 530 int nWrite; /* Number of writes per iteration */ 531 int nDelete; /* Number of deletes per iteration */ 532 533 int nValMin; /* Minimum value size for writes */ 534 int nValMax; /* Maximum value size for writes */ 535 }; 536 537 void testPutU32(u8 *aBuf, u32 iVal){ 538 aBuf[0] = (iVal >> 24) & 0xFF; 539 aBuf[1] = (iVal >> 16) & 0xFF; 540 aBuf[2] = (iVal >> 8) & 0xFF; 541 aBuf[3] = (iVal >> 0) & 0xFF; 542 } 543 544 void dt3PutKey(u8 *aBuf, int iKey){ 545 assert( iKey<100000 && iKey>=0 ); 546 sprintf((char *)aBuf, "%.5d", iKey); 547 } 548 549 static void doDataTest3( 550 const char *zSystem, /* Database system to test */ 551 Datatest3 *p, /* Structure containing test parameters */ 552 int *pRc /* OUT: Error code */ 553 ){ 554 int iDot = 0; 555 int rc = *pRc; 556 TestDb *pDb; 557 u8 *abPresent; /* Array of boolean */ 558 char *aVal; /* Buffer to hold values */ 559 int i; 560 u32 iSeq = 10; /* prng counter */ 561 562 abPresent = (u8 *)testMalloc(p->nRange+1); 563 aVal = (char *)testMalloc(p->nValMax+1); 564 pDb = testOpen(zSystem, 1, &rc); 565 566 for(i=0; i<p->nIter && rc==0; i++){ 567 int ii; 568 569 testCaseProgress(i, p->nIter, testCaseNDot(), &iDot); 570 571 /* Perform nWrite inserts */ 572 for(ii=0; ii<p->nWrite; ii++){ 573 u8 aKey[6]; 574 u32 iKey; 575 int nVal; 576 577 iKey = (testPrngValue(iSeq++) % p->nRange) + 1; 578 nVal = (testPrngValue(iSeq++) % (p->nValMax - p->nValMin)) + p->nValMin; 579 testPrngString(testPrngValue(iSeq++), aVal, nVal); 580 dt3PutKey(aKey, iKey); 581 582 testWrite(pDb, aKey, sizeof(aKey)-1, aVal, nVal, &rc); 583 abPresent[iKey] = 1; 584 } 585 586 /* Perform nDelete deletes */ 587 for(ii=0; ii<p->nDelete; ii++){ 588 u8 aKey1[6]; 589 u8 aKey2[6]; 590 u32 iKey; 591 592 iKey = (testPrngValue(iSeq++) % p->nRange) + 1; 593 dt3PutKey(aKey1, iKey-1); 594 dt3PutKey(aKey2, iKey+1); 595 596 testDeleteRange(pDb, aKey1, sizeof(aKey1)-1, aKey2, sizeof(aKey2)-1, &rc); 597 abPresent[iKey] = 0; 598 } 599 600 testReopen(&pDb, &rc); 601 602 for(ii=1; rc==0 && ii<=p->nRange; ii++){ 603 int nDbVal; 604 void *pDbVal; 605 u8 aKey[6]; 606 int dbrc; 607 608 dt3PutKey(aKey, ii); 609 dbrc = tdb_fetch(pDb, aKey, sizeof(aKey)-1, &pDbVal, &nDbVal); 610 testCompareInt(0, dbrc, &rc); 611 612 if( abPresent[ii] ){ 613 testCompareInt(1, (nDbVal>0), &rc); 614 }else{ 615 testCompareInt(1, (nDbVal<0), &rc); 616 } 617 } 618 } 619 620 testClose(&pDb); 621 testCaseFinish(rc); 622 *pRc = rc; 623 } 624 625 static char *getName3(const char *zSystem, Datatest3 *p){ 626 return testMallocPrintf("data3.%s.%d.%d.%d.%d.(%d..%d)", 627 zSystem, p->nRange, p->nIter, p->nWrite, p->nDelete, 628 p->nValMin, p->nValMax 629 ); 630 } 631 632 void test_data_3( 633 const char *zSystem, /* Database system name */ 634 const char *zPattern, /* Run test cases that match this pattern */ 635 int *pRc /* IN/OUT: Error code */ 636 ){ 637 Datatest3 aTest[] = { 638 /* nRange, nIter, nWrite, nDelete, nValMin, nValMax */ 639 { 100, 1000, 5, 5, 50, 100 }, 640 { 100, 1000, 2, 2, 5, 10 }, 641 }; 642 643 int i; 644 645 for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){ 646 char *zName = getName3(zSystem, &aTest[i]); 647 if( testCaseBegin(pRc, zPattern, "%s", zName) ){ 648 doDataTest3(zSystem, &aTest[i], pRc); 649 } 650 testFree(zName); 651 } 652 } 653 654