--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines_old/contactsmodel/tsrc/T_ViewNotificationError.cpp Tue Aug 31 15:05:21 2010 +0300
@@ -0,0 +1,267 @@
+// Copyright (c) 2003-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:
+//
+
+#include <e32test.h>
+#include <cntitem.h>
+#include <cntfldst.h>
+#include <cntviewbase.h>
+
+#include "CContactViewEventQueue.h"
+
+
+// Constants
+_LIT(KTestName, "T_ViewNotificationError");
+
+_LIT(KTestDbName, "c:T_ViewNotificationError.cdb");
+
+
+// Global RTest object
+LOCAL_D RTest test(KTestName);
+
+
+/**
+ * A helper class for holding the resources needed in the tests.
+ */
+class CTestResources :
+ public CBase, public MContactViewObserver
+ {
+ public:
+ static CTestResources* NewLC();
+ void ConstructL();
+ void CreateViewL();
+ void RemoveFirstContactL();
+ ~CTestResources();
+
+ CContactDatabase* iDb;
+ CContactViewEventQueue* iViewObserver1;
+ CContactViewEventQueue* iViewObserver2;
+ CContactViewEventQueue* iViewObserver3;
+ RContactViewSortOrder iViewSortOrder;
+ CContactLocalView* iAllContactsView;
+
+ private: // From MContactViewObserver.
+ void HandleContactViewEvent
+ (const CContactViewBase& aView, const TContactViewEvent& aEvent);
+ };
+
+/**
+ * Creates new test resources object.
+ */
+CTestResources* CTestResources::NewLC()
+ {
+ CTestResources* self = new(ELeave) CTestResources;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CTestResources::ConstructL()
+ {
+ // Open test DB
+ iDb = CContactDatabase::OpenL(KTestDbName);
+ }
+
+void CTestResources::CreateViewL()
+ {
+ // Create the sort order
+ iViewSortOrder.AppendL(KUidContactFieldFamilyName);
+ iViewSortOrder.AppendL(KUidContactFieldGivenName);
+ iViewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ // Create a view, assign this class to it's observer
+ iAllContactsView = CContactLocalView::NewL
+ (*this, *iDb, iViewSortOrder, EContactsOnly);
+
+ // Create three additional view observers
+ iViewObserver1 = CContactViewEventQueue::NewL(iAllContactsView);
+ iViewObserver2 = CContactViewEventQueue::NewL(iAllContactsView);
+ iViewObserver3 = CContactViewEventQueue::NewL(iAllContactsView);
+ iViewObserver1->CloseOnItemRemoved();
+ iViewObserver2->CloseOnItemRemoved();
+ iViewObserver3->CloseOnItemRemoved();
+ }
+
+void CTestResources::RemoveFirstContactL()
+ {
+ iDb->DeleteContactL(1);
+ }
+
+void CTestResources::HandleContactViewEvent
+ (const CContactViewBase& /*aView*/, const TContactViewEvent& /*aEvent*/)
+ {
+ // Do nothing
+ }
+
+CTestResources::~CTestResources()
+ {
+ if (iAllContactsView) iAllContactsView->Close(*this);
+ iViewSortOrder.Close();
+ delete iViewObserver3;
+ delete iViewObserver2;
+ delete iViewObserver1;
+ User::After(1000000);
+ delete iDb;
+ }
+
+
+LOCAL_C TContactItemId CreateTestContactL
+ (CContactDatabase& aDb, const TDesC& aFamilyName)
+ {
+ // Create a contact card
+ CContactCard* card = CContactCard::NewLC();
+ // Create a name field
+ CContactItemField* field = CContactItemField::NewLC
+ (KStorageTypeText, KUidContactFieldFamilyName);
+ field->TextStorage()->SetTextL(aFamilyName);
+ card->AddFieldL(*field);
+ CleanupStack::Pop(field);
+ // Add the contact to the DB
+ const TContactItemId contactId = aDb.AddNewContactL(*card);
+ CleanupStack::PopAndDestroy(card);
+ return contactId;
+ }
+
+
+LOCAL_C CContactIdArray* PopulateTestDbLC(TInt aNumContacts)
+ {
+ CContactIdArray* ids = CContactIdArray::NewLC();
+ CContactDatabase* db = CContactDatabase::ReplaceL(KTestDbName);
+ CleanupStack::PushL(db);
+ TBuf<50> name;
+ _LIT(KNameFormat, "Test%d");
+ for (TInt i=1; i <= aNumContacts; ++i)
+ {
+ name.Format(KNameFormat,i);
+ const TContactItemId id = CreateTestContactL(*db,name);
+ ids->AddL(id);
+ }
+ CleanupStack::PopAndDestroy(db);
+ return ids;
+ }
+
+
+/**
+ * This test demonstrates how a contact view fails to notify its observers
+ * if some of the observers deregisters for receiving events. It does not
+ * only fail to do that, it also panics the application.
+ * There is a design error in CContactViewBase::NotifyObservers.
+ */
+
+LOCAL_C void TestViewNotificationL()
+ {
+ test.Next(_L("Test contact view notification"));
+
+
+ // Open the populated test DB
+ CTestResources* res = CTestResources::NewLC();
+
+ // Create a contact view and three additional
+ // observers (please see CTestResources::CreateViewL
+ // implementation for extra comments)
+ res->CreateViewL();
+
+ // Wait for the first observer to report the view is ready
+ TContactViewEvent event;
+ test(res->iViewObserver1->ListenForEvent(10,event));
+ test(event.iEventType == TContactViewEvent::EReady);
+
+ // ..then the second observer...
+ test(res->iViewObserver2->ListenForEvent(10,event));
+ test(event.iEventType == TContactViewEvent::EReady);
+
+ // ..and finally the last observer reports it's ready.
+ test(res->iViewObserver3->ListenForEvent(10,event));
+ test(event.iEventType == TContactViewEvent::EReady);
+
+ // Remove one contact from the db
+ res->RemoveFirstContactL();
+
+ // Wait for the first observer to receive the remove event...
+ test(res->iViewObserver1->ListenForEvent(10,event));
+/**
+ * After the above line Contact Model crashes to
+ * USER 130 panic, EBadArrayIndex.
+ *
+ * The reason is that the observer deregistered itself
+ * from receiving contact view events when it got
+ * EItemRemoved event. The for loop in
+ * CContactViewBase::NotifyObservers can't handle that
+ * situation.
+ */
+ test(event.iEventType == TContactViewEvent::EItemRemoved);
+
+ // Then second observer should receive the event
+ test(res->iViewObserver2->ListenForEvent(10,event));
+ test(event.iEventType == TContactViewEvent::EItemRemoved);
+
+ // And finally the third observer should receive the event
+ test(res->iViewObserver3->ListenForEvent(10,event));
+ test(event.iEventType == TContactViewEvent::EItemRemoved);
+ CleanupStack::PopAndDestroy(res);
+ }
+
+/**
+
+@SYMTestCaseID PIM-T-VIEWNOTIFICATIONERROR-0001
+
+*/
+
+
+LOCAL_C void DoTestsL()
+ {
+ // Init
+ CleanupClosePushL(test);
+ test.Start(_L("@SYMTESTCaseID:PIM-T-VIEWNOTIFICATIONERROR-0001 T_ViewNotificationError"));
+
+
+ // Populate a test DB
+ const TInt KNumTestContacts = 100;
+ CContactIdArray* testContactIds = PopulateTestDbLC(KNumTestContacts);
+
+ // Execute the tests
+ TestViewNotificationL();
+
+ // Cleanup
+ CleanupStack::PopAndDestroy(testContactIds);
+ test.End();
+ CleanupStack::PopAndDestroy(); // 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());
+
+ // Cleanup
+ delete activeScheduler;
+ delete cleanupStack;
+ __UHEAP_MARKEND;
+ return err;
+ }