// Copyright (c) 1997-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:
// RTest based unit test to verify the operation of the functions
// to get/set 'default' view definitions in cntmodel. The functions are:
// TContactViewStore::DefaultViewsL()
// TContactViewStore::SetDefaultViewsL()
//
//
#include <e32base.h>
#include <e32test.h>
#include <cntdb.h>
#include <cntviewbase.h>
#include <cntviewstore.h>
#include <centralrepository.h>
#include "t_viewstore.h"
#include "cntviewprivate.h"
#include "cntviewstoreprivate.h"
/*
List of test cases
Need to mainly test the set function, so test various
combinations of setting view defs. e.g.
- Set the default techview settings
- Set multiple (valid) view settings
- Set invalid view settings
- Set mixed valid & invalid view settings
Other tests that may be of use:
- Different default repository files, some with invalid data?
- Error conditions:
- Calling DefaultViewsL() with a non-empty RArray: KErrArgument
- (Set)DefaultViewsL() with no repository: KErrNotFound
*/
_LIT(KTitle, "t_viewstore");
RTest test(KTitle);
class CTestManager : public CBase, public MContactViewObserver
{
public:
static CTestManager* NewLC();
void HandleContactViewEvent(const CContactViewBase &aView, const TContactViewEvent &aEvent);
void TestDefaultDefinitionL();
void TestInvalidViewNameL();
void TestInvalidSortPluginNameL();
void TestMultipleValidViewDefinitionsL();
void TestMultipleValidInvalidViewDefinitionsL();
void TestRetrievingExistingViewsL();
void TestDeleteReplaceL();
private:
CTestManager() {}
~CTestManager();
void ConstructL();
void Close();
private:
CContactDatabase* iDb;
RPointerArray<CContactViewBase> iViews;
};
/*
operator == for CContactDefaultViewDefinition
*/
TBool operator == (const CContactDefaultViewDefinition& viewDef1, const CContactDefaultViewDefinition& viewDef2)
{
if (viewDef1.ViewPreferences() != viewDef2.ViewPreferences())
{
return EFalse;
}
if (!(viewDef1.SortOrder() == viewDef2.SortOrder()))
{
return EFalse;
}
if (viewDef1.ViewNameL().Compare(viewDef2.ViewNameL()) != 0)
{
return EFalse;
}
if (viewDef1.SortPluginNameL().Compare(viewDef2.SortPluginNameL()) != 0)
{
return EFalse;
}
if (viewDef1.ViewType() != viewDef2.ViewType())
{
return EFalse;
}
return ETrue;
}
/*
*/
CContactViewDefinitionGenerator* CContactViewDefinitionGenerator::NewLC()
{
CContactViewDefinitionGenerator* self = new (ELeave) CContactViewDefinitionGenerator;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
/*
*/
void CContactViewDefinitionGenerator::ConstructL()
{
}
/*
*/
CContactDefaultViewDefinition* CContactViewDefinitionGenerator::CreateDefinitionLC(TViewDescription aDesc)
{
CContactDefaultViewDefinition* viewDef = 0;
RContactViewSortOrder viewSortOrder;
CleanupClosePushL(viewSortOrder);
switch (aDesc)
{
case ETechviewContactsAppView:
{
// This is the view definition used
// by the Techview Contacts application
_LIT(KContactsAppViewName, "KMainContactsAppView");
_LIT8(KSortPluginName, "");
viewSortOrder.AppendL(KUidContactFieldFamilyName);
viewSortOrder.AppendL(KUidContactFieldGivenName);
viewSortOrder.AppendL(KUidContactFieldCompanyName);
viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView,
KContactsAppViewName, viewSortOrder,
EContactsOnly, KSortPluginName);
break;
}
case EValidLFCView:
{
// This is a generic remote view typical
// of what might be used on a phone. It
// sorts the contacts based on last name,
// first name and company name, in that order.
_LIT(KGenericLFCViewName, "KGenericLFCView");
_LIT8(KSortPluginName, "");
viewSortOrder.AppendL(KUidContactFieldFamilyName);
viewSortOrder.AppendL(KUidContactFieldGivenName);
viewSortOrder.AppendL(KUidContactFieldPhoneNumber);
viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView,
KGenericLFCViewName, viewSortOrder,
EContactsOnly, KSortPluginName);
break;
}
case EValidLFPView:
{
// This is a generic remote view typical
// of what might be used on a phone. It
// sorts the contacts based on last name,
// first name and phone number, in that order.
_LIT(KGenericLFPViewName, "KGenericLFPView");
_LIT8(KSortPluginName, "");
viewSortOrder.AppendL(KUidContactFieldPhoneNumber);
viewSortOrder.AppendL(KUidContactFieldGivenName);
viewSortOrder.AppendL(KUidContactFieldFamilyName);
viewSortOrder.AppendL(KUidContactFieldCompanyName);
viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView,
KGenericLFPViewName, viewSortOrder,
EContactsOnly, KSortPluginName);
break;
}
case EInvalidViewNameView:
{
// This view is invalid because the view name
// is longer than KMaxUnicodeStringLength, the
// maximum length descriptor that can be stored
// in a repository key.
_LIT(KInvalidViewName, "KViewWithANameThatIsLongerThanTheMaximumAllowedLengthInACentralRepositoryKey");
_LIT8(KSortPluginName, "");
TBuf<NCentralRepositoryConstants::KMaxUnicodeStringLength + 2> invalidDesc;
invalidDesc.Copy(KInvalidViewName);
invalidDesc.AppendFill('*', (invalidDesc.MaxLength() - invalidDesc.Length()));
viewSortOrder.AppendL(KUidContactFieldGivenName);
viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView,
invalidDesc, viewSortOrder,
EContactsOnly, KSortPluginName);
break;
}
case EInvalidSortPluginNameView:
{
// This view is invalid because the view name
// is longer than KMaxBinaryLength, the
// maximum length 8-bit descriptor that can be
// stored in a repository key
_LIT(KInvalidSortPluginViewName, "KInvalidSortPluginNameView");
_LIT8(KInvalidSortPluginName, "InvalidSortPluginNameThatIsTooLongToFitIntoACentralRepositoryKey");
TBuf8<NCentralRepositoryConstants::KMaxBinaryLength + 2> invalidDesc;
invalidDesc.Copy(KInvalidSortPluginName);
invalidDesc.AppendFill('*', (invalidDesc.MaxLength() - invalidDesc.Length()));
viewSortOrder.AppendL(KUidContactFieldFamilyName);
viewSortOrder.AppendL(KUidContactFieldGivenName);
viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView,
KInvalidSortPluginViewName, viewSortOrder,
EContactsOnly, invalidDesc);
break;
}
default:
{
User::Leave(KErrArgument);
}
}
CleanupStack::Pop(viewDef);
CleanupStack::PopAndDestroy(&viewSortOrder);
CleanupStack::PushL(viewDef);
return viewDef;
}
//
// CTestManager
//
CTestManager::~CTestManager()
{
Close();
}
CTestManager* CTestManager::NewLC()
{
CTestManager* self = new (ELeave) CTestManager;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
void CTestManager::ConstructL()
{
}
void CTestManager::Close()
{
for (TInt i = 0; i < iViews.Count(); i++)
{
iViews[i]->Close(*this);
}
iViews.Close();
if (iDb)
{
delete iDb;
iDb = NULL;
}
}
/*
This gets called when a view is ready to use
*/
void CTestManager::HandleContactViewEvent(const CContactViewBase& /*aView*/, const TContactViewEvent& /*aEvent*/)
{
CActiveScheduler::Stop();
}
/*
Test the storing and retrieving of the
view definition used by the Techview
Contacts app
*/
void CTestManager::TestDefaultDefinitionL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
RPointerArray<CContactDefaultViewDefinition> viewDefs;
CleanupResetAndDestroyPushL(viewDefs);
// Store the 'default' view definition
CContactDefaultViewDefinition* viewDef = gen->CreateDefinitionLC(CContactViewDefinitionGenerator::ETechviewContactsAppView);
viewDefs.AppendL(viewDef);
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrNone);
viewDefs.Reset();
// Retrieve the view definition(s) and compare to what was stored
//for (TInt i=4 ;; i++)
// {
//__UHEAP_SETFAIL(RHeap::EFailNext, i);
//__UHEAP_MARK;
TRAP(err, TContactViewStore::GetDefaultViewsL(viewDefs));
//viewDefs.ResetAndDestroy();
//__UHEAP_MARKEND;
//__UHEAP_RESET;
// if (err != KErrNoMemory)
// {
// break;
// }
// }
test(err == KErrNone);
test(viewDefs.Count() == 1);
test(*viewDef == *viewDefs[0]);
CleanupStack::PopAndDestroy(viewDef);
CleanupStack::PopAndDestroy(&viewDefs);
CleanupStack::PopAndDestroy(gen);
}
/*
Test the storing of a view with an invalid name.
i.e. the name is to long to fit into the cenrep.
*/
void CTestManager::TestInvalidViewNameL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
CContactDefaultViewDefinition* viewDef = gen->CreateDefinitionLC(CContactViewDefinitionGenerator::EInvalidViewNameView);
RPointerArray<CContactDefaultViewDefinition> viewDefs;
// SetDefaultViewsL should leave with KErrArgument because
// the view name is too long.
viewDefs.AppendL(viewDef);
CleanupStack::Pop(viewDef);
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrArgument);
viewDefs.ResetAndDestroy();
CleanupStack::PopAndDestroy(gen);
}
/*
Test the storing of a view with an invalid sort plugin name.
i.e. the name is to long to fit into the cenrep.
*/
void CTestManager::TestInvalidSortPluginNameL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
CContactDefaultViewDefinition* viewDef = gen->CreateDefinitionLC(CContactViewDefinitionGenerator::EInvalidSortPluginNameView);
RPointerArray<CContactDefaultViewDefinition> viewDefs;
// SetDefaultViewsL should leave with KErrArgument because
// the view name is too long.
viewDefs.AppendL(viewDef);
CleanupStack::Pop(viewDef);
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrArgument);
viewDefs.ResetAndDestroy();
CleanupStack::PopAndDestroy(gen);
}
/*
Test the storing and retrieval of multiple
(valid) view definitions.
*/
void CTestManager::TestMultipleValidViewDefinitionsL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
RPointerArray<CContactDefaultViewDefinition> viewDefs;
CContactDefaultViewDefinition* viewDef;
CContactViewDefinitionGenerator::TViewDescription desc;
// create some view definitions
for (TInt i = 0; i < 100; i++)
{
desc = static_cast<CContactViewDefinitionGenerator::TViewDescription>(i % CContactViewDefinitionGenerator::ENumValidViewDescriptions);
viewDef = gen->CreateDefinitionLC(desc);
viewDefs.AppendL(viewDef);
CleanupStack::Pop(viewDef);
}
// store the view definitions
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrNone);
// retrieve the definitions
RPointerArray<CContactDefaultViewDefinition> storedViewDefs;
TRAP(err, TContactViewStore::GetDefaultViewsL(storedViewDefs));
test(err == KErrNone);
// check the retrieved ones match the ones which were stored
test(storedViewDefs.Count() == viewDefs.Count());
for (TInt j = 0; j < storedViewDefs.Count(); j++)
{
test(*viewDefs[j] == *storedViewDefs[j]);
}
viewDefs.ResetAndDestroy();
storedViewDefs.ResetAndDestroy();
CleanupStack::PopAndDestroy(gen);
}
/*
Test the storing and retrieval of multiple
valid and invalid view definitions. This
should fail, leaving with KErrArgument
*/
void CTestManager::TestMultipleValidInvalidViewDefinitionsL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
RPointerArray<CContactDefaultViewDefinition> viewDefs;
CContactDefaultViewDefinition* viewDef;
CContactViewDefinitionGenerator::TViewDescription desc;
// create some view definitions
for (TInt i = 0; i < 10; i++)
{
desc = static_cast<CContactViewDefinitionGenerator::TViewDescription>(i % CContactViewDefinitionGenerator::ENumViewDescriptions);
viewDef = gen->CreateDefinitionLC(desc);
viewDefs.AppendL(viewDef);
CleanupStack::Pop(viewDef);
}
// store the view definitions - this should leave
// with KErrArgument because of the invalid view(s)
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrArgument);
viewDefs.ResetAndDestroy();
CleanupStack::PopAndDestroy(gen);
}
/*
*/
void CTestManager::TestRetrievingExistingViewsL()
{
CContactViewDefinitionGenerator* gen = CContactViewDefinitionGenerator::NewLC();
RPointerArray<CContactDefaultViewDefinition> viewDefs;
CContactDefaultViewDefinition* viewDef;
TInt i;
// create some view definitions
for (i = 0; i < CContactViewDefinitionGenerator::ENumValidViewDescriptions; i++)
{
viewDef = gen->CreateDefinitionLC(CContactViewDefinitionGenerator::TViewDescription(i));
viewDefs.AppendL(viewDef);
CleanupStack::Pop(viewDef);
}
// store the view definitions
TRAPD(err, TContactViewStore::SetDefaultViewsL(viewDefs));
test(err == KErrNone);
// retrieve the definitions
RPointerArray<CContactDefaultViewDefinition> storedViewDefs;
TRAP(err, TContactViewStore::GetDefaultViewsL(storedViewDefs));
test(err == KErrNone);
// create the views that were retrieved
TRAP(err, iDb = CContactDatabase::OpenL());
if (err != KErrNone)
{
if (err == KErrNotFound)
{
RDebug::Printf("Error: Couldn't find default database.");
}
User::Leave(err);
}
CContactViewBase* view = NULL;
for (i = 0; i < storedViewDefs.Count(); i++)
{
viewDef = storedViewDefs[i];
if (viewDef->ViewType() == CContactDefaultViewDefinition::ERemoteView)
{
view = CContactRemoteView::NewL(*this, *iDb, viewDef->SortOrder(), viewDef->ViewPreferences());
}
else
{
view = CContactNamedRemoteView::NewL(*this, viewDef->ViewNameL(),
*iDb, viewDef->SortOrder(),
viewDef->ViewPreferences());
}
iViews.Append(view);
// Wait for the view to be created
CActiveScheduler::Start();
}
// get the list of existing views and checked against stored ones
RPointerArray<CContactDefaultViewDefinition> existingViewDefs;
TContactViewStorePrivate::GetDefinitionsOfExistingViewsL(KNullDesC, existingViewDefs);
test(storedViewDefs.Count() == existingViewDefs.Count());
for (i = 0; i < existingViewDefs.Count(); i++)
{
test(*existingViewDefs[i] == *storedViewDefs[i]);
}
existingViewDefs.ResetAndDestroy();
storedViewDefs.ResetAndDestroy();
viewDefs.ResetAndDestroy();
CleanupStack::PopAndDestroy(gen);
}
/*
*/
void CTestManager::TestDeleteReplaceL()
{
// Quick test: assuming server has been started in non-transient at start-up,
// try to replace the default database.
Close();
CContactDatabase::DeleteDefaultFileL();
// Start the contacts server in non-transient mode
// Attempt to delete the default file. This should not be blocked.
// Stop the contacts server
// Start contacts server in non-transient mode
// Attempt to replace default file.
}
/*
Implementation of test code
*/
/**
@SYMTestCaseID PIM-T-VIEWSTORE-0001
*/
LOCAL_C void doMainL()
{
CTestManager* testMgr = CTestManager::NewLC();
test.Start(_L("@SYMTESTCaseID:PIM-T-VIEWSTORE-0001 Storing the Techview Contacts App view definition"));
testMgr->TestDefaultDefinitionL();
test.Next(_L("Storing a view definition with invalid view name"));
testMgr->TestInvalidViewNameL();
test.Next(_L("Storing a view definition with invalid sort plugin name"));
testMgr->TestInvalidSortPluginNameL();
test.Next(_L("Storing multiple valid view definitions"));
testMgr->TestMultipleValidViewDefinitionsL();
test.Next(_L("Storing mixed valid and invalid views"));
testMgr->TestMultipleValidInvalidViewDefinitionsL();
test.Next(_L("Retrieving the list of views that exist in the server"));
testMgr->TestRetrievingExistingViewsL();
test.Next(_L("Delete/Replace of default database when server is non-transient"));
testMgr->TestDeleteReplaceL();
CleanupStack::PopAndDestroy(testMgr);
}
/*
t_viewstore entry point
*/
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
test.Title();
CTrapCleanup* cleanup = CTrapCleanup::New();
if (!cleanup)
{
return KErrNoMemory;
}
CActiveScheduler * scheduler = new (ELeave) CActiveScheduler;
CActiveScheduler::Install(scheduler);
TRAPD(err, doMainL());
if (err != KErrNone)
{
_LIT(KOutputRes,"t_viewstore returned with %d \n");
TBuf<64> formattable;
formattable.Format(KOutputRes, err);
test.Printf(formattable);
}
test(err == KErrNone);
delete scheduler;
delete cleanup;
test.End();
test.Close();
__UHEAP_MARKEND;
return err;
}