phonebookengines_old/contactsmodel/tsrc/T_GENERALADDRESS.CPP
changeset 40 b46a585f6909
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines_old/contactsmodel/tsrc/T_GENERALADDRESS.CPP	Fri Jun 11 13:29:23 2010 +0300
@@ -0,0 +1,960 @@
+// 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:
+//
+
+// System includes
+#include <e32test.h>
+#include <f32file.h>
+#include <s32file.h>
+#include <cntdb.h>
+#include <cntdef.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+#include <bautils.h>
+#include <barsc.h>
+#include <barsread.h>
+#include <versit.h>
+#include <vcard.h>
+#include <e32def.h>
+#include <coreappstest/testserver.h>
+// User includes
+#include "T_UTILS.H"
+
+// Flags
+#define OOM_TESTS
+
+// Globals
+static RTest TheTest(_L("T_GENERALADDRESS - Test General Address Export and Import"));
+static CCntTest* TheTestHelper;
+
+// Type definitions
+typedef void (*TGAFunction)(TBool& aPrintedTestTitle);
+
+// Constants
+const TInt KIntContactFieldVCardMapGENERALADDRESS = 0;
+const TUid KUidContactFieldVCardMapGENERALADDRESS = { KIntContactFieldVCardMapGENERALADDRESS };
+
+// Literal constants
+_LIT(KTestDatabaseFile, "C:GeneralAddressDatabase.cdb");
+//
+_LIT(KTestNameFamily, "Bloggs");
+_LIT(KTestNameGiven, "Joe");
+//
+_LIT(KTestAddressHOME, "_HOME");
+_LIT(KTestAddressWORK, "_WORK");
+_LIT(KTestAddressPREF, "_PREF");
+_LIT(KTestAddressGENERALADDRESS, "_GENERALADDRESS");
+//
+_LIT(KTestAddressPOSTOFFICE, "POSTOFFICE");
+_LIT(KTestAddressEXTENDEDADR, "EXTENDEDADR");
+_LIT(KTestAddressADR, "ADR");
+_LIT(KTestAddressLOCALITY, "LOCALITY");
+_LIT(KTestAddressREGION, "REGION");
+_LIT(KTestAddressPOSTCODE, "POSTCODE");
+_LIT(KTestAddressCOUNTRY, "COUNTRY");
+//
+_LIT(KTestVCardExportFileName, "C:\\T_GENERALADDRESS_EXPORTED.TXT");
+_LIT(KTestVCardImportFileName, "C:\\T_GENERALADDRESS_IMPORTED.TXT");
+//
+_LIT8(KVersitParam8GeneralAddress, "");
+
+
+// Utility methods
+
+/**
+ * Create a simple contact with just the name fields populated
+ */
+static TContactItemId CreateContactL(CContactDatabase& aDatabase)
+	{
+	const TContactItemId templateId = aDatabase.TemplateId();
+	//
+	CContactItem* templateCard = aDatabase.ReadContactLC(templateId);
+	CContactCard* card = CContactCard::NewL(templateCard);
+	CleanupStack::PushL(card);
+	//
+	SetNameL(*card, KUidContactFieldFamilyName, KUidContactFieldVCardMapUnusedN, KTestNameFamily, EFalse);
+	SetNameL(*card, KUidContactFieldGivenName, KUidContactFieldVCardMapUnusedN, KTestNameGiven, EFalse);
+	//
+	const TContactItemId id = aDatabase.AddNewContactL(*card);
+	CleanupStack::PopAndDestroy(2, templateCard);
+	return id;
+	}
+
+/**
+ * Combine a value and a postfix to create a real unified value
+ */
+static HBufC* ConstructAddressValueLC(const TDesC& aValue, const TDesC& aPostFix)
+	{
+	HBufC* value = HBufC::NewLC(aValue.Length() + aPostFix.Length());
+	TPtr pValue(value->Des());
+	pValue = aValue;
+	pValue.Append(aPostFix);
+	//
+	return value;
+	}
+
+/**
+ * Add a specific address field to a vCard
+ */
+static void AddAddressFieldL(CContactItem& aContact, TFieldType aFieldType, TUid aMapping, TFieldType aExtraFieldType, const TDesC& aValue, const TDesC& aValuePostFix)
+	{
+	CContentType* content = CContentType::NewL(aFieldType, aMapping);
+	CleanupStack::PushL(content);
+	content->AddFieldTypeL(aExtraFieldType);
+	//
+	CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, *content);
+	//
+	HBufC* value = ConstructAddressValueLC(aValue, aValuePostFix);
+	//
+	contactItemField->TextStorage()->SetStandardTextL(*value);
+	CleanupStack::PopAndDestroy(value);
+	//
+	aContact.AddFieldL(*contactItemField);
+	CleanupStack::Pop(contactItemField);
+	//
+	CleanupStack::PopAndDestroy(content);
+	}
+
+/**
+ * Return the post fix descriptor for a given field type (HOME, WORK, PREF, General)
+ */
+static TPtrC PostFixForFieldType(TFieldType aType)
+	{
+	TPtrC postFix(KNullDesC);
+	switch(aType.iUid)
+		{
+	case KIntContactFieldVCardMapHOME:
+		postFix.Set(KTestAddressHOME);
+		break;
+	case KIntContactFieldVCardMapWORK:
+		postFix.Set(KTestAddressWORK);
+		break;
+	case KIntContactFieldVCardMapPREF:
+		postFix.Set(KTestAddressPREF);
+		break;
+	case KIntContactFieldVCardMapGENERALADDRESS:
+		postFix.Set(KTestAddressGENERALADDRESS);
+		break;
+	default:
+		TheTest(EFalse);
+		break;
+		}
+	//
+	return postFix;
+	}
+
+/**
+ * Add a specific address type to a contact card
+ */
+static void AddAddressL(CContactDatabase& aDatabase, TContactItemId aId, TFieldType aExtraFieldType)
+	{
+	const TPtrC postFix(PostFixForFieldType(aExtraFieldType));
+	//
+	CContactItem* card = aDatabase.OpenContactLX(aId);
+	CleanupStack::PushL(card);
+	//
+	AddAddressFieldL(*card, KUidContactFieldPostOffice, KUidContactFieldVCardMapPOSTOFFICE, aExtraFieldType, KTestAddressPOSTOFFICE, postFix);
+	AddAddressFieldL(*card, KUidContactFieldExtendedAddress, KUidContactFieldVCardMapEXTENDEDADR, aExtraFieldType, KTestAddressEXTENDEDADR, postFix);
+	AddAddressFieldL(*card, KUidContactFieldAddress, KUidContactFieldVCardMapADR, aExtraFieldType, KTestAddressADR, postFix);
+	AddAddressFieldL(*card, KUidContactFieldLocality, KUidContactFieldVCardMapLOCALITY, aExtraFieldType, KTestAddressLOCALITY, postFix);
+	AddAddressFieldL(*card, KUidContactFieldRegion, KUidContactFieldVCardMapREGION, aExtraFieldType, KTestAddressREGION, postFix);
+	AddAddressFieldL(*card, KUidContactFieldPostcode, KUidContactFieldVCardMapPOSTCODE, aExtraFieldType, KTestAddressPOSTCODE, postFix);
+	AddAddressFieldL(*card, KUidContactFieldCountry, KUidContactFieldVCardMapCOUNTRY, aExtraFieldType, KTestAddressCOUNTRY, postFix);
+	//
+	aDatabase.CommitContactL(*card);
+	CleanupStack::PopAndDestroy(card);
+	CleanupStack::Pop(); // lock record
+	}
+
+/**
+ * Export a specific contact to a vCard file
+ */
+static void ExportContactAsVCardL(CContactDatabase& aDatabase, TContactItemId aId, RFs& aFsSession, const TDesC& aVCardFileName)
+	{
+	CContactIdArray* idArray = CContactIdArray::NewLC();
+	idArray->AddL(aId);
+	//
+	RFile outfile;
+	const TInt error = outfile.Replace(aFsSession, aVCardFileName, EFileWrite);
+	User::LeaveIfError(error);
+	CleanupClosePushL(outfile);
+	//
+	RFileWriteStream writeStream(outfile);
+	CleanupClosePushL(writeStream);
+	//
+	const TUid KVersitVCardUid = { KUidVCardConvDefaultImpl };
+	aDatabase.ExportSelectedContactsL(KVersitVCardUid, *idArray, writeStream, CContactDatabase::EDefault);
+	writeStream.CommitL();
+	CleanupStack::PopAndDestroy(3, idArray); // writeStream, outfile, idArray
+	}
+
+/**
+ * Parse a file using the Symbian vCard parser and return the parsed data structures
+ * to the caller
+ */
+static CParserVCard* ParseVCardFileLC(RFs& aFsSession, const TDesC& aVCardFileName)
+	{
+	CParserVCard* parser = CParserVCard::NewL();
+	CleanupStack::PushL(parser);
+	//
+	RFile readFile;
+	const TInt error = readFile.Open(aFsSession, aVCardFileName, EFileRead);
+	User::LeaveIfError(error);
+	CleanupClosePushL(readFile);
+	//
+	RFileReadStream readStream(readFile);
+	CleanupClosePushL(readStream);
+	parser->InternalizeL(readStream);
+	CleanupStack::PopAndDestroy(2); // readStream, readFile
+	//
+	return parser;
+	}
+
+/**
+ * Returns the property parameter name value used by Versit for this particular
+ * Contacts Model field type (E.g. HOME, WORK, PREF, etc). Returns KNullDesC in
+ * the case of General Address. Panic (fails the test) if the type is not recognised.
+ */
+static TPtrC8 VersitPropertyParameterNameForContactsModelFieldType(TFieldType aAddressType)
+	{
+	TPtrC8 propParamValue(KNullDesC8);
+	//
+	switch(aAddressType.iUid)
+		{
+	case KIntContactFieldVCardMapHOME:
+		propParamValue.Set(KVersitParam8Home);
+		break;
+	case KIntContactFieldVCardMapWORK:
+		propParamValue.Set(KVersitParam8Work);
+		break;
+	case KIntContactFieldVCardMapPREF:
+		propParamValue.Set(KVersitParam8Pref);
+		break;
+	case KIntContactFieldVCardMapGENERALADDRESS:
+		break;
+	default:
+		TheTest(EFalse);
+		break;
+		}
+	//
+	return propParamValue;
+	}
+
+/**
+ * Search a vCard property for the presence of a specific address type, e.g. HOME, WORK, PREF or "General"
+ */
+static TBool ValidateVCardPropertyForAddressType(const CParserProperty& aProperty, const TDesC8& aPropertyParameterType)
+	{
+	TBool validated = EFalse;
+
+	// Have to perform more substancial checks if we're looking for just a general address...
+	if	(aPropertyParameterType.Length())
+		{
+		// HOME, WORK, PREF
+		validated = (aProperty.Param(aPropertyParameterType) != NULL);
+		}
+	else
+		{
+		// In the case of General Address, which won't have an associated property parameter
+		// we must check that none of the other types are present for this address. If none are
+		// matched, then this address can be considered general.
+		const TBool foundHOME = (aProperty.Param(KVersitParam8Home) != NULL);
+		const TBool foundWORK = (aProperty.Param(KVersitParam8Work) != NULL);
+		const TBool foundPREF = (aProperty.Param(KVersitParam8Pref) != NULL);
+		//
+		validated = !(foundHOME || foundWORK || foundPREF);
+		}
+	//
+	return validated;
+	}
+
+/**
+ * Check that the specified actual value found in the vCard matches the expected value
+ * which is constructed from the raw value and post fix.
+ */
+static TBool ValidateAddressSubFieldL(const TDesC& aActualValue, const TDesC& aExpectedRawValue, const TDesC& aPostFix)
+	{
+	HBufC* expectedValue = ConstructAddressValueLC(aExpectedRawValue, aPostFix);
+	const TBool match = (expectedValue->CompareF(aActualValue) == 0);
+	CleanupStack::PopAndDestroy(expectedValue);
+	//
+	return match;
+	}
+
+/**
+ * Check that the specified array contains exact matches for each of the 7 address
+ * sub field values.
+ */
+static TBool ValidateAddressSubFieldValuesL(const CDesCArray& aArray, const TDesC& aPostFix)
+	{
+	TPtrC actualValue;
+	//
+	actualValue.Set(aArray[0]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressPOSTOFFICE, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[1]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressEXTENDEDADR, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[2]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressADR, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[3]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressLOCALITY, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[4]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressREGION, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[5]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressPOSTCODE, aPostFix))
+		return EFalse;
+	actualValue.Set(aArray[6]);
+	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressCOUNTRY, aPostFix))
+		return EFalse;
+	//
+	return ETrue;
+	}
+
+/**
+ * Check a vCard for the presence of a specific address type. Returns ETrue
+ * if the type is found within the vCard.
+ */
+static TBool ValidateVCardForAddressL(CParserVCard& aVCard, TFieldType aAddressType)
+	{
+	TBool validated = EFalse;
+	const TUid KVersitAddressPropertyValueType = { KVersitPropertyCDesCArrayUid };
+	const TPtrC8 propValueType = VersitPropertyParameterNameForContactsModelFieldType(aAddressType);
+	//
+	CArrayPtr<CParserProperty>* properties = aVCard.PropertyL(KVersitTokenADR, KVersitAddressPropertyValueType, EFalse);
+	if	(properties)
+		{
+		CleanupStack::PushL(properties);
+		const TInt count = properties->Count();
+		for(TInt i=0; i<count || !validated; i++)
+			{
+			// First verify the property parameters
+			CParserProperty& property = *properties->At(i);
+			if	(ValidateVCardPropertyForAddressType(property, propValueType))
+				{
+				// Next verify the property values
+				CParserPropertyValueCDesCArray* value = static_cast<CParserPropertyValueCDesCArray*>(property.Value());
+				CDesCArray* array = value->Value();
+
+				// There must be 7 sub-fields
+				if	(array->MdcaCount() == 7)
+					{
+					// Check each sub-field for the correct value
+					const TPtrC postFix = PostFixForFieldType(aAddressType);
+					validated = ValidateAddressSubFieldValuesL(*array, postFix);
+					}
+				}
+			}
+		CleanupStack::PopAndDestroy(properties);
+		}
+	return validated;
+	}
+
+/**
+ * Create a vCard N property and add it to the specified vCard parser object
+ */
+static void AddNameToVCardL(CParserVCard& aVCard)
+	{
+	// For the property value itself
+	CDesCArrayFlat* desArray = new (ELeave)CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+
+	// Add the names
+	desArray->AppendL(KTestNameFamily);
+	desArray->AppendL(KTestNameGiven);
+	desArray->AppendL(KNullDesC);
+	desArray->AppendL(KNullDesC);
+	desArray->AppendL(KNullDesC);
+
+	// Create the property value
+	CParserPropertyValue* value = new(ELeave) CParserPropertyValueCDesCArray(desArray);
+	CleanupStack::Pop(desArray);
+	CleanupStack::PushL(value);
+	//
+	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenN, NULL, NULL);
+	CleanupStack::Pop(value); // value
+
+	// This pushes property before anything can leave...
+	aVCard.AddPropertyL(property);
+	}
+
+/**
+ * Combine the address data and the post fix to form a new combined address data value
+ * and append it to the specified array
+ */
+static void AddAddressSubFieldToArrayL(CDesCArray& aArray, const TDesC& aAddress, const TDesC& aPostFix)
+	{
+	HBufC* value = ConstructAddressValueLC(aAddress, aPostFix);
+	aArray.AppendL(*value);
+	CleanupStack::PopAndDestroy(value);
+	}
+
+/**
+ * Create a vCard ADR property and add it to the specified vCard parser object
+ */
+static void AddAddressToVCardL(CParserVCard& aVCard, const TDesC8& aAddressType)
+	{
+	// For the property parameters
+    CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy, arrayOfParams));
+
+	// If the address type is NULL then its a general address, in which case it doesn't
+	// need a property parameter. Otherwise, assume it does
+	if	(aAddressType.Length())
+		{
+		CParserParam* parserParam = CParserParam::NewL(aAddressType, KNullDesC);
+		CleanupStack::PushL(parserParam);
+		arrayOfParams->AppendL(parserParam);
+		CleanupStack::Pop(parserParam);
+		}
+
+	// Create the value array
+	CDesCArrayFlat* desArray = new (ELeave)CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+
+	// Pick the correct postfix
+	TPtrC postFix(KNullDesC);
+	if	(aAddressType == KVersitParam8Home)
+		postFix.Set(KTestAddressHOME);
+	else if (aAddressType == KVersitParam8Work)
+		postFix.Set(KTestAddressWORK);
+	else if (aAddressType == KVersitParam8Pref)
+		postFix.Set(KTestAddressPREF);
+	else if (aAddressType == KVersitParam8GeneralAddress)
+		postFix.Set(KTestAddressGENERALADDRESS);
+
+	// Add the names
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressPOSTOFFICE, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressEXTENDEDADR, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressADR, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressLOCALITY, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressREGION, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressPOSTCODE, postFix);
+	AddAddressSubFieldToArrayL(*desArray, KTestAddressCOUNTRY, postFix);
+
+	// Create the property value
+	CParserPropertyValue* value = new (ELeave) CParserPropertyValueCDesCArray(desArray);
+	CleanupStack::Pop(desArray);
+	CleanupStack::PushL(value);
+
+	// And finally, the property itself
+	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenADR, NULL, arrayOfParams);
+	CleanupStack::Pop(2, arrayOfParams); // value, arrayOfParams
+
+	// Add to vCard object - takes ownership of property immediately
+	aVCard.AddPropertyL(property);
+	}
+
+/**
+ * Create a simple vCard which contains only an N (Name) property
+ */
+static CParserVCard* CreateVCardLC()
+	{
+	CParserVCard* parser = CParserVCard::NewL();
+	CleanupStack::PushL(parser);
+	//
+	AddNameToVCardL(*parser);
+	//
+	return parser;
+	}
+
+/**
+ * Export the specified vCard object to a file
+ */
+static void CreateVCardFileFromVCardObjectL(CParserVCard& aVCard, RFs& aFsSession, const TDesC& aVCardFileName)
+	{
+	RFile outfile;
+	const TInt error = outfile.Replace(aFsSession, aVCardFileName, EFileWrite);
+	User::LeaveIfError(error);
+	CleanupClosePushL(outfile);
+	//
+	RFileWriteStream writeStream(outfile);
+	CleanupClosePushL(writeStream);
+	//
+	aVCard.ExternalizeL(writeStream);
+	writeStream.CommitL();
+	CleanupStack::PopAndDestroy(2); // writeStream, outfile
+	}
+
+/**
+ * Import the specified vCard to the contacts database and return the newly created contact item
+ */
+static CContactItem* ImportVCardLC(CContactDatabase& aDatabase, RFs& aFsSession, const TDesC& aVCardFileName)
+	{
+	RFile readFile;
+	const TInt error = readFile.Open(aFsSession, aVCardFileName, EFileRead);
+	User::LeaveIfError(error);
+	CleanupClosePushL(readFile);
+	//
+	RFileReadStream readStream(readFile);
+	CleanupClosePushL(readStream);
+	//
+	TBool importSuccessful = EFalse;
+	const TInt options = CContactDatabase::EDefault;
+	const TUid KVersitVCardUid = { KUidVCardConvDefaultImpl };
+	//
+	CArrayPtr<CContactItem>* contacts = aDatabase.ImportContactsL(KVersitVCardUid, readStream, importSuccessful, options);
+	CleanupStack::PopAndDestroy(2); // readStream, readFile
+
+	// Check import results
+	TheTest(importSuccessful);
+	TheTest(contacts != NULL);
+	TheTest(contacts->Count() == 1);
+
+	// Delete container, but not the contact itself
+	CContactItem* item = contacts->At(0);
+	CleanupStack::PushL(item);
+	delete contacts;
+	return item;
+	}
+
+/**
+ * Check the specified field set for the presence of a specific field which conforms
+ * to the specified address type
+ */
+static TBool LocateAddressFieldByType(CContactItemFieldSet& aFieldSet, TFieldType aFieldType, TUid aMapping, const TDesC& aExpectedValue, const TDesC& aExpectedPostFix)
+	{
+	TBool located = EFalse;
+
+	// Locate field
+	TInt pos = KErrNotFound;
+	if	(aFieldType != KNullUid) // KNullUid is for general address
+		pos = aFieldSet.Find(aFieldType, aMapping);
+	else
+		pos = aFieldSet.Find(aMapping);
+	//
+	if	(pos != KErrNotFound)
+		{
+		// Make real value
+		HBufC* value = ConstructAddressValueLC(aExpectedValue, aExpectedPostFix);
+
+		// Verify
+		CContactItemField& field = aFieldSet[pos];
+		CContactTextField* storage = field.TextStorage();
+		located = (storage->Text().CompareF(*value) == 0);
+		//
+		CleanupStack::PopAndDestroy(value);
+		}
+	//
+	return located;
+	}
+
+/**
+ * Check the specified contact card contains an address corresponding to the specified type
+ */
+static TBool ValidateContactForAddressTypeL(CContactItem& aContact, TFieldType aAddressType)
+	{
+	CContactItemFieldSet& fieldSet = aContact.CardFields();
+	const TPtrC postFix(PostFixForFieldType(aAddressType));
+	//
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapPOSTOFFICE, KTestAddressPOSTOFFICE, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapEXTENDEDADR, KTestAddressEXTENDEDADR, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapADR, KTestAddressADR, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapLOCALITY, KTestAddressLOCALITY, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapREGION, KTestAddressREGION, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapPOSTCODE, KTestAddressPOSTCODE, postFix))
+		return EFalse;
+	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapCOUNTRY, KTestAddressCOUNTRY, postFix))
+		return EFalse;
+	//
+	return ETrue;
+	}
+
+
+// Tests
+
+static void Test1L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("EXPORT General address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	const TContactItemId contactId = CreateContactL(database);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
+	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
+	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
+	CleanupStack::PopAndDestroy(parser);
+	}
+
+static void Test2L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("EXPORT General, Home address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	const TContactItemId contactId = CreateContactL(database);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapHOME);
+	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
+	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapHOME));
+	CleanupStack::PopAndDestroy(parser);
+	}
+
+static void Test3L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("EXPORT General, Work address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	const TContactItemId contactId = CreateContactL(database);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapWORK);
+	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
+	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapWORK));
+	CleanupStack::PopAndDestroy(parser);
+	}
+
+
+static void Test4L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("EXPORT General, Home, Work address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	const TContactItemId contactId = CreateContactL(database);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapHOME);
+	AddAddressL(database, contactId, KUidContactFieldVCardMapWORK);
+	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
+	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapHOME));
+	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapWORK));
+	CleanupStack::PopAndDestroy(parser);
+	}
+
+
+static void Test5L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("IMPORT General address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	CParserVCard* vCard = CreateVCardLC();
+	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
+	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
+	CleanupStack::PopAndDestroy(vCard);
+	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
+	CleanupStack::PopAndDestroy(item);
+	}
+
+static void Test6L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("IMPORT General, Home address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	CParserVCard* vCard = CreateVCardLC();
+	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
+	AddAddressToVCardL(*vCard, KVersitParam8Home);
+	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
+	CleanupStack::PopAndDestroy(vCard);
+	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapHOME));
+	CleanupStack::PopAndDestroy(item);
+	}
+
+
+static void Test7L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("IMPORT General, Work address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	//
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	CParserVCard* vCard = CreateVCardLC();
+	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
+	AddAddressToVCardL(*vCard, KVersitParam8Work);
+	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
+	CleanupStack::PopAndDestroy(vCard);
+	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapWORK));
+	CleanupStack::PopAndDestroy(item);
+	}
+
+
+static void Test8L(TBool& aPrintedTestTitle)
+	{
+	if	(!aPrintedTestTitle)
+		{
+		TheTest.Next(_L("IMPORT General, Home, Work address"));
+
+		aPrintedTestTitle = ETrue;
+		}
+	RFs& fsSession = TheTestHelper->Fs();
+	CContactDatabase& database = *TheTestHelper->Db();
+	//
+	CParserVCard* vCard = CreateVCardLC();
+	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
+	AddAddressToVCardL(*vCard, KVersitParam8Home);
+	AddAddressToVCardL(*vCard, KVersitParam8Work);
+	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
+	CleanupStack::PopAndDestroy(vCard);
+	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapHOME));
+	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapWORK));
+	CleanupStack::PopAndDestroy(item);
+	}
+
+static void RunListOfTestsL(const RArray<TGAFunction>& aTests)
+	{
+	TBool printedTestTitle = EFalse;
+	const TInt count = aTests.Count();
+	for(TInt i=0; i<count; i++)
+		{
+		TGAFunction test = aTests[i];
+		TheTestHelper->CreateDatabaseL();
+		TRAPD(err, (*test)(printedTestTitle));
+
+		// Ensure that we close the database if a leave occurs or
+		// else the OOM test code thinks we've leaked it
+		TheTestHelper->CloseDatabase();
+
+		// Cascade error
+		User::LeaveIfError(err);
+
+		printedTestTitle = EFalse;
+		}
+	}
+
+static void TestExportL()
+	{
+	RArray<TGAFunction> array;
+	CleanupClosePushL(array);
+	//
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test1L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test2L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test3L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test4L)));
+	//
+	RunListOfTestsL(array);
+	//
+	CleanupStack::PopAndDestroy(&array);
+	}
+
+static void TestImportL()
+	{
+	RArray<TGAFunction> array;
+	CleanupClosePushL(array);
+	//
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test5L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test6L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test7L)));
+	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test8L)));
+	//
+	RunListOfTestsL(array);
+	//
+	CleanupStack::PopAndDestroy(&array);
+	}
+
+
+static void RunTestsL()
+	{
+	TRAPD(errExport, TestExportL());
+	TheTest(errExport == KErrNone || errExport == KErrNoMemory);
+	//
+	TRAPD(errImport, TestImportL());
+	TheTest(errImport == KErrNone || errImport == KErrNoMemory);
+	}
+
+#ifdef OOM_TESTS
+
+static void ExpandCleanupStackL()
+	{
+	// Reserve some space on the cleanup stack:
+		{
+		for (TInt ii=0;ii<1000;++ii)
+			CleanupStack::PushL(&ii);
+		}
+	CleanupStack::Pop(1000);
+	}
+
+static void PrepareTestSkipsL(RArray<TInt>& aSkipArray, TInt aCount, ...)
+	{
+	aSkipArray.Reset();
+	//
+    VA_LIST list;
+    VA_START(list, aCount);
+	//
+	TInt* startPtr = reinterpret_cast<TInt*>(&list); // Same as list[0]
+	for(TInt i=0; i<aCount; i++)
+		{
+		const TInt cycle = startPtr[i];
+		aSkipArray.AppendL(cycle);
+		}
+	}
+
+
+static TInt RunOOMTestL(TGAFunction aFunction, const RArray<TInt>& aSkipArray)
+	{
+	//
+	TBool printedTestTitle = EFalse;
+	TInt ret = KErrNoMemory;
+	TInt failAt = 0;
+	while(ret != KErrNone)
+		{
+		failAt += failAt/50 + 1;
+		TheTest.Printf(_L("OOM step: %d\n"), failAt);
+		if (aSkipArray.Find(failAt) != KErrNotFound)
+			continue;
+		//
+		__UHEAP_MARK;
+		TheTestHelper->CreateDatabaseL();
+
+		__UHEAP_SETFAIL(RHeap::EDeterministic, failAt);
+		TRAP(ret, aFunction(printedTestTitle));
+		__UHEAP_RESET;
+
+		// Ensure that we close the database
+		TheTestHelper->CloseDatabase();
+
+
+		__UHEAP_MARKEND;
+		//
+		if	(ret != KErrNoMemory && ret != KErrNone)
+			{
+			TheTest.Printf(_L("Non standard error: %d\n"),ret);
+			TheTest.Getch();
+			}
+		TheTest(ret == KErrNoMemory || ret == KErrNone);
+		}
+	//
+	return KErrNone;
+	}
+
+static void RunOOMTestsL()
+	{
+	ExpandCleanupStackL();
+	//
+	RArray<TInt> knownFailures;
+	CleanupClosePushL(knownFailures);
+
+	// EXPORT
+	PrepareTestSkipsL(knownFailures, 0);
+	RunOOMTestL(Test1L, knownFailures);
+	//
+	// (Skip OOM on Test2L, Test3L and Test4L as they execute the same code as Test1L)
+
+	// IMPORT
+	PrepareTestSkipsL(knownFailures, 0);
+	RunOOMTestL(Test5L, knownFailures);
+	//
+	// (Skip OOM on Test6L, Test7L and Test8L as they execute the same code as Test5L)
+
+	CleanupStack::PopAndDestroy(&knownFailures);
+	}
+#endif
+
+static void DoMainL()
+	{
+	CTestRegister* TempFiles = CTestRegister::NewLC();
+	TempFiles->RegisterL(KTestDatabaseFile, EFileTypeCnt);
+	TempFiles->RegisterL(KTestVCardExportFileName);
+	TempFiles->RegisterL(KTestVCardImportFileName);
+
+	// Run normal testing
+	TRAPD(testRet, RunTestsL());
+	TheTest(testRet == KErrNone);
+
+	// Run OOM testing
+#ifdef OOM_TESTS
+	TRAPD(oomRet, RunOOMTestsL());
+	TheTest(oomRet == KErrNone);
+#endif
+
+	CleanupStack::PopAndDestroy(TempFiles);
+	}
+
+/**
+
+@SYMTestCaseID     PIM-T-GENERALADDRESS-0001
+
+*/
+
+GLDEF_C TInt E32Main()
+	{
+	__UHEAP_MARK;
+	TheTest.Start(_L("@SYMTESTCaseID:PIM-T-GENERALADDRESS-0001 T_GENERALADDRESS - Test General Address Export and Import"));
+
+
+	// Stupid test library alert...
+	TheTestHelper = new(ELeave) CCntTest();
+	TheTestHelper->ConstructL(TheTest, KTestDatabaseFile);
+
+	TRAP_IGNORE(DoMainL());
+	//
+	TheTestHelper->EndTestLib(KErrNone);
+	//
+	__UHEAP_MARKEND;
+	return(KErrNone);
+    }