/* * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). * Contact: http://www.qt-project.org/legal * 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: * Summary: * A test to exercise the contacts model subview object and associated * functionality. The test includes creating, resorting and searching a view. * Actions: * -- Create a new database; * -- Populate database with randomly generated data; * -- Create a local named view sorted by lname, fname, company and telephone; * -- Create a subview based on the local view; * -- Verify the subview has been created properly; * -- Resort the local view; * -- Verify the subview has been updated properly after resort; * -- Clean up. * Associated defect: * DEF125393 PIM Sphinx QP: Improve test coverage of Cntmodel Subviews * Written by: * James Clarke * */ #include "t_subview.h" ////////////////////////////////////////////////////////////////////////////////////////////////// // CSubViewTest methods ////////////////////////////////////////////////////////////////////////////////////////////////// CSubViewTest* CSubViewTest::NewLC() { CSubViewTest* self = new (ELeave) CSubViewTest(); CleanupStack::PushL(self); self->ConstructL(); return self; } CSubViewTest::CSubViewTest() : CActive(CActive::EPriorityStandard) { } void CSubViewTest::ConstructL() { CActiveScheduler::Add(this); // create a database populated with randomly generated contacts iContactsDb = DbCreator::CreateDbL(KDbName, KNumContacts); } CSubViewTest::~CSubViewTest() { Cancel(); Cleanup(); } void CSubViewTest::Cleanup() { if (iNamedLocalView) { iNamedLocalView->Close(*this); iNamedLocalView = NULL; } if (iSubView) { iSubView->Close(*this); iSubView = NULL; } delete iContactsDb; TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KDbName)); } void CSubViewTest::RunL() { switch (iState) { case ETestStarted: CreateNamedLocalViewL(); iState = ENamedLocalViewCreated; break; case ENamedLocalViewCreated: test.Printf(_L("Local view created")); CreateSubViewL(); iState = ESubViewCreated; break; case ESubViewCreated: test.Printf(_L("Sub view created")); PreResortTestL(); ResortNamedLocalViewL(); iState = EResorting; break; case ENamedLocalViewResorted: case ESubViewUpdated: break; case ESortingComplete: test.Printf(_L("Local view resorted")); test.Printf(_L("Sub view updated after local view resort.")); PostResortTestL(); CActiveScheduler::Stop(); break; default: test.Printf(_L("Invalid state.")); test(EFalse); } } void CSubViewTest::CreateNamedLocalViewL() { test.Next(_L("Creating local view.")); RContactViewSortOrder sortOrder; CleanupClosePushL(sortOrder); sortOrder.AppendL(KUidContactFieldFamilyName); sortOrder.AppendL(KUidContactFieldGivenName); sortOrder.AppendL(KUidContactFieldCompanyName); sortOrder.AppendL(KUidContactFieldPhoneNumber); // set the field indexes to reflect the order above iLnameIdx = 0; iFnameIdx = 1; iCnameIdx = 2; iNumIdx = 3; iNamedLocalView = CContactNamedLocalView::NewL(*this, KTestName(), *iContactsDb, sortOrder, EContactsOnly); CleanupStack::PopAndDestroy(&sortOrder); } void CSubViewTest::DoCancel() { } void CSubViewTest::CreateSubViewL() { test.Next(_L("Creating subview.")); iSubView = CContactSubView::NewL(*iNamedLocalView, *iContactsDb, *this, KLowBoundary(), KHighBoundary()); } void CSubViewTest::HandleContactViewEvent(const CContactViewBase& aView, const TContactViewEvent& aEvent) { if (aEvent.iEventType == TContactViewEvent::ESortOrderChanged) { if (iState == EResorting) { if (&aView == iNamedLocalView) { iState = ENamedLocalViewResorted; } else { iState = ESubViewUpdated; } } else if (iState == ENamedLocalViewResorted || iState == ESubViewUpdated) { iState = ESortingComplete; } else { test.Printf(_L("Ooops! Something's gone wrong with the view-resorting states...")); test(EFalse); } } if (aEvent.iEventType == TContactViewEvent::EReady || iState == ESortingComplete) { TRequestStatus* pStat = &iStatus; User::RequestComplete(pStat, KErrNone); SetActive(); } } void CSubViewTest::PrintSubViewL() const { const TInt KLocalCount(iNamedLocalView->CountL()); const TInt KSubCount(iSubView->CountL()); test.Printf(_L("Subview contains %d of the %d contacts in the NamedLocalView."), KSubCount, KLocalCount); for(TInt i = 0; i < KSubCount; ++i) { const TPtrC fname = iSubView->ContactAtL(i).Field(iFnameIdx); const TPtrC lname = iSubView->ContactAtL(i).Field(iLnameIdx); const TPtrC cname = iSubView->ContactAtL(i).Field(iCnameIdx); const TPtrC num = iSubView->ContactAtL(i).Field(iNumIdx); test.Printf(_L("Contact #%d -- Person: %S %S; Company: %S; Phone number: %S."), i + 1, &fname, &lname, &cname, &num); } } void CSubViewTest::PreResortTestL() const { test.Next(_L("Verifying subview is correct after creation.")); SubAndLocalViewCompareTestL(); CheckSortOrderL(); } void CSubViewTest::PostResortTestL() const { test.Next(_L("Verifying subview is correct after resorting underlying view.")); SubAndLocalViewCompareTestL(); CheckSortOrderL(); } void CSubViewTest::SubAndLocalViewCompareTestL() const { test.Printf(_L("Testing subview is accurate compared to the local view.")); const TInt KSubViewCount = iSubView->CountL(); const TInt KLocalViewCount = iNamedLocalView->CountL(); const TInt KFirstFieldIdx(0); TInt subViewIdx(0); TBool foundFirstInSubView(EFalse); TBool foundLastInSubView(EFalse); TInt subCntItemId(iSubView->AtL(subViewIdx)); TInt localCntItemId(-1); // initialise with a value that can't be a real Id for(TInt localViewIdx = 0; localViewIdx < KLocalViewCount && !foundLastInSubView; ++localViewIdx) { localCntItemId = iNamedLocalView->AtL(localViewIdx); // already found the first item in the sub view within // the underlying local view. if (foundFirstInSubView) { ++subViewIdx; subCntItemId = iSubView->AtL(subViewIdx); // check that the contact ids in the sub view and local view match if (subCntItemId != localCntItemId) { test.Printf(_L("Mismatch of contacts between subview and local view")); test(EFalse); } // if we've found the last sub view item, do boundary checking to // ensure we have the right things from the local view in the sub view. if (subViewIdx == KSubViewCount - 1) { foundLastInSubView = ETrue; // Haven't checked localViewIdx < KLocalViewCount but it's not // likely that the last contact in the sub view will legitimately // be the same as the last one in the local view. const TPtrC nextLocalName = iNamedLocalView->ContactAtL(localViewIdx + 1).Field(KFirstFieldIdx); const TPtrC subName = iSubView->ContactAtL(subViewIdx).Field(KFirstFieldIdx); // check that the first character of the last contact in the subview // is within the proper range and that the next contact in the // local view is outside the range. test.Printf(_L("Found last contact from subview in local view. Testing for errors.")); test(subName.Left(1).CompareF(KHighChar) <= 0 || nextLocalName.Left(1).CompareF(KHighChar) > 0); test.Printf(_L("-- check okay.")); } } // we've found the first contact item from the sub view in the local // view. check else if (localCntItemId == subCntItemId && !foundFirstInSubView) { foundFirstInSubView = ETrue; // Haven't checked localViewIdx != 0 but it is not likely that the // first contact in the local view will legitimately be the same as // the first one in the sub view. const TPtrC prevLocalName = iNamedLocalView->ContactAtL(localViewIdx - 1).Field(KFirstFieldIdx); const TPtrC subName = iSubView->ContactAtL(subViewIdx).Field(KFirstFieldIdx); // check that the first character of the first contact in the subview // is within the proper range and that the previous contact in the // local view is outside the range. test.Printf(_L("Found first contact from subview in local view. Testing for errors.")); test(subName.Left(1).CompareF(KLowChar) >= 0 && prevLocalName.Left(1).CompareF(KLowChar) < 0); test.Printf(_L("-- check okay.")); // check that we can find an expected contact item in the subview // and cannot find something that should not be there. test.Printf(_L("Testing FindL() functionality.")); test(iSubView->FindL(subCntItemId) == subViewIdx && iSubView->FindL(iNamedLocalView->AtL(localViewIdx - 1)) == KErrNotFound); test.Printf(_L("-- check okay.")); // check the AllFieldsLC functionality test.Printf(_L("Testing AllFieldsLC() functionality.")); _LIT(KDelimiter, ";"); HBufC* allFields = iSubView->AllFieldsLC(subViewIdx, KDelimiter()); TPtrC allFieldsPtr = allFields->Des(); TBufC<16> field0 = iSubView->ContactAtL(subViewIdx).Field(0); TBufC<16> field1 = iSubView->ContactAtL(subViewIdx).Field(1); TBufC<16> field2 = iSubView->ContactAtL(subViewIdx).Field(2); TBufC<16> field3 = iSubView->ContactAtL(subViewIdx).Field(3); TBuf<48> fieldsBuf; _LIT(KFormat, "%S;%S;%S;%S"); fieldsBuf.AppendFormat(KFormat(), &field0, &field1, &field2, &field3); test(fieldsBuf.Compare(allFieldsPtr) == 0); // they should be the same test.Printf(_L("-- check okay.")); CleanupStack::PopAndDestroy(allFields); } } } void CSubViewTest::CheckSortOrderL() const { test.Printf(_L("Checking sort order")); RContactViewSortOrder sortOrder = iSubView->SortOrderL(); // don't take ownership test( sortOrder[iLnameIdx] == KUidContactFieldFamilyName && sortOrder[iFnameIdx] == KUidContactFieldGivenName && sortOrder[iCnameIdx] == KUidContactFieldCompanyName && sortOrder[iNumIdx] == KUidContactFieldPhoneNumber && iSubView->ContactViewPreferences() == EContactsOnly ); } void CSubViewTest::ResortNamedLocalViewL() { test.Next(_L("Resorting local view.")); RContactViewSortOrder sortOrder; CleanupClosePushL(sortOrder); sortOrder.AppendL(KUidContactFieldCompanyName); sortOrder.AppendL(KUidContactFieldGivenName); sortOrder.AppendL(KUidContactFieldFamilyName); sortOrder.AppendL(KUidContactFieldPhoneNumber); // set the field indexes to reflect the order above iCnameIdx = 0; iFnameIdx = 1; iLnameIdx = 2; iNumIdx = 3; iNamedLocalView->ChangeSortOrderL(sortOrder); CleanupStack::PopAndDestroy(&sortOrder); } void CSubViewTest::DoTestL() { TRequestStatus* status = &iStatus; User::RequestComplete(status, KErrNone); SetActive(); iState = ETestStarted; CActiveScheduler::Start(); } ////////////////////////////////////////////////////////////////////////////////////////////////// // main test functions ////////////////////////////////////////////////////////////////////////////////////////////////// /** @SYMTestCaseID PIM-T-SUBVIEW-0001 */ void DoTestsL() { test.Start(_L("@SYMTESTCaseID:PIM-T-SUBVIEW-0001 ")); CSubViewTest* myTest = CSubViewTest::NewLC(); myTest->DoTestL(); // do some stuff here... CleanupStack::PopAndDestroy(myTest); test.End(); test.Close(); } GLDEF_C TInt E32Main() { // Init __UHEAP_MARK; CTrapCleanup* cleanupStack = CTrapCleanup::New(); if (!cleanupStack) { return KErrNoMemory; } CActiveScheduler* activeScheduler = new CActiveScheduler; if (!activeScheduler) { return KErrNoMemory; } CActiveScheduler::Install(activeScheduler); // Run the tests TRAPD(err, DoTestsL()); if (err) { TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KDbName) ); test(EFalse); } // Cleanup delete activeScheduler; delete cleanupStack; __UHEAP_MARKEND; return err; }