diff -r 000000000000 -r dfb7c4ff071f commsconfig/commsdatabaseshim/ts_commdb/Step_046_xx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsconfig/commsdatabaseshim/ts_commdb/Step_046_xx.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1027 @@ +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// This contains CommDb Unit Test Cases 046.XX +// +// + +// EPOC includes +#include +#include +#include +#include + +// Test system includes +#include +#include +#include "Teststepcommdb.h" +#include "TestSuiteCommdb.h" +#include "Step_046_xx.h" +#include + + +const TInt KTest04605Repeats = 20; + +// +// Test step 046.01 +// + +// constructor +CCommDbTest046_01::CCommDbTest046_01() + { + // store the name of this test case + iTestStepName = _L("step_046_01"); + } + +// destructor +CCommDbTest046_01::~CCommDbTest046_01() + { + } + + +TVerdict CCommDbTest046_01::doTestStepPreambleL() + { + openDbL(); + return EPass; + } + +TInt CCommDbTest046_01::executeStepL() + { + TInt ret=KErrGeneral; + + //This step checks that record id's are created in the expected manner, + //and that the record cursor also behaves as expected ie it moves to + //the next record, when the record it points to is deleted. + + iTheView = iTheDb->OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + CleanupStack::Pop(iTheView); + //Insert 4 records checking the id each time + TUint32 id; + + CDBLEAVE(iTheView->InsertRecord( id ), KErrNone); + if ( id != 1 ) + User::Leave( ret ); + + iTheView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service #1")); + iTheView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + iTheView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// iTheView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + iTheView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( iTheView->PutRecordChanges(), KErrNone ); + + CDBLEAVE(iTheView->InsertRecord( id ), KErrNone); + if ( id != 2 ) + User::Leave( ret ); + + iTheView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service #2")); + iTheView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + iTheView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// iTheView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + iTheView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( iTheView->PutRecordChanges(), KErrNone ); + + CDBLEAVE(iTheView->InsertRecord( id ), KErrNone); + if ( id !=3 ) + User::Leave( ret ); + + + iTheView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service #3")); + iTheView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + iTheView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// iTheView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + iTheView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( iTheView->PutRecordChanges(), KErrNone ); + + + CDBLEAVE(iTheView->InsertRecord( id ), KErrNone); + if ( id !=4 ) + User::Leave( ret ); + + + iTheView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service #4")); + iTheView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + iTheView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// iTheView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + iTheView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( iTheView->PutRecordChanges(), KErrNone ); + + + //Open a new view and move to the last record + delete iTheView; + iTheView = 0; + + iTheView = iTheDb->OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + CleanupStack::Pop(iTheView); + + CDBLEAVE( iTheView->GotoFirstRecord(), KErrNone ); + CDBLEAVE( iTheView->GotoNextRecord(), KErrNone ); + CDBLEAVE( iTheView->GotoNextRecord(), KErrNone ); + CDBLEAVE( iTheView->GotoNextRecord(), KErrNone ); + + //Delete the last record + CDBLEAVE( iTheView->DeleteRecord(), KErrNone ); + CDBLEAVE( iTheView->GotoPreviousRecord(), KErrNone); + //Check the cursor is now pointing at the previous record + + TUint32 value; + iTheView->ReadUintL( TPtrC(COMMDB_ID), value ); + + if ( value != 3 ) + User::Leave( ret ); + + //Goto the first record and delete that + CDBLEAVE( iTheView->GotoFirstRecord(), KErrNone ); + CDBLEAVE( iTheView->DeleteRecord(), KErrNone ); + CDBLEAVE( iTheView->GotoNextRecord(), KErrNone ); + //Check the cursor is now pointing at the second record + + iTheView->ReadUintL( TPtrC(COMMDB_ID), value ); + if ( value != 2 ) + User::Leave( ret ); + + //Insert a new record and check the id is correct + + CDBLEAVE(iTheView->InsertRecord( id ), KErrNone); + /* + DBMS supports cyclic id allocation..commsdat was forced + to do that too..but looks like we do reuse the record ids + if the deleted record was the last one. I think we should forget about + this slip because + a)Its not a behaviour worth having for us and we got away with it anyway + b)None of our client seem to give a damn about this for last few years + + if ( id != 5 ) + User::Leave( ret );*/ + + if ( id != 4 ) + User::Leave( ret ); + + iTheView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service #5")); + iTheView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + iTheView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// iTheView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + iTheView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + iTheView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( iTheView->PutRecordChanges(), KErrNone ); + + ret = KErrNone; //Passed if we get this far + + return ret; + } + + +TVerdict CCommDbTest046_01::doTestStepL( ) + { + Log(_L("Step 046.01 called ")); + + + if ( executeStepL() == KErrNone ) + iTestStepResult = EPass; + else + iTestStepResult = EFail; + + return iTestStepResult; + } + + + +// +// Test step 046.02 +// + +// constructor +CCommDbTest046_02::CCommDbTest046_02() + { + // store the name of this test case + iTestStepName = _L("step_046_02"); + } + +// destructor +CCommDbTest046_02::~CCommDbTest046_02() + { + } + + +TVerdict CCommDbTest046_02::doTestStepPreambleL() + { + openDbL(); + return EPass; + } + +void CCommDbTest046_02::insertTestRecordsL( TUint aQuantity ) + { + TUint count; + TUint32 id; + CCommsDbTableView* dbView; + + dbView = iTheDb->OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + + for( count=0; count < aQuantity; count++ ) + { + + CDBLEAVE(dbView->InsertRecord( id ), KErrNone); + dbView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service Test Record")); + dbView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + dbView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + dbView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// dbView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + dbView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + CDBLEAVE( dbView->PutRecordChanges(), KErrNone ); + + } + + CleanupStack::PopAndDestroy(dbView); + + } + +void CCommDbTest046_02::deleteLastRecordsL( TUint aQuantity ) + { + TUint count; + TInt ret = KErrGeneral; + CCommsDbTableView* dbView; + + dbView = iTheDb->OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + CDBLEAVE( dbView->GotoFirstRecord(), KErrNone ); + + //Move to the end of the view + do + { + ret = dbView->GotoNextRecord(); + }while ( ret != KErrNotFound ); + + //Need to move the cursor back into the view + dbView->GotoPreviousRecord(); + + //Now delete the record and move back one + for ( count=0; count< aQuantity; count++) + { + CDBLEAVE( dbView->DeleteRecord(), KErrNone ); + CDBLEAVE( dbView->GotoPreviousRecord(), KErrNone ); + } + + CleanupStack::PopAndDestroy(dbView); + } + + +TInt CCommDbTest046_02::executeStepL() + { + TInt ret=KErrGeneral, count; + + // NOTE: count limit reduced from 100 to 5, because commsdat has an id limit + // of 128 when inserting records. After this, you get a KErrOverflow from + // CCommsDbTableView::InsertRecord() in insertTestRecordsL(...). + for ( count=0; count < 5; count++ ) + { + insertTestRecordsL( 10 ); + + //Start a transaction, write 10 records, then rollback + CDBLEAVE( iTheDb->BeginTransaction(), KErrNone ); + insertTestRecordsL( 10 ); + iTheDb->RollbackTransaction(); + + //Start a transaction, write 10 records, delete them, then rollback + CDBLEAVE( iTheDb->BeginTransaction(), KErrNone ); + insertTestRecordsL( 10 ); + deleteLastRecordsL( 10 ); + iTheDb->RollbackTransaction(); + + //Start a transaction, write 10 records and commit them + CDBLEAVE( iTheDb->BeginTransaction(), KErrNone ); + insertTestRecordsL( 10 ); + CDBLEAVE( iTheDb->CommitTransaction(), KErrNone ); + + } + + ret = KErrNone; + + return ret; + } + + + +TVerdict CCommDbTest046_02::doTestStepL( ) + { + Log(_L("Step 046.02 called ")); + + + if ( executeStepL() == KErrNone ) + iTestStepResult = EPass; + else + iTestStepResult = EFail; + + return iTestStepResult; + } + + +// +//Thread1 does the first right, our main thread then does the second. +//They continue to take it in turns to do writes + +CCommDbTest046_03::CCommDbTest046_03() + { + // store the name of this test case + iTestStepName = _L("step_046_03"); + } + +CCommDbTest046_03::~CCommDbTest046_03() + {} + +TVerdict CCommDbTest046_03::doTestStepL( void ) + { + if(executeStepL()!=KErrNone) + return EFail; + return EPass; + } + +TVerdict CCommDbTest046_03::doTestStepPreambleL() + { + iTheDb=CCommsDatabase::NewL(); + + return EPass; + } + +TInt CCommDbTest046_03::Thread1Function(TAny* aPtr) + { + CTrapCleanup* cleanup=CTrapCleanup::New(); + if (cleanup==NULL) + return(KErrNoMemory); + + TRAPD(err, DoThread1TestL(aPtr)); + if(err != KErrNone) + { + return err; + } + + delete cleanup; + return(KErrNone); + } + +void CCommDbTest046_03::DoThread1TestL(TAny* aPtr) + { + TThreadInfo* syncInfo = (TThreadInfo*) aPtr; + TRequestStatus localStatus(KRequestPending); + syncInfo->iThread1Status = &localStatus; + + CCommsDatabase* cDb = CCommsDatabase::NewL(); + CleanupStack::PushL(cDb); + CCommsDbTableView* modemTable = cDb->OpenTableLC(TPtrC(MODEM_BEARER)); + + TUint32 dummyId; + modemTable->InsertRecord(dummyId); + modemTable->WriteTextL(TPtrC(COMMDB_NAME),_L("Thread1, Entry1")); + User::LeaveIfError(modemTable->PutRecordChanges()); + + //this thread is the first on to do all its rights + CleanupStack::PopAndDestroy(modemTable); + CleanupStack::PopAndDestroy(cDb); + + syncInfo->iMainThread.RequestComplete(syncInfo->iMainThreadStatus, KErrNone); + } + +TInt CCommDbTest046_03::executeStepL() + { + //First thing is to empty the modem table + CCommsDbTableView* modemTable = iTheDb->OpenTableLC(TPtrC(MODEM_BEARER)); + while(modemTable->GotoFirstRecord()==KErrNone) + modemTable->DeleteRecord(); + + RThread thread1; + TThreadInfo sync1; + TRequestStatus status1(KRequestPending); + sync1.iMainThreadStatus=&status1; + sync1.iMainThread.Duplicate(RThread(),EOwnerProcess); + _LIT(KThread1Name,"Thread1"); + User::LeaveIfError(thread1.Create(KThread1Name,Thread1Function,KDefaultStackSize,NULL,&sync1)); + CleanupClosePushL(thread1); + + iTheDb->BeginTransaction(); + + TUint32 dummyId; + modemTable->InsertRecord(dummyId); + _LIT(KTestName, "Main, Entry1"); + modemTable->WriteTextL(TPtrC(COMMDB_NAME), KTestName); + + //OK, lets start the other thread off now. + + TRequestStatus status2(KRequestPending); + + thread1.Logon(status2); + thread1.Resume(); + User::WaitForRequest(status1,status2); + + //OK, one of the status has completed, if it's status1 then that means thread1 didn't panic + //which is a bad thing. + + if(status1 != KRequestPending) + User::Leave(KErrGeneral); //Report error by leaving + + if(thread1.ExitType() != EExitPanic) + User::Leave(KErrGeneral); //Thread1 didn't panic, something else has gone wrong. + + CleanupStack::PopAndDestroy(); //thread1 + //Lets finish our entry off, and check it's OK. + User::LeaveIfError(modemTable->PutRecordChanges()); + + iTheDb->CommitTransaction(); + + CleanupStack::PopAndDestroy(modemTable); + + //Lets make a new modem view and check it's only got our entry in. + modemTable=NULL; + modemTable = iTheDb->OpenTableLC(TPtrC(MODEM_BEARER)); + User::LeaveIfError(modemTable->GotoFirstRecord()); + + TBuf tempBuf; + modemTable->ReadTextL(TPtrC(COMMDB_NAME), tempBuf); + + if(tempBuf!=KTestName) + User::Leave(KErrGeneral); + + CleanupStack::PopAndDestroy(modemTable); + return EPass; + } + +TVerdict CCommDbTest046_03::doTestStepPostambleL() + { + delete iTheDb; + iTheDb=NULL; + return EPass; + } + +// +/* +Note for anyone who looks at this code. +It's a bit of a mess, but it seems to do the job. Basically thread1 is the thread trying to +do a write to the database, and our main thread is the one responsible for checking that +the change hasn't gone in before PutRecordChanges is called by thread1. After thread1 has +done it's write, we check that the write was sucessfull. This is done by our main thread +right at the end of CCommDbTest046_04::executeStepL(). +*/ + +CCommDbTest046_04::CCommDbTest046_04() + { + // store the name of this test case + iTestStepName = _L("step_046_04"); + } + +CCommDbTest046_04::~CCommDbTest046_04() + {} + +TVerdict CCommDbTest046_04::doTestStepL( void ) + { + if(executeStepL()!=KErrNone) + return EFail; + return EPass; + } + +TVerdict CCommDbTest046_04::doTestStepPreambleL() + { + iTheDb=CCommsDatabase::NewL(); + + return EPass; + } + +TInt CCommDbTest046_04::Thread1Function(TAny* aPtr) + { + CTrapCleanup* cleanup=CTrapCleanup::New(); + if (cleanup==NULL) + return(KErrNoMemory); + + TRAPD(err, DoThread1TestL(aPtr)); + + delete cleanup; + return(err); + } + +void CCommDbTest046_04::DoThread1TestL(TAny* aPtr) + { + TThreadInfo* remoteThreadInfo = (TThreadInfo*) aPtr; + CCommsDatabase* cDb =CCommsDatabase::NewL(); + CleanupStack::PushL(cDb); + + CCommsDbTableView* dialInIspView = cDb->OpenTableLC(TPtrC(DIAL_IN_ISP)); + User::LeaveIfError(dialInIspView->GotoFirstRecord()); + dialInIspView->UpdateRecord(); + dialInIspView->WriteLongTextL(TPtrC(ISP_LOGIN_SCRIPT), _L("Changed")); + + remoteThreadInfo->iCaller.RequestComplete(remoteThreadInfo->iStatus1,KErrNone);//We're now ready to kick of the other thread + + User::After(10000000); + TInt err = dialInIspView->PutRecordChanges(); + + CleanupStack::PopAndDestroy(dialInIspView); + + CleanupStack::PopAndDestroy(cDb); + remoteThreadInfo->iCaller.RequestComplete(remoteThreadInfo->iStatus2,err); + } + +TInt CCommDbTest046_04::executeStepL() + { + //Set the commdb up so we know what's in the first record of the Dial in ISP before we start. + CCommsDbTableView* dialInIspView = iTheDb->OpenTableLC(TPtrC(DIAL_IN_ISP)); + User::LeaveIfError(dialInIspView->GotoFirstRecord()); + dialInIspView->UpdateRecord(); + dialInIspView->WriteLongTextL(TPtrC(ISP_LOGIN_SCRIPT), _L("Original")); + User::LeaveIfError(dialInIspView->PutRecordChanges()); + CleanupStack::PopAndDestroy(dialInIspView); + + //Start off the first thread, this will run until it has done all but PutRecordChanges is called on the transaction. + RThread thread1; + TThreadInfo sync1; + TRequestStatus status1(KRequestPending); + TRequestStatus status2(KRequestPending); + sync1.iStatus1=&status1; + sync1.iStatus2=&status2; + sync1.iCaller.Duplicate(RThread(),EOwnerProcess); + _LIT(KThread1Name,"Thread1"); + TInt err=thread1.Create(KThread1Name,Thread1Function,KDefaultStackSize,NULL,&sync1); + CleanupClosePushL(thread1); + + if(err==KErrNone) + { + thread1.Resume(); + User::WaitForRequest(status1); + } + //Thread just kicked off will have run to User::After(10000000); by the time we get to here + //We've basically got 10 seconds from here to check that the record hasn't been committed, which sould be plenty long enough. + + dialInIspView = iTheDb->OpenTableLC(TPtrC(DIAL_IN_ISP)); + User::LeaveIfError(dialInIspView->GotoFirstRecord()); + + HBufC* retrievedString = dialInIspView->ReadLongTextLC(TPtrC(ISP_LOGIN_SCRIPT)); + + if(*retrievedString!=_L("Original")) + User::Leave(KErrGeneral); + + CleanupStack::PopAndDestroy(); //retrievedString + retrievedString=NULL; + CleanupStack::PopAndDestroy(dialInIspView); + + User::WaitForRequest(status2); + User::LeaveIfError(status2.Int()); //status2.Int() is the value returned when PutRecordChanges is called by thread1. + + //Might as well check that thread1s changes got through.... + dialInIspView = iTheDb->OpenTableLC(TPtrC(DIAL_IN_ISP)); + User::LeaveIfError(dialInIspView->GotoFirstRecord()); + retrievedString= dialInIspView->ReadLongTextLC(TPtrC(ISP_LOGIN_SCRIPT)); + err=KErrNone; + if(*retrievedString!=_L("Changed")) + err= KErrGeneral; + CleanupStack::PopAndDestroy(); //retrievedString + CleanupStack::PopAndDestroy(dialInIspView); + CleanupStack::PopAndDestroy(); //thread1 + return err; + } + +TVerdict CCommDbTest046_04::doTestStepPostambleL() + { + delete iTheDb; + iTheDb=NULL; + return EPass; + } + +// + + +CCommDbTest046_05::CCommDbTest046_05() + { + // store the name of this test case + iTestStepName = _L("step_046_05"); + } + +CCommDbTest046_05::~CCommDbTest046_05() + {} + +TVerdict CCommDbTest046_05::doTestStepL( void ) + { + if(executeStepL()!=KErrNone) + return EFail; + return EPass; + } + +TVerdict CCommDbTest046_05::doTestStepPreambleL() + { + iTheDb=CCommsDatabase::NewL(); + + return EPass; + } + +TInt CCommDbTest046_05::Thread1Function(TAny* aPtr) + { + CTrapCleanup* cleanup=CTrapCleanup::New(); + if (cleanup==NULL) + return(KErrNoMemory); + + TRAPD(err, DoThread1TestL(aPtr)); + + delete cleanup; + return(err); + } + +void CCommDbTest046_05::DoThread1TestL(TAny* aPtr) + { + TInt ret; + TInt64 seed; + TThreadInfo* remoteThreadInfo = (TThreadInfo*) aPtr; + + CCommsDatabase* cDb = CCommsDatabase::NewL(); + CleanupStack::PushL(cDb); + + for (TInt count=0; count < KTest04605Repeats; count++ ) + { + PrintDebug(_L("DoThread1TestL() - 1. InsertTestRecords")); + InsertTestRecordsL(EFalse, 10 , *cDb); + + + // Start a transaction, write 10 records, then rollback + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - 2. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() - 2. BeginTransaction")); + TRequestStatus status1(KRequestPending); + cDb->RequestNotification(status1); + PrintDebug(_L("DoThread1TestL() - 3. InsertTestRecords")); + while(!InsertTestRecordsL(EFalse, 10 , *cDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("DoThread1TestL() - Rolling back Transaction")); + cDb->RollbackTransaction(); + User::WaitForRequest(status1); + status1 = KRequestPending; + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again")); + cDb->RequestNotification(status1); + } + // 10 records inserted successfully, now rollback and wait for CommDb + PrintDebug(_L("DoThread1TestL() - 4. Rollback")); + cDb->RollbackTransaction(); + PrintDebug(_L("DoThread1TestL() - 5. WaitForRequest")); + User::WaitForRequest(status1); + + + + //Start a transaction, write 10 records, delete them, then rollback + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - 6. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() - 6. BeginTransaction")); + TRequestStatus status2(KRequestPending); + cDb->RequestNotification(status2); + PrintDebug(_L("DoThread1TestL() - 7. InsertTestRecords")); + while(!InsertTestRecordsL( EFalse, 10 , *cDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("DoThread1TestL() - Rolling back Transaction")); + cDb->RollbackTransaction(); + User::WaitForRequest(status2); + status2 = KRequestPending; + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again")); + cDb->RequestNotification(status2); + } + // 10 records inserted successfully, now delete them, rollback and wait for commdb + DeleteLastRecordsL(EFalse, 10, *cDb ); + PrintDebug(_L("DoThread1TestL() - 8. Rollback")); + cDb->RollbackTransaction(); + PrintDebug(_L("DoThread1TestL() - 9. WaitForRequest")); + User::WaitForRequest(status2); + + + //Start a transaction, write 10 records and commit them + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - 10. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() -10. BeginTransaction")); + TRequestStatus status3(KRequestPending); + cDb->RequestNotification(status3); + PrintDebug(_L("DoThread1TestL() -11. InsertRecords")); + while(!InsertTestRecordsL(EFalse, 10 , *cDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("DoThread1TestL() - Rolling back Transaction")); + cDb->RollbackTransaction(); + User::WaitForRequest(status3); + status3 = KRequestPending; + RandomDelay(seed); + while(ret = cDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("DoThread1TestL() - Begin Transaction Again")); + cDb->RequestNotification(status3); + } + // Commit the 10 records, wait for CommDb + PrintDebug(_L("DoThread1TestL() -12. Commit")); + User::LeaveIfError(cDb->CommitTransaction()); + PrintDebug(_L("DoThread1TestL() -13. WaitForRequest")); + User::WaitForRequest(status3); + + // Give the other thread a chance + PrintDebug(_L("DoThread1TestL() -14. User::After")); + RandomDelay(seed); + } + + CleanupStack::PopAndDestroy(cDb); + PrintDebug(_L("DoThread1TestL() RequestComplete")); + remoteThreadInfo->iCaller.RequestComplete(remoteThreadInfo->iStatus1, KErrNone); + + } + +TInt CCommDbTest046_05::executeStepL() + { + TInt ret; + + //Start off the first thread, this will run until it has done all but PutRecordChanges is called on the transaction. + RThread thread1; + TInt64 seed; + TThreadInfo sync1; + TRequestStatus remoteThreadStatus(KRequestPending); + sync1.iStatus1=&remoteThreadStatus; + sync1.iCaller.Duplicate(RThread(),EOwnerProcess); + _LIT(KThread1Name,"Thread1"); + User::LeaveIfError(thread1.Create(KThread1Name,Thread1Function,KDefaultStackSize,NULL,&sync1)); + CleanupClosePushL(thread1); + + thread1.Resume(); + for (TInt count=0; count < KTest04605Repeats; count++ ) + { + PrintDebug(_L("ExecuteStepL() - 1. InsertTestRecords")); + InsertTestRecordsL(ETrue, 10, *iTheDb ); + + //Start a transaction, write 10 records, then rollback + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - 2. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() - 2. BeginTransaction")); + TRequestStatus status1(KRequestPending); + iTheDb->RequestNotification(status1); + PrintDebug(_L("ExecuteStepL() - 3. InsertTestRecords")); + while(!InsertTestRecordsL(ETrue, 10 , *iTheDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("ExecuteStepL() - Rolling back Transaction")); + iTheDb->RollbackTransaction(); + User::WaitForRequest(status1); + status1 = KRequestPending; + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again")); + iTheDb->RequestNotification(status1); + } + // 10 records written, now rollback and wait for commdb + PrintDebug(_L("ExecuteStepL() - 4. Rollback")); + iTheDb->RollbackTransaction(); + PrintDebug(_L("ExecuteStepL() - 5. WaitForRequest")); + User::WaitForRequest(status1); + + + + //Start a transaction, write 10 records, delete them, then rollback + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - 6. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() - 6. BeginTransaction")); + TRequestStatus status2(KRequestPending); + iTheDb->RequestNotification(status2); + PrintDebug(_L("ExecuteStepL() - 7. InsertTestRecordsL")); + while(!InsertTestRecordsL(ETrue, 10 , *iTheDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("ExecuteStepL() - Rolling back Transaction")); + iTheDb->RollbackTransaction(); + User::WaitForRequest(status2); + status2 = KRequestPending; + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again")); + iTheDb->RequestNotification(status2); + } + // 10 records written successfully, now delete them, rollback and wait for commmdb + PrintDebug(_L("ExecuteStepL() - 8. DeleteTestRecordsL")); + DeleteLastRecordsL(ETrue, 10, *iTheDb); + PrintDebug(_L("ExecuteStepL() - 9. Rollback")); + iTheDb->RollbackTransaction(); + PrintDebug(_L("ExecuteStepL() -10. WaitForRequest")); + User::WaitForRequest(status2); + + + + //Start a transaction, write 10 records and commit them + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - 11. BeginTransaction failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() -11. BeginTransaction")); + TRequestStatus status3(KRequestPending); + iTheDb->RequestNotification(status3); + PrintDebug(_L("ExecuteStepL() -12. InsertTestRecords")); + while(!InsertTestRecordsL( ETrue,10 , *iTheDb)) + { + // Error during record insertion, most likely the other thread beat + // us to it, Rollback and try again + PrintDebug(_L("ExecuteStepL() - Rolling back Transaction")); + iTheDb->RollbackTransaction(); + User::WaitForRequest(status3); + status3 = KRequestPending; + RandomDelay(seed); + while(ret = iTheDb->BeginTransaction(), ret!=KErrNone) + { + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again failed")); + User::After(2000); + } + PrintDebug(_L("ExecuteStepL() - Begin Transaction Again")); + iTheDb->RequestNotification(status3); + } + PrintDebug(_L("ExecuteStepL() -13. Commit")); + User::LeaveIfError(iTheDb->CommitTransaction()); + PrintDebug(_L("ExecuteStepL() -14. WaitForRequest")); + User::WaitForRequest(status3); + + + // Give the other thread a chance to do stuff + PrintDebug(_L("ExecuteStepL() -15. User::After")); + RandomDelay(seed); + } + + PrintDebug(_L("ExecuteStepL() - Wait For Remote Thread")); + User::WaitForRequest(remoteThreadStatus); + CleanupStack::PopAndDestroy(); //thread1 + PrintDebug(_L("ExecuteStepL() - Exiting")); + return KErrNone; + } + +TVerdict CCommDbTest046_05::doTestStepPostambleL() + { + delete iTheDb; + iTheDb=NULL; + return EPass; + } + +TBool CCommDbTest046_05::InsertTestRecordsL( TBool aCallerIsMainThread, TUint aQuantity, CCommsDatabase& aDb ) + { + TUint32 id; + CCommsDbTableView* dbView = aDb.OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + for(TUint count=0; count < aQuantity; count++ ) + { + while(dbView->InsertRecord( id )!= KErrNone) + { + if(aCallerIsMainThread) + PrintDebug(_L("ExecuteStepL() Insert Record failed...")); + else PrintDebug(_L("DoThread1TestL() Insert Record failed...")); + CleanupStack::PopAndDestroy(dbView); + return EFalse; + } + dbView->WriteTextL(TPtrC(COMMDB_NAME),_L("My Service Test Record")); + dbView->WriteBoolL(TPtrC(ISP_DIAL_RESOLUTION),ETrue); + dbView->WriteBoolL(TPtrC(ISP_USE_LOGIN_SCRIPT),EFalse); + dbView->WriteBoolL(TPtrC(ISP_PROMPT_FOR_LOGIN),ETrue); +// dbView->WriteTextL(TPtrC(ISP_IF_NAME),_L("ppp")); + dbView->WriteBoolL(TPtrC(ISP_IF_PROMPT_FOR_AUTH),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP_ADDR_FROM_SERVER),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP_DNS_ADDR_FROM_SERVER),ETrue); + dbView->WriteBoolL(TPtrC(ISP_IP6_DNS_ADDR_FROM_SERVER),ETrue); + User::LeaveIfError(dbView->PutRecordChanges()); + if(aCallerIsMainThread) + PrintDebug(_L("ExecuteStepL() InsertingRecord...")); + else PrintDebug(_L("DoThread1TestL() InsertingRecord...")); + + // Allow the other thread to do things between each record insertion + User::After(5000); + } + + CleanupStack::PopAndDestroy(dbView); + return ETrue; + } + +void CCommDbTest046_05::DeleteLastRecordsL( TBool aCallerIsMainThread, TUint aQuantity, CCommsDatabase& aDb) + { + TUint count; + TInt ret = KErrGeneral; + CCommsDbTableView* dbView; + + dbView = aDb.OpenTableLC( TPtrC(DIAL_OUT_ISP) ); + CDBLEAVE( dbView->GotoFirstRecord(), KErrNone ); + + //Move to the end of the view + do + { + ret = dbView->GotoNextRecord(); + }while ( ret != KErrNotFound ); + + //Need to move the cursor back into the view + dbView->GotoPreviousRecord(); + + //Now delete the record and move back one + for ( count=0; count< aQuantity; count++) + { + // Allow the other thread to do things between each record deletion + User::After(5000); + User::LeaveIfError(dbView->DeleteRecord()); + User::LeaveIfError( dbView->GotoPreviousRecord()); + if(aCallerIsMainThread) + PrintDebug(_L("ExecuteStepL() Record Deleted...")); + else PrintDebug(_L("DoThread1TestL() Record Deleted...")); + + } + + CleanupStack::PopAndDestroy(dbView); + } + +void CCommDbTest046_05::RandomDelay(TInt64 &aSeed) + { + // Random delay for between 0-1 seconds + // Gives a thread a chance to access the database while the other + // thread is still sleeping + + // If this delay is made excessively large, the test is pointeless, + // the two threads will just take turns to do things with the database + + // If the delay is too short both threads will hammer CommDb simulataneously and + // they will effectively deadlock, neither getting the chance to complete anything + + + TInt32 delay; + TReal rnd = Math::FRand(aSeed); + rnd*=1000000; + delay=(TInt32) rnd; + User::After(delay); + } + +void CCommDbTest046_05::PrintDebug(TPtrC )//aString) + { + // Uncomment this line to see whats going on in the debug trace + //RDebug::Print(aString); + }