phonebookengines_old/contactsmodel/tsrc/T_GENERALADDRESS.CPP
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // System includes
       
    17 #include <e32test.h>
       
    18 #include <f32file.h>
       
    19 #include <s32file.h>
       
    20 #include <cntdb.h>
       
    21 #include <cntdef.h>
       
    22 #include <cntitem.h>
       
    23 #include <cntfield.h>
       
    24 #include <cntfldst.h>
       
    25 #include <bautils.h>
       
    26 #include <barsc.h>
       
    27 #include <barsread.h>
       
    28 #include <versit.h>
       
    29 #include <vcard.h>
       
    30 #include <e32def.h>
       
    31 #include <coreappstest/testserver.h>
       
    32 // User includes
       
    33 #include "T_UTILS.H"
       
    34 
       
    35 // Flags
       
    36 #define OOM_TESTS
       
    37 
       
    38 // Globals
       
    39 static RTest TheTest(_L("T_GENERALADDRESS - Test General Address Export and Import"));
       
    40 static CCntTest* TheTestHelper;
       
    41 
       
    42 // Type definitions
       
    43 typedef void (*TGAFunction)(TBool& aPrintedTestTitle);
       
    44 
       
    45 // Constants
       
    46 const TInt KIntContactFieldVCardMapGENERALADDRESS = 0;
       
    47 const TUid KUidContactFieldVCardMapGENERALADDRESS = { KIntContactFieldVCardMapGENERALADDRESS };
       
    48 
       
    49 // Literal constants
       
    50 _LIT(KTestDatabaseFile, "C:GeneralAddressDatabase.cdb");
       
    51 //
       
    52 _LIT(KTestNameFamily, "Bloggs");
       
    53 _LIT(KTestNameGiven, "Joe");
       
    54 //
       
    55 _LIT(KTestAddressHOME, "_HOME");
       
    56 _LIT(KTestAddressWORK, "_WORK");
       
    57 _LIT(KTestAddressPREF, "_PREF");
       
    58 _LIT(KTestAddressGENERALADDRESS, "_GENERALADDRESS");
       
    59 //
       
    60 _LIT(KTestAddressPOSTOFFICE, "POSTOFFICE");
       
    61 _LIT(KTestAddressEXTENDEDADR, "EXTENDEDADR");
       
    62 _LIT(KTestAddressADR, "ADR");
       
    63 _LIT(KTestAddressLOCALITY, "LOCALITY");
       
    64 _LIT(KTestAddressREGION, "REGION");
       
    65 _LIT(KTestAddressPOSTCODE, "POSTCODE");
       
    66 _LIT(KTestAddressCOUNTRY, "COUNTRY");
       
    67 //
       
    68 _LIT(KTestVCardExportFileName, "C:\\T_GENERALADDRESS_EXPORTED.TXT");
       
    69 _LIT(KTestVCardImportFileName, "C:\\T_GENERALADDRESS_IMPORTED.TXT");
       
    70 //
       
    71 _LIT8(KVersitParam8GeneralAddress, "");
       
    72 
       
    73 
       
    74 // Utility methods
       
    75 
       
    76 /**
       
    77  * Create a simple contact with just the name fields populated
       
    78  */
       
    79 static TContactItemId CreateContactL(CContactDatabase& aDatabase)
       
    80 	{
       
    81 	const TContactItemId templateId = aDatabase.TemplateId();
       
    82 	//
       
    83 	CContactItem* templateCard = aDatabase.ReadContactLC(templateId);
       
    84 	CContactCard* card = CContactCard::NewL(templateCard);
       
    85 	CleanupStack::PushL(card);
       
    86 	//
       
    87 	SetNameL(*card, KUidContactFieldFamilyName, KUidContactFieldVCardMapUnusedN, KTestNameFamily, EFalse);
       
    88 	SetNameL(*card, KUidContactFieldGivenName, KUidContactFieldVCardMapUnusedN, KTestNameGiven, EFalse);
       
    89 	//
       
    90 	const TContactItemId id = aDatabase.AddNewContactL(*card);
       
    91 	CleanupStack::PopAndDestroy(2, templateCard);
       
    92 	return id;
       
    93 	}
       
    94 
       
    95 /**
       
    96  * Combine a value and a postfix to create a real unified value
       
    97  */
       
    98 static HBufC* ConstructAddressValueLC(const TDesC& aValue, const TDesC& aPostFix)
       
    99 	{
       
   100 	HBufC* value = HBufC::NewLC(aValue.Length() + aPostFix.Length());
       
   101 	TPtr pValue(value->Des());
       
   102 	pValue = aValue;
       
   103 	pValue.Append(aPostFix);
       
   104 	//
       
   105 	return value;
       
   106 	}
       
   107 
       
   108 /**
       
   109  * Add a specific address field to a vCard
       
   110  */
       
   111 static void AddAddressFieldL(CContactItem& aContact, TFieldType aFieldType, TUid aMapping, TFieldType aExtraFieldType, const TDesC& aValue, const TDesC& aValuePostFix)
       
   112 	{
       
   113 	CContentType* content = CContentType::NewL(aFieldType, aMapping);
       
   114 	CleanupStack::PushL(content);
       
   115 	content->AddFieldTypeL(aExtraFieldType);
       
   116 	//
       
   117 	CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, *content);
       
   118 	//
       
   119 	HBufC* value = ConstructAddressValueLC(aValue, aValuePostFix);
       
   120 	//
       
   121 	contactItemField->TextStorage()->SetStandardTextL(*value);
       
   122 	CleanupStack::PopAndDestroy(value);
       
   123 	//
       
   124 	aContact.AddFieldL(*contactItemField);
       
   125 	CleanupStack::Pop(contactItemField);
       
   126 	//
       
   127 	CleanupStack::PopAndDestroy(content);
       
   128 	}
       
   129 
       
   130 /**
       
   131  * Return the post fix descriptor for a given field type (HOME, WORK, PREF, General)
       
   132  */
       
   133 static TPtrC PostFixForFieldType(TFieldType aType)
       
   134 	{
       
   135 	TPtrC postFix(KNullDesC);
       
   136 	switch(aType.iUid)
       
   137 		{
       
   138 	case KIntContactFieldVCardMapHOME:
       
   139 		postFix.Set(KTestAddressHOME);
       
   140 		break;
       
   141 	case KIntContactFieldVCardMapWORK:
       
   142 		postFix.Set(KTestAddressWORK);
       
   143 		break;
       
   144 	case KIntContactFieldVCardMapPREF:
       
   145 		postFix.Set(KTestAddressPREF);
       
   146 		break;
       
   147 	case KIntContactFieldVCardMapGENERALADDRESS:
       
   148 		postFix.Set(KTestAddressGENERALADDRESS);
       
   149 		break;
       
   150 	default:
       
   151 		TheTest(EFalse);
       
   152 		break;
       
   153 		}
       
   154 	//
       
   155 	return postFix;
       
   156 	}
       
   157 
       
   158 /**
       
   159  * Add a specific address type to a contact card
       
   160  */
       
   161 static void AddAddressL(CContactDatabase& aDatabase, TContactItemId aId, TFieldType aExtraFieldType)
       
   162 	{
       
   163 	const TPtrC postFix(PostFixForFieldType(aExtraFieldType));
       
   164 	//
       
   165 	CContactItem* card = aDatabase.OpenContactLX(aId);
       
   166 	CleanupStack::PushL(card);
       
   167 	//
       
   168 	AddAddressFieldL(*card, KUidContactFieldPostOffice, KUidContactFieldVCardMapPOSTOFFICE, aExtraFieldType, KTestAddressPOSTOFFICE, postFix);
       
   169 	AddAddressFieldL(*card, KUidContactFieldExtendedAddress, KUidContactFieldVCardMapEXTENDEDADR, aExtraFieldType, KTestAddressEXTENDEDADR, postFix);
       
   170 	AddAddressFieldL(*card, KUidContactFieldAddress, KUidContactFieldVCardMapADR, aExtraFieldType, KTestAddressADR, postFix);
       
   171 	AddAddressFieldL(*card, KUidContactFieldLocality, KUidContactFieldVCardMapLOCALITY, aExtraFieldType, KTestAddressLOCALITY, postFix);
       
   172 	AddAddressFieldL(*card, KUidContactFieldRegion, KUidContactFieldVCardMapREGION, aExtraFieldType, KTestAddressREGION, postFix);
       
   173 	AddAddressFieldL(*card, KUidContactFieldPostcode, KUidContactFieldVCardMapPOSTCODE, aExtraFieldType, KTestAddressPOSTCODE, postFix);
       
   174 	AddAddressFieldL(*card, KUidContactFieldCountry, KUidContactFieldVCardMapCOUNTRY, aExtraFieldType, KTestAddressCOUNTRY, postFix);
       
   175 	//
       
   176 	aDatabase.CommitContactL(*card);
       
   177 	CleanupStack::PopAndDestroy(card);
       
   178 	CleanupStack::Pop(); // lock record
       
   179 	}
       
   180 
       
   181 /**
       
   182  * Export a specific contact to a vCard file
       
   183  */
       
   184 static void ExportContactAsVCardL(CContactDatabase& aDatabase, TContactItemId aId, RFs& aFsSession, const TDesC& aVCardFileName)
       
   185 	{
       
   186 	CContactIdArray* idArray = CContactIdArray::NewLC();
       
   187 	idArray->AddL(aId);
       
   188 	//
       
   189 	RFile outfile;
       
   190 	const TInt error = outfile.Replace(aFsSession, aVCardFileName, EFileWrite);
       
   191 	User::LeaveIfError(error);
       
   192 	CleanupClosePushL(outfile);
       
   193 	//
       
   194 	RFileWriteStream writeStream(outfile);
       
   195 	CleanupClosePushL(writeStream);
       
   196 	//
       
   197 	const TUid KVersitVCardUid = { KUidVCardConvDefaultImpl };
       
   198 	aDatabase.ExportSelectedContactsL(KVersitVCardUid, *idArray, writeStream, CContactDatabase::EDefault);
       
   199 	writeStream.CommitL();
       
   200 	CleanupStack::PopAndDestroy(3, idArray); // writeStream, outfile, idArray
       
   201 	}
       
   202 
       
   203 /**
       
   204  * Parse a file using the Symbian vCard parser and return the parsed data structures
       
   205  * to the caller
       
   206  */
       
   207 static CParserVCard* ParseVCardFileLC(RFs& aFsSession, const TDesC& aVCardFileName)
       
   208 	{
       
   209 	CParserVCard* parser = CParserVCard::NewL();
       
   210 	CleanupStack::PushL(parser);
       
   211 	//
       
   212 	RFile readFile;
       
   213 	const TInt error = readFile.Open(aFsSession, aVCardFileName, EFileRead);
       
   214 	User::LeaveIfError(error);
       
   215 	CleanupClosePushL(readFile);
       
   216 	//
       
   217 	RFileReadStream readStream(readFile);
       
   218 	CleanupClosePushL(readStream);
       
   219 	parser->InternalizeL(readStream);
       
   220 	CleanupStack::PopAndDestroy(2); // readStream, readFile
       
   221 	//
       
   222 	return parser;
       
   223 	}
       
   224 
       
   225 /**
       
   226  * Returns the property parameter name value used by Versit for this particular
       
   227  * Contacts Model field type (E.g. HOME, WORK, PREF, etc). Returns KNullDesC in
       
   228  * the case of General Address. Panic (fails the test) if the type is not recognised.
       
   229  */
       
   230 static TPtrC8 VersitPropertyParameterNameForContactsModelFieldType(TFieldType aAddressType)
       
   231 	{
       
   232 	TPtrC8 propParamValue(KNullDesC8);
       
   233 	//
       
   234 	switch(aAddressType.iUid)
       
   235 		{
       
   236 	case KIntContactFieldVCardMapHOME:
       
   237 		propParamValue.Set(KVersitParam8Home);
       
   238 		break;
       
   239 	case KIntContactFieldVCardMapWORK:
       
   240 		propParamValue.Set(KVersitParam8Work);
       
   241 		break;
       
   242 	case KIntContactFieldVCardMapPREF:
       
   243 		propParamValue.Set(KVersitParam8Pref);
       
   244 		break;
       
   245 	case KIntContactFieldVCardMapGENERALADDRESS:
       
   246 		break;
       
   247 	default:
       
   248 		TheTest(EFalse);
       
   249 		break;
       
   250 		}
       
   251 	//
       
   252 	return propParamValue;
       
   253 	}
       
   254 
       
   255 /**
       
   256  * Search a vCard property for the presence of a specific address type, e.g. HOME, WORK, PREF or "General"
       
   257  */
       
   258 static TBool ValidateVCardPropertyForAddressType(const CParserProperty& aProperty, const TDesC8& aPropertyParameterType)
       
   259 	{
       
   260 	TBool validated = EFalse;
       
   261 
       
   262 	// Have to perform more substancial checks if we're looking for just a general address...
       
   263 	if	(aPropertyParameterType.Length())
       
   264 		{
       
   265 		// HOME, WORK, PREF
       
   266 		validated = (aProperty.Param(aPropertyParameterType) != NULL);
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		// In the case of General Address, which won't have an associated property parameter
       
   271 		// we must check that none of the other types are present for this address. If none are
       
   272 		// matched, then this address can be considered general.
       
   273 		const TBool foundHOME = (aProperty.Param(KVersitParam8Home) != NULL);
       
   274 		const TBool foundWORK = (aProperty.Param(KVersitParam8Work) != NULL);
       
   275 		const TBool foundPREF = (aProperty.Param(KVersitParam8Pref) != NULL);
       
   276 		//
       
   277 		validated = !(foundHOME || foundWORK || foundPREF);
       
   278 		}
       
   279 	//
       
   280 	return validated;
       
   281 	}
       
   282 
       
   283 /**
       
   284  * Check that the specified actual value found in the vCard matches the expected value
       
   285  * which is constructed from the raw value and post fix.
       
   286  */
       
   287 static TBool ValidateAddressSubFieldL(const TDesC& aActualValue, const TDesC& aExpectedRawValue, const TDesC& aPostFix)
       
   288 	{
       
   289 	HBufC* expectedValue = ConstructAddressValueLC(aExpectedRawValue, aPostFix);
       
   290 	const TBool match = (expectedValue->CompareF(aActualValue) == 0);
       
   291 	CleanupStack::PopAndDestroy(expectedValue);
       
   292 	//
       
   293 	return match;
       
   294 	}
       
   295 
       
   296 /**
       
   297  * Check that the specified array contains exact matches for each of the 7 address
       
   298  * sub field values.
       
   299  */
       
   300 static TBool ValidateAddressSubFieldValuesL(const CDesCArray& aArray, const TDesC& aPostFix)
       
   301 	{
       
   302 	TPtrC actualValue;
       
   303 	//
       
   304 	actualValue.Set(aArray[0]);
       
   305 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressPOSTOFFICE, aPostFix))
       
   306 		return EFalse;
       
   307 	actualValue.Set(aArray[1]);
       
   308 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressEXTENDEDADR, aPostFix))
       
   309 		return EFalse;
       
   310 	actualValue.Set(aArray[2]);
       
   311 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressADR, aPostFix))
       
   312 		return EFalse;
       
   313 	actualValue.Set(aArray[3]);
       
   314 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressLOCALITY, aPostFix))
       
   315 		return EFalse;
       
   316 	actualValue.Set(aArray[4]);
       
   317 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressREGION, aPostFix))
       
   318 		return EFalse;
       
   319 	actualValue.Set(aArray[5]);
       
   320 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressPOSTCODE, aPostFix))
       
   321 		return EFalse;
       
   322 	actualValue.Set(aArray[6]);
       
   323 	if	(!ValidateAddressSubFieldL(actualValue, KTestAddressCOUNTRY, aPostFix))
       
   324 		return EFalse;
       
   325 	//
       
   326 	return ETrue;
       
   327 	}
       
   328 
       
   329 /**
       
   330  * Check a vCard for the presence of a specific address type. Returns ETrue
       
   331  * if the type is found within the vCard.
       
   332  */
       
   333 static TBool ValidateVCardForAddressL(CParserVCard& aVCard, TFieldType aAddressType)
       
   334 	{
       
   335 	TBool validated = EFalse;
       
   336 	const TUid KVersitAddressPropertyValueType = { KVersitPropertyCDesCArrayUid };
       
   337 	const TPtrC8 propValueType = VersitPropertyParameterNameForContactsModelFieldType(aAddressType);
       
   338 	//
       
   339 	CArrayPtr<CParserProperty>* properties = aVCard.PropertyL(KVersitTokenADR, KVersitAddressPropertyValueType, EFalse);
       
   340 	if	(properties)
       
   341 		{
       
   342 		CleanupStack::PushL(properties);
       
   343 		const TInt count = properties->Count();
       
   344 		for(TInt i=0; i<count || !validated; i++)
       
   345 			{
       
   346 			// First verify the property parameters
       
   347 			CParserProperty& property = *properties->At(i);
       
   348 			if	(ValidateVCardPropertyForAddressType(property, propValueType))
       
   349 				{
       
   350 				// Next verify the property values
       
   351 				CParserPropertyValueCDesCArray* value = static_cast<CParserPropertyValueCDesCArray*>(property.Value());
       
   352 				CDesCArray* array = value->Value();
       
   353 
       
   354 				// There must be 7 sub-fields
       
   355 				if	(array->MdcaCount() == 7)
       
   356 					{
       
   357 					// Check each sub-field for the correct value
       
   358 					const TPtrC postFix = PostFixForFieldType(aAddressType);
       
   359 					validated = ValidateAddressSubFieldValuesL(*array, postFix);
       
   360 					}
       
   361 				}
       
   362 			}
       
   363 		CleanupStack::PopAndDestroy(properties);
       
   364 		}
       
   365 	return validated;
       
   366 	}
       
   367 
       
   368 /**
       
   369  * Create a vCard N property and add it to the specified vCard parser object
       
   370  */
       
   371 static void AddNameToVCardL(CParserVCard& aVCard)
       
   372 	{
       
   373 	// For the property value itself
       
   374 	CDesCArrayFlat* desArray = new (ELeave)CDesCArrayFlat(4);
       
   375 	CleanupStack::PushL(desArray);
       
   376 
       
   377 	// Add the names
       
   378 	desArray->AppendL(KTestNameFamily);
       
   379 	desArray->AppendL(KTestNameGiven);
       
   380 	desArray->AppendL(KNullDesC);
       
   381 	desArray->AppendL(KNullDesC);
       
   382 	desArray->AppendL(KNullDesC);
       
   383 
       
   384 	// Create the property value
       
   385 	CParserPropertyValue* value = new(ELeave) CParserPropertyValueCDesCArray(desArray);
       
   386 	CleanupStack::Pop(desArray);
       
   387 	CleanupStack::PushL(value);
       
   388 	//
       
   389 	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenN, NULL, NULL);
       
   390 	CleanupStack::Pop(value); // value
       
   391 
       
   392 	// This pushes property before anything can leave...
       
   393 	aVCard.AddPropertyL(property);
       
   394 	}
       
   395 
       
   396 /**
       
   397  * Combine the address data and the post fix to form a new combined address data value
       
   398  * and append it to the specified array
       
   399  */
       
   400 static void AddAddressSubFieldToArrayL(CDesCArray& aArray, const TDesC& aAddress, const TDesC& aPostFix)
       
   401 	{
       
   402 	HBufC* value = ConstructAddressValueLC(aAddress, aPostFix);
       
   403 	aArray.AppendL(*value);
       
   404 	CleanupStack::PopAndDestroy(value);
       
   405 	}
       
   406 
       
   407 /**
       
   408  * Create a vCard ADR property and add it to the specified vCard parser object
       
   409  */
       
   410 static void AddAddressToVCardL(CParserVCard& aVCard, const TDesC8& aAddressType)
       
   411 	{
       
   412 	// For the property parameters
       
   413     CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
       
   414 	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy, arrayOfParams));
       
   415 
       
   416 	// If the address type is NULL then its a general address, in which case it doesn't
       
   417 	// need a property parameter. Otherwise, assume it does
       
   418 	if	(aAddressType.Length())
       
   419 		{
       
   420 		CParserParam* parserParam = CParserParam::NewL(aAddressType, KNullDesC);
       
   421 		CleanupStack::PushL(parserParam);
       
   422 		arrayOfParams->AppendL(parserParam);
       
   423 		CleanupStack::Pop(parserParam);
       
   424 		}
       
   425 
       
   426 	// Create the value array
       
   427 	CDesCArrayFlat* desArray = new (ELeave)CDesCArrayFlat(4);
       
   428 	CleanupStack::PushL(desArray);
       
   429 
       
   430 	// Pick the correct postfix
       
   431 	TPtrC postFix(KNullDesC);
       
   432 	if	(aAddressType == KVersitParam8Home)
       
   433 		postFix.Set(KTestAddressHOME);
       
   434 	else if (aAddressType == KVersitParam8Work)
       
   435 		postFix.Set(KTestAddressWORK);
       
   436 	else if (aAddressType == KVersitParam8Pref)
       
   437 		postFix.Set(KTestAddressPREF);
       
   438 	else if (aAddressType == KVersitParam8GeneralAddress)
       
   439 		postFix.Set(KTestAddressGENERALADDRESS);
       
   440 
       
   441 	// Add the names
       
   442 	AddAddressSubFieldToArrayL(*desArray, KTestAddressPOSTOFFICE, postFix);
       
   443 	AddAddressSubFieldToArrayL(*desArray, KTestAddressEXTENDEDADR, postFix);
       
   444 	AddAddressSubFieldToArrayL(*desArray, KTestAddressADR, postFix);
       
   445 	AddAddressSubFieldToArrayL(*desArray, KTestAddressLOCALITY, postFix);
       
   446 	AddAddressSubFieldToArrayL(*desArray, KTestAddressREGION, postFix);
       
   447 	AddAddressSubFieldToArrayL(*desArray, KTestAddressPOSTCODE, postFix);
       
   448 	AddAddressSubFieldToArrayL(*desArray, KTestAddressCOUNTRY, postFix);
       
   449 
       
   450 	// Create the property value
       
   451 	CParserPropertyValue* value = new (ELeave) CParserPropertyValueCDesCArray(desArray);
       
   452 	CleanupStack::Pop(desArray);
       
   453 	CleanupStack::PushL(value);
       
   454 
       
   455 	// And finally, the property itself
       
   456 	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenADR, NULL, arrayOfParams);
       
   457 	CleanupStack::Pop(2, arrayOfParams); // value, arrayOfParams
       
   458 
       
   459 	// Add to vCard object - takes ownership of property immediately
       
   460 	aVCard.AddPropertyL(property);
       
   461 	}
       
   462 
       
   463 /**
       
   464  * Create a simple vCard which contains only an N (Name) property
       
   465  */
       
   466 static CParserVCard* CreateVCardLC()
       
   467 	{
       
   468 	CParserVCard* parser = CParserVCard::NewL();
       
   469 	CleanupStack::PushL(parser);
       
   470 	//
       
   471 	AddNameToVCardL(*parser);
       
   472 	//
       
   473 	return parser;
       
   474 	}
       
   475 
       
   476 /**
       
   477  * Export the specified vCard object to a file
       
   478  */
       
   479 static void CreateVCardFileFromVCardObjectL(CParserVCard& aVCard, RFs& aFsSession, const TDesC& aVCardFileName)
       
   480 	{
       
   481 	RFile outfile;
       
   482 	const TInt error = outfile.Replace(aFsSession, aVCardFileName, EFileWrite);
       
   483 	User::LeaveIfError(error);
       
   484 	CleanupClosePushL(outfile);
       
   485 	//
       
   486 	RFileWriteStream writeStream(outfile);
       
   487 	CleanupClosePushL(writeStream);
       
   488 	//
       
   489 	aVCard.ExternalizeL(writeStream);
       
   490 	writeStream.CommitL();
       
   491 	CleanupStack::PopAndDestroy(2); // writeStream, outfile
       
   492 	}
       
   493 
       
   494 /**
       
   495  * Import the specified vCard to the contacts database and return the newly created contact item
       
   496  */
       
   497 static CContactItem* ImportVCardLC(CContactDatabase& aDatabase, RFs& aFsSession, const TDesC& aVCardFileName)
       
   498 	{
       
   499 	RFile readFile;
       
   500 	const TInt error = readFile.Open(aFsSession, aVCardFileName, EFileRead);
       
   501 	User::LeaveIfError(error);
       
   502 	CleanupClosePushL(readFile);
       
   503 	//
       
   504 	RFileReadStream readStream(readFile);
       
   505 	CleanupClosePushL(readStream);
       
   506 	//
       
   507 	TBool importSuccessful = EFalse;
       
   508 	const TInt options = CContactDatabase::EDefault;
       
   509 	const TUid KVersitVCardUid = { KUidVCardConvDefaultImpl };
       
   510 	//
       
   511 	CArrayPtr<CContactItem>* contacts = aDatabase.ImportContactsL(KVersitVCardUid, readStream, importSuccessful, options);
       
   512 	CleanupStack::PopAndDestroy(2); // readStream, readFile
       
   513 
       
   514 	// Check import results
       
   515 	TheTest(importSuccessful);
       
   516 	TheTest(contacts != NULL);
       
   517 	TheTest(contacts->Count() == 1);
       
   518 
       
   519 	// Delete container, but not the contact itself
       
   520 	CContactItem* item = contacts->At(0);
       
   521 	CleanupStack::PushL(item);
       
   522 	delete contacts;
       
   523 	return item;
       
   524 	}
       
   525 
       
   526 /**
       
   527  * Check the specified field set for the presence of a specific field which conforms
       
   528  * to the specified address type
       
   529  */
       
   530 static TBool LocateAddressFieldByType(CContactItemFieldSet& aFieldSet, TFieldType aFieldType, TUid aMapping, const TDesC& aExpectedValue, const TDesC& aExpectedPostFix)
       
   531 	{
       
   532 	TBool located = EFalse;
       
   533 
       
   534 	// Locate field
       
   535 	TInt pos = KErrNotFound;
       
   536 	if	(aFieldType != KNullUid) // KNullUid is for general address
       
   537 		pos = aFieldSet.Find(aFieldType, aMapping);
       
   538 	else
       
   539 		pos = aFieldSet.Find(aMapping);
       
   540 	//
       
   541 	if	(pos != KErrNotFound)
       
   542 		{
       
   543 		// Make real value
       
   544 		HBufC* value = ConstructAddressValueLC(aExpectedValue, aExpectedPostFix);
       
   545 
       
   546 		// Verify
       
   547 		CContactItemField& field = aFieldSet[pos];
       
   548 		CContactTextField* storage = field.TextStorage();
       
   549 		located = (storage->Text().CompareF(*value) == 0);
       
   550 		//
       
   551 		CleanupStack::PopAndDestroy(value);
       
   552 		}
       
   553 	//
       
   554 	return located;
       
   555 	}
       
   556 
       
   557 /**
       
   558  * Check the specified contact card contains an address corresponding to the specified type
       
   559  */
       
   560 static TBool ValidateContactForAddressTypeL(CContactItem& aContact, TFieldType aAddressType)
       
   561 	{
       
   562 	CContactItemFieldSet& fieldSet = aContact.CardFields();
       
   563 	const TPtrC postFix(PostFixForFieldType(aAddressType));
       
   564 	//
       
   565 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapPOSTOFFICE, KTestAddressPOSTOFFICE, postFix))
       
   566 		return EFalse;
       
   567 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapEXTENDEDADR, KTestAddressEXTENDEDADR, postFix))
       
   568 		return EFalse;
       
   569 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapADR, KTestAddressADR, postFix))
       
   570 		return EFalse;
       
   571 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapLOCALITY, KTestAddressLOCALITY, postFix))
       
   572 		return EFalse;
       
   573 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapREGION, KTestAddressREGION, postFix))
       
   574 		return EFalse;
       
   575 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapPOSTCODE, KTestAddressPOSTCODE, postFix))
       
   576 		return EFalse;
       
   577 	if	(!LocateAddressFieldByType(fieldSet, aAddressType, KUidContactFieldVCardMapCOUNTRY, KTestAddressCOUNTRY, postFix))
       
   578 		return EFalse;
       
   579 	//
       
   580 	return ETrue;
       
   581 	}
       
   582 
       
   583 
       
   584 // Tests
       
   585 
       
   586 static void Test1L(TBool& aPrintedTestTitle)
       
   587 	{
       
   588 	if	(!aPrintedTestTitle)
       
   589 		{
       
   590 		TheTest.Next(_L("EXPORT General address"));
       
   591 
       
   592 		aPrintedTestTitle = ETrue;
       
   593 		}
       
   594 	//
       
   595 	RFs& fsSession = TheTestHelper->Fs();
       
   596 	CContactDatabase& database = *TheTestHelper->Db();
       
   597 	//
       
   598 	const TContactItemId contactId = CreateContactL(database);
       
   599 	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
       
   600 	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
       
   601 	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
       
   602 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
       
   603 	CleanupStack::PopAndDestroy(parser);
       
   604 	}
       
   605 
       
   606 static void Test2L(TBool& aPrintedTestTitle)
       
   607 	{
       
   608 	if	(!aPrintedTestTitle)
       
   609 		{
       
   610 		TheTest.Next(_L("EXPORT General, Home address"));
       
   611 
       
   612 		aPrintedTestTitle = ETrue;
       
   613 		}
       
   614 	//
       
   615 	RFs& fsSession = TheTestHelper->Fs();
       
   616 	CContactDatabase& database = *TheTestHelper->Db();
       
   617 	//
       
   618 	const TContactItemId contactId = CreateContactL(database);
       
   619 	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
       
   620 	AddAddressL(database, contactId, KUidContactFieldVCardMapHOME);
       
   621 	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
       
   622 	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
       
   623 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
       
   624 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapHOME));
       
   625 	CleanupStack::PopAndDestroy(parser);
       
   626 	}
       
   627 
       
   628 static void Test3L(TBool& aPrintedTestTitle)
       
   629 	{
       
   630 	if	(!aPrintedTestTitle)
       
   631 		{
       
   632 		TheTest.Next(_L("EXPORT General, Work address"));
       
   633 
       
   634 		aPrintedTestTitle = ETrue;
       
   635 		}
       
   636 	//
       
   637 	RFs& fsSession = TheTestHelper->Fs();
       
   638 	CContactDatabase& database = *TheTestHelper->Db();
       
   639 	//
       
   640 	const TContactItemId contactId = CreateContactL(database);
       
   641 	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
       
   642 	AddAddressL(database, contactId, KUidContactFieldVCardMapWORK);
       
   643 	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
       
   644 	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
       
   645 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
       
   646 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapWORK));
       
   647 	CleanupStack::PopAndDestroy(parser);
       
   648 	}
       
   649 
       
   650 
       
   651 static void Test4L(TBool& aPrintedTestTitle)
       
   652 	{
       
   653 	if	(!aPrintedTestTitle)
       
   654 		{
       
   655 		TheTest.Next(_L("EXPORT General, Home, Work address"));
       
   656 
       
   657 		aPrintedTestTitle = ETrue;
       
   658 		}
       
   659 	//
       
   660 	RFs& fsSession = TheTestHelper->Fs();
       
   661 	CContactDatabase& database = *TheTestHelper->Db();
       
   662 	//
       
   663 	const TContactItemId contactId = CreateContactL(database);
       
   664 	AddAddressL(database, contactId, KUidContactFieldVCardMapGENERALADDRESS);
       
   665 	AddAddressL(database, contactId, KUidContactFieldVCardMapHOME);
       
   666 	AddAddressL(database, contactId, KUidContactFieldVCardMapWORK);
       
   667 	ExportContactAsVCardL(database, contactId, fsSession, KTestVCardExportFileName);
       
   668 	CParserVCard* parser = ParseVCardFileLC(fsSession, KTestVCardExportFileName);
       
   669 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapGENERALADDRESS));
       
   670 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapHOME));
       
   671 	TheTest(ValidateVCardForAddressL(*parser, KUidContactFieldVCardMapWORK));
       
   672 	CleanupStack::PopAndDestroy(parser);
       
   673 	}
       
   674 
       
   675 
       
   676 static void Test5L(TBool& aPrintedTestTitle)
       
   677 	{
       
   678 	if	(!aPrintedTestTitle)
       
   679 		{
       
   680 		TheTest.Next(_L("IMPORT General address"));
       
   681 
       
   682 		aPrintedTestTitle = ETrue;
       
   683 		}
       
   684 	//
       
   685 	RFs& fsSession = TheTestHelper->Fs();
       
   686 	CContactDatabase& database = *TheTestHelper->Db();
       
   687 	//
       
   688 	CParserVCard* vCard = CreateVCardLC();
       
   689 	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
       
   690 	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
       
   691 	CleanupStack::PopAndDestroy(vCard);
       
   692 	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
       
   693 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
       
   694 	CleanupStack::PopAndDestroy(item);
       
   695 	}
       
   696 
       
   697 static void Test6L(TBool& aPrintedTestTitle)
       
   698 	{
       
   699 	if	(!aPrintedTestTitle)
       
   700 		{
       
   701 		TheTest.Next(_L("IMPORT General, Home address"));
       
   702 
       
   703 		aPrintedTestTitle = ETrue;
       
   704 		}
       
   705 	//
       
   706 	RFs& fsSession = TheTestHelper->Fs();
       
   707 	CContactDatabase& database = *TheTestHelper->Db();
       
   708 	//
       
   709 	CParserVCard* vCard = CreateVCardLC();
       
   710 	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
       
   711 	AddAddressToVCardL(*vCard, KVersitParam8Home);
       
   712 	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
       
   713 	CleanupStack::PopAndDestroy(vCard);
       
   714 	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
       
   715 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
       
   716 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapHOME));
       
   717 	CleanupStack::PopAndDestroy(item);
       
   718 	}
       
   719 
       
   720 
       
   721 static void Test7L(TBool& aPrintedTestTitle)
       
   722 	{
       
   723 	if	(!aPrintedTestTitle)
       
   724 		{
       
   725 		TheTest.Next(_L("IMPORT General, Work address"));
       
   726 
       
   727 		aPrintedTestTitle = ETrue;
       
   728 		}
       
   729 	//
       
   730 	RFs& fsSession = TheTestHelper->Fs();
       
   731 	CContactDatabase& database = *TheTestHelper->Db();
       
   732 	//
       
   733 	CParserVCard* vCard = CreateVCardLC();
       
   734 	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
       
   735 	AddAddressToVCardL(*vCard, KVersitParam8Work);
       
   736 	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
       
   737 	CleanupStack::PopAndDestroy(vCard);
       
   738 	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
       
   739 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
       
   740 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapWORK));
       
   741 	CleanupStack::PopAndDestroy(item);
       
   742 	}
       
   743 
       
   744 
       
   745 static void Test8L(TBool& aPrintedTestTitle)
       
   746 	{
       
   747 	if	(!aPrintedTestTitle)
       
   748 		{
       
   749 		TheTest.Next(_L("IMPORT General, Home, Work address"));
       
   750 
       
   751 		aPrintedTestTitle = ETrue;
       
   752 		}
       
   753 	RFs& fsSession = TheTestHelper->Fs();
       
   754 	CContactDatabase& database = *TheTestHelper->Db();
       
   755 	//
       
   756 	CParserVCard* vCard = CreateVCardLC();
       
   757 	AddAddressToVCardL(*vCard, KVersitParam8GeneralAddress);
       
   758 	AddAddressToVCardL(*vCard, KVersitParam8Home);
       
   759 	AddAddressToVCardL(*vCard, KVersitParam8Work);
       
   760 	CreateVCardFileFromVCardObjectL(*vCard, fsSession, KTestVCardImportFileName);
       
   761 	CleanupStack::PopAndDestroy(vCard);
       
   762 	CContactItem* item = ImportVCardLC(database, fsSession, KTestVCardImportFileName);
       
   763 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapGENERALADDRESS));
       
   764 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapHOME));
       
   765 	TheTest(ValidateContactForAddressTypeL(*item, KUidContactFieldVCardMapWORK));
       
   766 	CleanupStack::PopAndDestroy(item);
       
   767 	}
       
   768 
       
   769 static void RunListOfTestsL(const RArray<TGAFunction>& aTests)
       
   770 	{
       
   771 	TBool printedTestTitle = EFalse;
       
   772 	const TInt count = aTests.Count();
       
   773 	for(TInt i=0; i<count; i++)
       
   774 		{
       
   775 		TGAFunction test = aTests[i];
       
   776 		TheTestHelper->CreateDatabaseL();
       
   777 		TRAPD(err, (*test)(printedTestTitle));
       
   778 
       
   779 		// Ensure that we close the database if a leave occurs or
       
   780 		// else the OOM test code thinks we've leaked it
       
   781 		TheTestHelper->CloseDatabase();
       
   782 
       
   783 		// Cascade error
       
   784 		User::LeaveIfError(err);
       
   785 
       
   786 		printedTestTitle = EFalse;
       
   787 		}
       
   788 	}
       
   789 
       
   790 static void TestExportL()
       
   791 	{
       
   792 	RArray<TGAFunction> array;
       
   793 	CleanupClosePushL(array);
       
   794 	//
       
   795 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test1L)));
       
   796 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test2L)));
       
   797 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test3L)));
       
   798 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test4L)));
       
   799 	//
       
   800 	RunListOfTestsL(array);
       
   801 	//
       
   802 	CleanupStack::PopAndDestroy(&array);
       
   803 	}
       
   804 
       
   805 static void TestImportL()
       
   806 	{
       
   807 	RArray<TGAFunction> array;
       
   808 	CleanupClosePushL(array);
       
   809 	//
       
   810 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test5L)));
       
   811 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test6L)));
       
   812 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test7L)));
       
   813 	User::LeaveIfError(array.Append(static_cast<TGAFunction>(Test8L)));
       
   814 	//
       
   815 	RunListOfTestsL(array);
       
   816 	//
       
   817 	CleanupStack::PopAndDestroy(&array);
       
   818 	}
       
   819 
       
   820 
       
   821 static void RunTestsL()
       
   822 	{
       
   823 	TRAPD(errExport, TestExportL());
       
   824 	TheTest(errExport == KErrNone || errExport == KErrNoMemory);
       
   825 	//
       
   826 	TRAPD(errImport, TestImportL());
       
   827 	TheTest(errImport == KErrNone || errImport == KErrNoMemory);
       
   828 	}
       
   829 
       
   830 #ifdef OOM_TESTS
       
   831 
       
   832 static void ExpandCleanupStackL()
       
   833 	{
       
   834 	// Reserve some space on the cleanup stack:
       
   835 		{
       
   836 		for (TInt ii=0;ii<1000;++ii)
       
   837 			CleanupStack::PushL(&ii);
       
   838 		}
       
   839 	CleanupStack::Pop(1000);
       
   840 	}
       
   841 
       
   842 static void PrepareTestSkipsL(RArray<TInt>& aSkipArray, TInt aCount, ...)
       
   843 	{
       
   844 	aSkipArray.Reset();
       
   845 	//
       
   846     VA_LIST list;
       
   847     VA_START(list, aCount);
       
   848 	//
       
   849 	TInt* startPtr = reinterpret_cast<TInt*>(&list); // Same as list[0]
       
   850 	for(TInt i=0; i<aCount; i++)
       
   851 		{
       
   852 		const TInt cycle = startPtr[i];
       
   853 		aSkipArray.AppendL(cycle);
       
   854 		}
       
   855 	}
       
   856 
       
   857 
       
   858 static TInt RunOOMTestL(TGAFunction aFunction, const RArray<TInt>& aSkipArray)
       
   859 	{
       
   860 	//
       
   861 	TBool printedTestTitle = EFalse;
       
   862 	TInt ret = KErrNoMemory;
       
   863 	TInt failAt = 0;
       
   864 	while(ret != KErrNone)
       
   865 		{
       
   866 		failAt += failAt/50 + 1;
       
   867 		TheTest.Printf(_L("OOM step: %d\n"), failAt);
       
   868 		if (aSkipArray.Find(failAt) != KErrNotFound)
       
   869 			continue;
       
   870 		//
       
   871 		__UHEAP_MARK;
       
   872 		TheTestHelper->CreateDatabaseL();
       
   873 
       
   874 		__UHEAP_SETFAIL(RHeap::EDeterministic, failAt);
       
   875 		TRAP(ret, aFunction(printedTestTitle));
       
   876 		__UHEAP_RESET;
       
   877 
       
   878 		// Ensure that we close the database
       
   879 		TheTestHelper->CloseDatabase();
       
   880 
       
   881 
       
   882 		__UHEAP_MARKEND;
       
   883 		//
       
   884 		if	(ret != KErrNoMemory && ret != KErrNone)
       
   885 			{
       
   886 			TheTest.Printf(_L("Non standard error: %d\n"),ret);
       
   887 			TheTest.Getch();
       
   888 			}
       
   889 		TheTest(ret == KErrNoMemory || ret == KErrNone);
       
   890 		}
       
   891 	//
       
   892 	return KErrNone;
       
   893 	}
       
   894 
       
   895 static void RunOOMTestsL()
       
   896 	{
       
   897 	ExpandCleanupStackL();
       
   898 	//
       
   899 	RArray<TInt> knownFailures;
       
   900 	CleanupClosePushL(knownFailures);
       
   901 
       
   902 	// EXPORT
       
   903 	PrepareTestSkipsL(knownFailures, 0);
       
   904 	RunOOMTestL(Test1L, knownFailures);
       
   905 	//
       
   906 	// (Skip OOM on Test2L, Test3L and Test4L as they execute the same code as Test1L)
       
   907 
       
   908 	// IMPORT
       
   909 	PrepareTestSkipsL(knownFailures, 0);
       
   910 	RunOOMTestL(Test5L, knownFailures);
       
   911 	//
       
   912 	// (Skip OOM on Test6L, Test7L and Test8L as they execute the same code as Test5L)
       
   913 
       
   914 	CleanupStack::PopAndDestroy(&knownFailures);
       
   915 	}
       
   916 #endif
       
   917 
       
   918 static void DoMainL()
       
   919 	{
       
   920 	CTestRegister* TempFiles = CTestRegister::NewLC();
       
   921 	TempFiles->RegisterL(KTestDatabaseFile, EFileTypeCnt);
       
   922 	TempFiles->RegisterL(KTestVCardExportFileName);
       
   923 	TempFiles->RegisterL(KTestVCardImportFileName);
       
   924 
       
   925 	// Run normal testing
       
   926 	TRAPD(testRet, RunTestsL());
       
   927 	TheTest(testRet == KErrNone);
       
   928 
       
   929 	// Run OOM testing
       
   930 #ifdef OOM_TESTS
       
   931 	TRAPD(oomRet, RunOOMTestsL());
       
   932 	TheTest(oomRet == KErrNone);
       
   933 #endif
       
   934 
       
   935 	CleanupStack::PopAndDestroy(TempFiles);
       
   936 	}
       
   937 
       
   938 /**
       
   939 
       
   940 @SYMTestCaseID     PIM-T-GENERALADDRESS-0001
       
   941 
       
   942 */
       
   943 
       
   944 GLDEF_C TInt E32Main()
       
   945 	{
       
   946 	__UHEAP_MARK;
       
   947 	TheTest.Start(_L("@SYMTESTCaseID:PIM-T-GENERALADDRESS-0001 T_GENERALADDRESS - Test General Address Export and Import"));
       
   948 
       
   949 
       
   950 	// Stupid test library alert...
       
   951 	TheTestHelper = new(ELeave) CCntTest();
       
   952 	TheTestHelper->ConstructL(TheTest, KTestDatabaseFile);
       
   953 
       
   954 	TRAP_IGNORE(DoMainL());
       
   955 	//
       
   956 	TheTestHelper->EndTestLib(KErrNone);
       
   957 	//
       
   958 	__UHEAP_MARKEND;
       
   959 	return(KErrNone);
       
   960     }