=== modified file 'storage/ndb/test/ndbapi/testNdbApi.cpp' --- storage/ndb/test/ndbapi/testNdbApi.cpp 2009-03-30 12:03:52 +0000 +++ storage/ndb/test/ndbapi/testNdbApi.cpp 2009-04-01 16:27:31 +0000 @@ -2636,6 +2636,138 @@ testNdbRecordRowLength(NDBT_Context* ctx return NDBT_OK; } +int +weirdAssertFail(NDBT_Context* ctx, NDBT_Step* step) +{ + /* testNdbApi -n WeirdAssertFail + * Generates phrase "here2" on 6.3 which is + * output by DbtupExecQuery::handleReadReq() + * detecting that the record's tuple checksum + * is incorrect. + * Later can generate assertion failure in + * prepare_read + * ndbassert(src_len >= (dynstart - src_data)); + * resulting in node failure + */ + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table* pTab= ctx->getTab(); + + int numIterations= 100; + int numRecords= 1024; + + NdbTransaction* trans; + HugoOperations hugoOps(*pTab); + + for (int iter=0; iter < numIterations; iter++) + { + ndbout << "Iter : " << iter << endl; + CHECK((trans= pNdb->startTransaction()) != 0); + + CHECK(hugoOps.setTransaction(trans) == 0); + + CHECK(hugoOps.pkInsertRecord(pNdb, + 0, + numRecords) == 0); + + /* Now execute the transaction */ + if ((trans->execute(NdbTransaction::NoCommit) != 0)) + { + ndbout << "Execute failed, error is " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + CHECK(0); + } + + CHECK(trans->getNdbError().code == 0); + + /* Now delete the records in the same transaction + * Need to do this manually as Hugo doesn't support it + */ + CHECK(hugoOps.pkDeleteRecord(pNdb, + 0, + numRecords) == 0); + + CHECK(trans->execute(NdbTransaction::NoCommit) == 0); + CHECK(trans->getNdbError().code == 0); + + /* Now abort the transaction by closing it */ + trans->close(); + + /* Force Hugo Transaction back to NULL */ + hugoOps.setTransaction(NULL, true); + } + + return NDBT_OK; +} + +int +weirdAssertFail2(NDBT_Context* ctx, NDBT_Step* step) +{ + /* testNdbApi -n WeirdAssertFail2 + * Results in assertion failure in DbtupCommit::execTUP_DEALLOCREQ() + * ndbassert(ptr->m_header_bits & Tuple_header::FREE); + * Results in node failure + */ + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table* pTab= ctx->getTab(); + + int numOuterIterations= 50; + int numInnerIterations= 20; + int numRecords= 200; + + NdbTransaction* trans; + + for (int outerIter=0; outerIter < numOuterIterations; outerIter++) + { + HugoOperations hugoOps(*pTab); + + ndbout << "Outer Iter : " << outerIter << endl; + + int offset= (outerIter * numRecords); + + CHECK(hugoOps.startTransaction(pNdb) == 0); + CHECK(hugoOps.pkInsertRecord(pNdb, offset, numRecords) == 0); + CHECK(hugoOps.execute_Commit(pNdb) == 0); + CHECK(hugoOps.closeTransaction(pNdb) == 0); + + for (int iter=0; iter < numInnerIterations; iter++) + { + //ndbout << "Inner Iter : " << iter << endl; + CHECK((trans= pNdb->startTransaction()) != 0); + + CHECK(hugoOps.setTransaction(trans) == 0); + + /* Delete the records */ + CHECK(hugoOps.pkDeleteRecord(pNdb, + offset, + numRecords) == 0); + + /* Re-insert them */ + CHECK(hugoOps.pkInsertRecord(pNdb, + offset, + numRecords) == 0); + + /* Now execute the transaction, with IgnoreError */ + if ((trans->execute(NdbTransaction::NoCommit, + NdbOperation::AO_IgnoreError) != 0)) + { + ndbout << "Execute failed, error is " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + CHECK(0); + } + + /* Now abort the transaction by closing it without committing */ + trans->close(); + + /* Force Hugo Transaction back to NULL */ + hugoOps.setTransaction(NULL, true); + } + } + + return NDBT_OK; +} + NDBT_TESTSUITE(testNdbApi); TESTCASE("MaxNdb", @@ -2773,6 +2905,14 @@ TESTCASE("NdbRecordRowLength", "Verify that the record row length calculation is correct") { INITIALIZER(testNdbRecordRowLength); } +TESTCASE("WeirdAssertFail", + "Rollback insert followed by delete to get corruption") { + INITIALIZER(weirdAssertFail); +} +TESTCASE("WeirdAssertFail2", + "Rollback no-change update on top of existing data") { + INITIALIZER(weirdAssertFail2); +} NDBT_TESTSUITE_END(testNdbApi); int main(int argc, const char** argv){