persistentstorage/centralrepository/test/T_CenRepTrans.cpp
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2005-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 #include "t_cenrep_helper.h"
       
    17 #include <e32test.h>
       
    18 #include <f32file.h>
       
    19 #include "srvrepos_noc.h"
       
    20 #include "srvres.h"
       
    21 #include "cachemgr.h"
       
    22 #include <bautils.h>
       
    23 #include "setting.h"
       
    24 
       
    25 //Forward declarations
       
    26 class CTestObserver;
       
    27 
       
    28 ///////////////////////////////////////////////////////////////////////////////////////
       
    29 // Globals
       
    30 
       
    31 static RTest TheTest(_L("T_CenRepTrans"));
       
    32 const TUid KTestRepositoryId = {0x00000010};
       
    33 //CentralRepository server UID
       
    34 static const TUid KCenRepServerUID = {0x10202BE9};
       
    35 
       
    36 static CTestObserver* TheObserver = NULL;
       
    37 static CServerRepository* TheServerRepository = NULL;
       
    38 
       
    39 static const TUint32 KIntSettingID = 843;
       
    40 static const TInt KIntSettingVal = 25;
       
    41 
       
    42 static const TUint32 KRealSettingID = 844;
       
    43 static const TReal KRealSettingVal = 8.76;
       
    44 static const TReal KRealSettingVal2 = 19.234;
       
    45 
       
    46 static const TUint32 KStringSettingID = 845;
       
    47 _LIT8(KStringSettingVal, "a test string");
       
    48 _LIT8(KStringSettingVal2, "another string");
       
    49 _LIT8(KEmptyString, "");
       
    50 
       
    51 _LIT(KTestFile1,	"C:\\PRIVATE\\10202BE9\\PERSISTS\\00000010.TXT");
       
    52 _LIT(KCreTestFile1,	"C:\\PRIVATE\\10202BE9\\PERSISTS\\00000010.CRE");
       
    53 _LIT(KTmpTestFile1,	"C:\\PRIVATE\\10202BE9\\PERSISTS\\00000010.TMP");
       
    54 
       
    55 
       
    56 ///////////////////////////////////////////////////////////////////////////////////////
       
    57 //
       
    58 
       
    59 //Delete file function.
       
    60 //Used by the test application to cleanup the C drive at the end of the test.
       
    61 static void DeleteFile(const TDesC& aFullName)
       
    62 	{
       
    63 	RFs fsSession;
       
    64 	TInt err = fsSession.Connect();
       
    65 	if(err == KErrNone)
       
    66 		{
       
    67 		TEntry entry;
       
    68 		if(fsSession.Entry(aFullName, entry) == KErrNone)
       
    69 			{
       
    70 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
       
    71 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
       
    72 			if(err != KErrNone)
       
    73 				{
       
    74 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
       
    75 				}
       
    76 			err = fsSession.Delete(aFullName);
       
    77 			if(err != KErrNone)
       
    78 				{
       
    79 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
       
    80 				}
       
    81 			}
       
    82 		fsSession.Close();
       
    83 		}
       
    84 	else
       
    85 		{
       
    86 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
       
    87 		}
       
    88 	}
       
    89 
       
    90 static void DeleteFiles()
       
    91 	{
       
    92 	::DeleteFile(KTestFile1);
       
    93 	::DeleteFile(KCreTestFile1);
       
    94 	::DeleteFile(KTmpTestFile1);
       
    95 	}
       
    96 
       
    97 static TInt GetFileTimeStamp(const TDesC& aFullName, TTime& aTime)
       
    98 	{
       
    99 	RFs fsSession;
       
   100 	TInt err = fsSession.Connect();
       
   101 	if(err == KErrNone)
       
   102 		{
       
   103 		TEntry entry;
       
   104 		if(fsSession.Entry(aFullName, entry) == KErrNone)
       
   105 			{
       
   106 			aTime=entry.iModified;
       
   107 			}
       
   108 		fsSession.Close();
       
   109 		}
       
   110 	else
       
   111 		{
       
   112 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
       
   113 		}
       
   114 	return err;
       
   115 	}
       
   116 
       
   117 
       
   118 ///////////////////////////////////////////////////////////////////////////////////////
       
   119 // Test macros and functions.
       
   120 
       
   121 static void Check(TInt aValue, TInt aLine)
       
   122 	{
       
   123 	if(!aValue)
       
   124 		{
       
   125 		::DeleteFiles();
       
   126 		TheTest(EFalse, aLine);
       
   127 		}
       
   128 	}
       
   129 static  void Check(TInt aValue, TInt aExpected, TInt aLine)
       
   130 	{
       
   131 	if(aValue != aExpected)
       
   132 		{
       
   133 		::DeleteFiles();
       
   134 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
   135 		TheTest(EFalse, aLine);
       
   136 		}
       
   137 	}
       
   138 #define TEST(arg) ::Check((arg), __LINE__)
       
   139 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
   140 
       
   141 ///////////////////////////////////////////////////////////////////////////////////////
       
   142 
       
   143 static void CheckTmpFileDeleted()
       
   144 	{
       
   145 	RFs fsSession;
       
   146 	TInt err = fsSession.Connect();
       
   147 	if(err == KErrNone)
       
   148 		{
       
   149 		// Allow time for file to be deleted
       
   150 		User::After(500*1000);
       
   151 		TEST2 (BaflUtils::FileExists (fsSession, KTmpTestFile1), EFalse);
       
   152 		fsSession.Close();
       
   153 		}
       
   154 	else
       
   155 		{
       
   156 		RDebug::Print(_L("Error %d connecting file session.\n"), err);
       
   157 		}
       
   158 	}
       
   159 
       
   160 
       
   161 ///////////////////////////////////////////////////////////////////////////////////////
       
   162 // CTestObserver class
       
   163 
       
   164 //It is needed for the creation of CServerRepository object.
       
   165 //Used also to track Get/Set/Create/Delete setting notifications, received
       
   166 //from CServerRepository object.
       
   167 class CTestObserver : public CBase, public MObserver
       
   168 	{
       
   169 public:
       
   170 	CTestObserver();
       
   171 	void Notify(TUint32 aId);
       
   172 
       
   173 public:
       
   174 	TBool iAssertNotification;
       
   175 
       
   176 	};
       
   177 
       
   178 CTestObserver::CTestObserver() :
       
   179 	iAssertNotification(EFalse)
       
   180 	{
       
   181 	}
       
   182 
       
   183 void CTestObserver::Notify(TUint32 aId)
       
   184 	{
       
   185 	RDebug::Print(_L("Notification! Id=%d.\n"), aId);
       
   186 	if(iAssertNotification)
       
   187 		{
       
   188 		TEST(0);
       
   189 		}
       
   190 	}
       
   191 
       
   192 ///////////////////////////////////////////////////////////////////////////////////////
       
   193 //
       
   194 
       
   195 //Deletes the global TheObserver object. Sets it to NULL.
       
   196 static void ReleaseObserver(TAny*)
       
   197 	{
       
   198 	delete TheObserver;
       
   199 	TheObserver = NULL;
       
   200 	}
       
   201 
       
   202 //Deletes the global TheServerRepository object. Sets it to NULL.
       
   203 static void ReleaseRepository(TAny*)
       
   204 	{
       
   205 	TheServerRepository->Close();
       
   206 	delete TheServerRepository;
       
   207 	TheServerRepository = NULL;
       
   208 	TServerResources::iCacheManager->DisableCache(ETrue);
       
   209 	TServerResources::iObserver->CloseiOpenRepositories();
       
   210 	TServerResources::iCacheManager->EnableCache();
       
   211 	}
       
   212 
       
   213 //This function is called from CreateSetting_OOMtestL().
       
   214 //It creates an integer, real or string setting in the repository
       
   215 //with ID=KTestRepositoryId. All this is done in an OOM loop.
       
   216 //The output from this test is: the repository file with ID = KTestRepositoryId
       
   217 //will be copied from Z to C drive;
       
   218 // An integer, real or string setting will be created in that repository.
       
   219 //Changes in the repository will be stored on C drive (in the related repository file)
       
   220 static void DoCreateSettingL(TBool aTrapping,TServerSetting::TType aSettingType)
       
   221 	{
       
   222 	TheObserver = new (ELeave) CTestObserver;
       
   223 	TCleanupItem clnItem1(&ReleaseObserver, NULL);
       
   224 	CleanupStack::PushL(clnItem1);
       
   225 
       
   226 	TheServerRepository = new (ELeave) CServerRepository;
       
   227 	TCleanupItem clnItem2(&ReleaseRepository, NULL);
       
   228 	CleanupStack::PushL(clnItem2);
       
   229 
       
   230 	// Turn OOM trapping on Repository Open on/off for testing purposes.
       
   231 	TServerResources::iObserver->iTrapOOMOnOpen=aTrapping;
       
   232 	// Open the repository
       
   233 	TheServerRepository->OpenL(KTestRepositoryId, *TheObserver);
       
   234 
       
   235 	// All write operations, including CreateL must be done in a transaction
       
   236 	TheServerRepository->StartTransaction(CRepository::EConcurrentReadWriteTransaction);
       
   237 	TheServerRepository->CleanupCancelTransactionPushL();
       
   238 
       
   239 	//Create the appropriate setting based on aValueType
       
   240 	switch(aSettingType)
       
   241 		{
       
   242 		case TServerSetting::EInt:
       
   243 			{
       
   244 			// Create setting - fails if value already there (it must not be)
       
   245 			User::LeaveIfError(TheServerRepository->TransactionCreateL(KIntSettingID, KIntSettingVal, NULL));
       
   246 
       
   247 			// Try to get the value from the transaction cache
       
   248 			TInt val = 0;
       
   249 			User::LeaveIfError(TheServerRepository->Get(KIntSettingID, val));
       
   250 			TEST2(val,KIntSettingVal);
       
   251 			break;
       
   252 			}
       
   253 
       
   254 		case TServerSetting::EReal:
       
   255 			{
       
   256 			// Create setting - fails if value already there (it must not be)
       
   257 			User::LeaveIfError(TheServerRepository->TransactionCreateL(KRealSettingID, KRealSettingVal, NULL));
       
   258 
       
   259 			// Try to get the value from the transaction cache
       
   260 			TReal val = 0;
       
   261 			User::LeaveIfError(TheServerRepository->Get(KRealSettingID, val));
       
   262 			TEST(val == KRealSettingVal);
       
   263 			break;
       
   264 			}
       
   265 
       
   266 		case TServerSetting::EString:
       
   267 			{
       
   268 			// Create setting - fails if value already there (it must not be)
       
   269 			User::LeaveIfError(TheServerRepository->TransactionCreateL(KStringSettingID, KStringSettingVal, NULL));
       
   270 
       
   271 			// Try to get the value from the transaction cache
       
   272 			TBuf8<16> bufVal(KEmptyString);
       
   273 			User::LeaveIfError(TheServerRepository->Get(KStringSettingID, bufVal));
       
   274 			TEST(bufVal == KStringSettingVal);
       
   275 			break;
       
   276 			}
       
   277 		default:
       
   278 			break;
       
   279 		}
       
   280 
       
   281 	// Commit the changes
       
   282 	CleanupStack::Pop();
       
   283 	TUint32 keyInfo;
       
   284 	User::LeaveIfError(TheServerRepository->CommitTransaction(keyInfo));
       
   285 
       
   286 	TServerResources::iObserver->iTrapOOMOnOpen=EFalse;
       
   287 	// Close the repository
       
   288 	TheServerRepository->Close();
       
   289 
       
   290 	CleanupStack::PopAndDestroy(2);//TheObserver & TheServerRepository
       
   291 	}
       
   292 
       
   293 //This function is called from SetSetting_OOMtest().
       
   294 //It expects that the previous test (CreateSetting_OOMtestL()) had completed successfully
       
   295 //and there is a repository file (ID=0x10) on drive C and there is an integer setting
       
   296 //in that repository (ID=KIntSettingID, Value=KIntSettingVal).
       
   297 //The test will try to change the setting value in a transaction. Because the test is
       
   298 //executed in an OOM loop, CommitChangesL() - will fail when called by SetL, leaving the
       
   299 //repository content inconsistent - the in-memory repository content will be deleted
       
   300 //(no settings), but in  the file the setting will exist and its value will still be KIntSettingVal.
       
   301 static void DoSetIntSettingL()
       
   302 	{
       
   303 	TEST(TheObserver != NULL);
       
   304 	TEST(TheServerRepository != NULL);
       
   305 	// Check if the setting is there - and has (or is restored to) the original value
       
   306 	TInt val = 0;
       
   307 	User::LeaveIfError(TheServerRepository->Get(KIntSettingID, val));
       
   308 	TEST2(val,KIntSettingVal);
       
   309 
       
   310 	// Change the setting value
       
   311 	// All write operations, including CreateL must be done in a transaction
       
   312 	TheServerRepository->StartTransaction(CRepository::EConcurrentReadWriteTransaction);
       
   313 	TheServerRepository->CleanupCancelTransactionPushL();
       
   314 	// Change the setting value
       
   315 	User::LeaveIfError(TheServerRepository->TransactionSetL(KIntSettingID, KIntSettingVal + 1));
       
   316 
       
   317 	// Check if the setting is there - it should be in transaction cache now
       
   318 	User::LeaveIfError(TheServerRepository->Get(KIntSettingID, val));
       
   319 	TEST2(val,(KIntSettingVal + 1));
       
   320 
       
   321 	// Commit the changes
       
   322 	CleanupStack::Pop();
       
   323 	TUint32 keyInfo;
       
   324 	User::LeaveIfError(TheServerRepository->CommitTransaction(keyInfo));
       
   325 
       
   326 	// Check if the setting is there. The transaction was successful so the new value
       
   327 	// should be returned.
       
   328 	val = 0;
       
   329 	User::LeaveIfError(TheServerRepository->Get(KIntSettingID, val));
       
   330 	TEST2(val,(KIntSettingVal + 1));
       
   331 	}
       
   332 
       
   333 //This function is called from SetSetting_OOMtest().
       
   334 //It expects that the previous test (CreateSetting_OOMtestL()) had completed successfully
       
   335 //and there is a repository file (ID=0x10) on drive C and there is an rea; setting
       
   336 //in that repository (ID=KRealSettingID, Value=KRealSettingVal).
       
   337 //The test will try to change the setting value in a transaction. Because the test is
       
   338 //executed in an OOM loop, CommitChangesL() - will fail when called by SetL, leaving the
       
   339 //repository content inconsistent - the in-memory repository content will be deleted
       
   340 //(no settings), but in  the file the setting will exist and its value will still be KRealSettingVal.
       
   341 static void DoSetRealSettingL()
       
   342 	{
       
   343 	TEST(TheObserver != NULL);
       
   344 	TEST(TheServerRepository != NULL);
       
   345 	// Check if the setting is there - and has (or is restored to) the original value
       
   346 	TReal val = 0;
       
   347 	User::LeaveIfError(TheServerRepository->Get(KRealSettingID, val));
       
   348 	TEST(val == KRealSettingVal);
       
   349 
       
   350 	// Change the setting value
       
   351 	// All write operations, including CreateL must be done in a transaction
       
   352 	TheServerRepository->StartTransaction(CRepository::EConcurrentReadWriteTransaction);
       
   353 	TheServerRepository->CleanupCancelTransactionPushL();
       
   354 	// Change the setting value
       
   355 	User::LeaveIfError(TheServerRepository->TransactionSetL(KRealSettingID, KRealSettingVal2));
       
   356 
       
   357 	// Check if the setting is there - it should be in transaction cache now
       
   358 	User::LeaveIfError(TheServerRepository->Get(KRealSettingID, val));
       
   359 	TEST(val == KRealSettingVal2);
       
   360 
       
   361 	// Commit the changes
       
   362 	CleanupStack::Pop();
       
   363 	TUint32 keyInfo;
       
   364 	User::LeaveIfError(TheServerRepository->CommitTransaction(keyInfo));
       
   365 
       
   366 	// Check if the setting is there. The transaction was successful so the new value
       
   367 	// should be returned.
       
   368 	val = 0;
       
   369 	User::LeaveIfError(TheServerRepository->Get(KRealSettingID, val));
       
   370 	TEST(val == KRealSettingVal2);
       
   371 	}
       
   372 
       
   373 //This function is called from SetSetting_OOMtest().
       
   374 //It expects that the previous test (CreateSetting_OOMtestL()) had completed successfully
       
   375 //and there is a repository file (ID=0x10) on drive C and there is an string setting
       
   376 //in that repository (ID=KStringSettingID, Value=KStringSettingVal).
       
   377 //The test will try to change the setting value in a transaction. Because the test is
       
   378 //executed in an OOM loop, CommitChangesL() - will fail when called by SetL, leaving the
       
   379 //repository content inconsistent - the in-memory repository content will be deleted
       
   380 //(no settings), but in  the file the setting will exist and its value will still
       
   381 //be KStringSettingVal.
       
   382 static void DoSetStringSettingL()
       
   383 	{
       
   384 	TEST(TheObserver != NULL);
       
   385 	TEST(TheServerRepository != NULL);
       
   386 
       
   387 	// Check if the setting is there - and has (or is restored to) the original value
       
   388 	TBuf8<16> bufVal(KEmptyString);
       
   389 	User::LeaveIfError(TheServerRepository->Get(KStringSettingID, bufVal));
       
   390 	TEST(bufVal == KStringSettingVal);
       
   391 
       
   392 	// Change the setting value
       
   393 	// All write operations, including CreateL must be done in a transaction
       
   394 	TheServerRepository->StartTransaction(CRepository::EConcurrentReadWriteTransaction);
       
   395 	TheServerRepository->CleanupCancelTransactionPushL();
       
   396 
       
   397 	// Change the setting value
       
   398 	User::LeaveIfError(TheServerRepository->TransactionSetL(KStringSettingID, KStringSettingVal2));
       
   399 
       
   400 	// Check if the setting is there - it should be in transaction cache now
       
   401 	User::LeaveIfError(TheServerRepository->Get(KStringSettingID, bufVal));
       
   402 	TEST(bufVal == KStringSettingVal2);
       
   403 	// Commit the changes
       
   404 	CleanupStack::Pop();
       
   405 	TUint32 keyInfo;
       
   406 	User::LeaveIfError(TheServerRepository->CommitTransaction(keyInfo));
       
   407 
       
   408 	// Check if the setting is there. The transaction was successful so the new value
       
   409 	// should be returned.
       
   410 	bufVal = KEmptyString;
       
   411 	User::LeaveIfError(TheServerRepository->Get(KStringSettingID, bufVal));
       
   412 	TEST(bufVal == KStringSettingVal2);
       
   413 	}
       
   414 
       
   415 //This function is called from SetSetting_OOMtest()in the case where previous
       
   416 //DoSetSettingL() call failed with KErrNoMemory, leaving the repository object
       
   417 //in inconsisten state - the in-memory presentation of the repository differs from
       
   418 //the repository file content. The function will try to repair the repository,
       
   419 //as it would have to happen in a real situation. Then it will check that
       
   420 //the repository content is consistent, which means the tested setting value should
       
   421 //be the same as it was before DoSetSettingL() call.
       
   422 static void DoRecoverRepositoryL(TServerSetting::TType aSettingType)
       
   423 	{
       
   424 	//Repair the repository as it happens in a real situation
       
   425 	//AccessL calls RestoreConsistencyL() indirectly
       
   426 	//RestoreConsistencyL() is called in the production code from the session object,
       
   427 	//ServiceL() implementation. So, it will be called before any other repository call
       
   428 	//and it should restore the repository content - it should repair the repository
       
   429 	//consitency.
       
   430 	TServerResources::iObserver->AccessL(KTestRepositoryId);
       
   431 	//Check if the setting is there - the old, pre-transactional value should be
       
   432 	//in-memory now.
       
   433 	switch(aSettingType)
       
   434 		{
       
   435 		case TServerSetting::EInt:
       
   436 			{
       
   437 			TInt val = 0;
       
   438 			User::LeaveIfError(TheServerRepository->Get(KIntSettingID, val));
       
   439 			TEST2(val,KIntSettingVal);
       
   440 			break;
       
   441 			}
       
   442 
       
   443 		case TServerSetting::EReal:
       
   444 			{
       
   445 			TReal val = 0;
       
   446 			User::LeaveIfError(TheServerRepository->Get(KRealSettingID, val));
       
   447 			TEST(val == KRealSettingVal);
       
   448 			break;
       
   449 			}
       
   450 
       
   451 		case TServerSetting::EString:
       
   452 			{
       
   453 			TBuf8<16> bufVal(KEmptyString);
       
   454 			User::LeaveIfError(TheServerRepository->Get(KStringSettingID, bufVal));
       
   455 			TEST(bufVal == KStringSettingVal);
       
   456 			break;
       
   457 			}
       
   458 		default:
       
   459 			break;
       
   460 		}
       
   461 	}
       
   462 
       
   463 //Inits TServerResources object.
       
   464 //It should be called once, before the creation of CServerRepository object.
       
   465 static void InitEnvL()
       
   466 	{
       
   467 	TServerResources::InitialiseL();
       
   468 
       
   469 	delete TServerResources::iDataDirectory; TServerResources::iDataDirectory = NULL;
       
   470 	delete TServerResources::iRomDirectory; TServerResources::iRomDirectory = NULL;
       
   471 	delete TServerResources::iInstallDirectory; TServerResources::iInstallDirectory = NULL;
       
   472 
       
   473 	TServerResources::iDataDirectory = HBufC::NewL(KMaxFileName);
       
   474 	TServerResources::iRomDirectory = HBufC::NewL(KMaxFileName);
       
   475 	TServerResources::iInstallDirectory = HBufC::NewL(KMaxFileName);
       
   476 
       
   477 	TBuf<32> uidName;
       
   478 	uidName.Format(_L("%08X"), KCenRepServerUID.iUid);
       
   479 
       
   480 	TPtr ptr1(TServerResources::iDataDirectory->Des());
       
   481 	ptr1.Append(_L("C:\\PRIVATE\\"));
       
   482 	ptr1.Append(uidName);
       
   483 	ptr1.Append(_L("\\PERSISTS\\"));
       
   484 
       
   485 	TPtr ptr2(TServerResources::iRomDirectory->Des());
       
   486 	ptr2.Append(_L("Z:\\PRIVATE\\"));
       
   487 	ptr2.Append(uidName);
       
   488 	ptr2.Append(_L("\\"));
       
   489 
       
   490 	TPtr ptr3(TServerResources::iInstallDirectory->Des());
       
   491 	ptr3.Append(_L("C:\\PRIVATE\\"));
       
   492 	ptr3.Append(uidName);
       
   493 	ptr3.Append(_L("\\"));
       
   494 	}
       
   495 
       
   496 //Destroys TServerResources object.
       
   497 //It should be called after the CServerRepository object was destroyed.
       
   498 static void ReleaseEnv()
       
   499 	{
       
   500 	TServerResources::Close();
       
   501 	}
       
   502 
       
   503 //Creates global TheServerRepository and TheObserver objects
       
   504 //It is used in SetSetting_OOMtest()
       
   505 static void InitEnv2L()
       
   506 	{
       
   507 	TheObserver = new CTestObserver;
       
   508 	TEST(TheObserver != NULL);
       
   509 
       
   510 	TheServerRepository = new CServerRepository;
       
   511 	TEST(TheServerRepository != NULL);
       
   512 
       
   513 	TheServerRepository->OpenL(KTestRepositoryId, *TheObserver);
       
   514 	}
       
   515 
       
   516 //Destroys global TheServerRepository and TheObserver objects
       
   517 //It is used in SetSetting_OOMtest()
       
   518 static void ReleaseEnv2()
       
   519 	{
       
   520 	::ReleaseRepository(NULL);
       
   521 	::ReleaseObserver(NULL);
       
   522 	}
       
   523 
       
   524 //Central repository test: it creates a setting in OOM conditions.
       
   525 static void CreateSetting_OOMtestL(TBool aTrapping,TServerSetting::TType aSettingType)
       
   526 	{
       
   527 	TInt err;
       
   528 	TRAP(err, ::InitEnvL());
       
   529 	TEST2(err, KErrNone);
       
   530 	for(TInt count=1;;++count)
       
   531 		{
       
   532 		CleanupCDriveL();
       
   533 		__UHEAP_FAILNEXT(count);
       
   534 		__UHEAP_MARK;
       
   535 
       
   536 		TRAP(err, ::DoCreateSettingL(aTrapping,aSettingType));
       
   537 
       
   538 		TServerResources::iOwnerIdLookUpTable.Reset();
       
   539 		TServerResources::iObserver->Reset();
       
   540 
       
   541 		__UHEAP_MARKEND;
       
   542 
       
   543 		if(err == KErrNone)
       
   544 			{
       
   545 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
       
   546 			break;
       
   547 			}
       
   548 		else if(err != KErrNoMemory)
       
   549 			{
       
   550 			TEST2(err, KErrNone);
       
   551 			}
       
   552 		}
       
   553 
       
   554 	::ReleaseEnv();
       
   555 	__UHEAP_RESET;
       
   556 	}
       
   557 
       
   558 //Central repository test: it sets new setting value in OOM conditions.
       
   559 //Then ComitChangesL() is called to store the new setting's value in the repository
       
   560 //file. Because of the simulated OOM conditions ComitChangesL() can fail, leaving the
       
   561 //repository in inconsistent state.
       
   562 //DoRecoverRepositoryL() is called to repair the repository and restore the consistency.
       
   563 static void SetSetting_OOMtest(TServerSetting::TType aSettingType)
       
   564 	{
       
   565 	TTime before;
       
   566 	TTime after;
       
   567 	// Check that cre file exists and get modification time
       
   568 	TEST2 (GetFileTimeStamp(KCreTestFile1, before), KErrNone);
       
   569 	after=before;
       
   570 
       
   571 	TInt err;
       
   572 	TRAP(err, ::InitEnvL());
       
   573 	TEST2(err, KErrNone);
       
   574 	TRAP(err, ::InitEnv2L());
       
   575 	TEST2(err, KErrNone);	
       
   576 	for(TInt count=1;;++count)
       
   577 		{
       
   578 		__UHEAP_FAILNEXT(count);
       
   579 		__UHEAP_MARK;
       
   580 
       
   581 	switch(aSettingType)
       
   582 		{
       
   583 		case TServerSetting::EInt:
       
   584 			{
       
   585 			TRAP(err, ::DoSetIntSettingL());
       
   586 			break;
       
   587 			}
       
   588 		case TServerSetting::EReal:
       
   589 			{
       
   590 			TRAP(err, ::DoSetRealSettingL());
       
   591 			break;
       
   592 			}
       
   593 		case TServerSetting::EString:
       
   594 			{
       
   595 			TRAP(err, ::DoSetStringSettingL());
       
   596 			break;
       
   597 			}
       
   598 		default:
       
   599 			break;
       
   600 		}
       
   601 
       
   602 		// Get timestamp of cre file. It is now possible for the commit to
       
   603 		// fail with KErrNoMemory after a successful write. If filestamp
       
   604 		// changes, the cre file has been written and the test is complete
       
   605 		TEST2 (GetFileTimeStamp(KCreTestFile1, after), KErrNone);
       
   606 		if(before!=after)
       
   607 			{
       
   608 			err=KErrNone;
       
   609 			}
       
   610 
       
   611 		if(err == KErrNoMemory)
       
   612 			{
       
   613 			__UHEAP_MARKEND;
       
   614 			//DoSetSettingL() call failed (so the transaction). Try to recover.
       
   615 			TInt err2;
       
   616 			TRAP(err2, ::DoRecoverRepositoryL(aSettingType));
       
   617 			TEST2(err2, KErrNone);
       
   618 			}
       
   619 		else if(err == KErrNone)
       
   620 			{
       
   621 			//The heap cannot be checked at this point because memory may have been
       
   622 			//allocated which must be freed by a call to ReleaseEnv2.
       
   623 			//It is checked outside the loop instead
       
   624 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
       
   625 			break;
       
   626 			}
       
   627 		else
       
   628 			{
       
   629 			__UHEAP_MARKEND;
       
   630 			TEST2(err, KErrNone);
       
   631 			}
       
   632 		// Check that tmp file generated by attempted commit is deleted
       
   633 		// by RestoreConsistencyL() in DoRecoverRepositoryL().
       
   634 		::CheckTmpFileDeleted();
       
   635 		}
       
   636 	// Check that no tmp file is left over
       
   637 	::ReleaseEnv2();
       
   638 	::ReleaseEnv();
       
   639 	//This __UHEAP_MARKEND checks the heap after the call to DoSetxSettings
       
   640 	//succeeds as calls to CommitTRansactions can allocate memory which must be freed
       
   641 	//by calling ReleaseEnv2
       
   642 	__UHEAP_MARKEND;
       
   643 	__UHEAP_RESET;
       
   644 	}
       
   645 
       
   646 ///////////////////////////////////////////////////////////////////////////////////////
       
   647 
       
   648 void RunTestsL(TServerSetting::TType aSettingType)
       
   649 	{
       
   650 
       
   651 	TheTest.Next(_L("Create setting - OOM test - OOM Trapping off"));
       
   652 	::CreateSetting_OOMtestL(EFalse,aSettingType);
       
   653 
       
   654 	TheTest.Next(_L("Create setting - OOM test - OOM Trapping on"));
       
   655 	::CreateSetting_OOMtestL(ETrue,aSettingType);
       
   656 
       
   657 	TheTest.Next(_L("Set setting - transaction - OOM test"));
       
   658 	::SetSetting_OOMtest(aSettingType);
       
   659 
       
   660 	}
       
   661 
       
   662 static void MainL()
       
   663 	{
       
   664 	// create and install the active scheduler we need for the cache manager in TServerResources::InitialiseL
       
   665 	CActiveScheduler* cacheManagerAS=new(ELeave) CActiveScheduler;
       
   666 	CleanupStack::PushL(cacheManagerAS);
       
   667 	CActiveScheduler::Install(cacheManagerAS);
       
   668 
       
   669 	::DeleteFiles();
       
   670 
       
   671 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-CENTRALREPOSITORY-LEGACY-T_CENREPTRANS-0001 Int Setting Tests "));
       
   672 	RunTestsL(TServerSetting::EInt);
       
   673 
       
   674 	TheTest.Next(_L("Real Setting Tests"));
       
   675 	RunTestsL(TServerSetting::EReal);
       
   676 
       
   677 	TheTest.Next(_L("String Setting Tests"));
       
   678 	RunTestsL(TServerSetting::EString);
       
   679 
       
   680 	TheTest.End();
       
   681 	TheTest.Close();
       
   682 
       
   683 	CleanupStack::PopAndDestroy(cacheManagerAS);
       
   684 	}
       
   685 
       
   686 TInt E32Main()
       
   687 	{
       
   688 	__UHEAP_MARK;
       
   689 
       
   690 	CTrapCleanup* tc = CTrapCleanup::New();
       
   691 	TEST(tc != NULL);
       
   692 
       
   693 	TheTest.Title();
       
   694 	TRAPD(err, ::MainL());
       
   695 	TEST2(err, KErrNone);
       
   696 
       
   697 	::DeleteFiles();
       
   698 
       
   699 	delete tc;
       
   700 
       
   701 	__UHEAP_MARKEND;
       
   702 
       
   703 	User::Heap().Check();
       
   704 	return KErrNone;
       
   705 	}