cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "tscripttests.h"
       
    20 #include "t_testhandler.h"
       
    21 #include "t_certstoretests.h"
       
    22 #include "t_certstoreactions.h"
       
    23 
       
    24 #include <e32std.h>
       
    25 #include <f32file.h>
       
    26 #include <ECom.h>
       
    27 
       
    28 
       
    29 ///////////////
       
    30 
       
    31 #include "t_testsetup.h"
       
    32 #include "t_testactionspec.h"
       
    33 #include "t_input.h"
       
    34 #include "t_certstoreactionmemfail.h"
       
    35 #include "tcancel.h"
       
    36 #include "t_message.h"
       
    37 #include "tScriptSetup.h"
       
    38 #include "tHardcodedSetup.h"
       
    39 #include "t_testhandler.h"
       
    40 #include "t_output.h"
       
    41 #include "tTestSpec.h"
       
    42 #include "Ttesthandlersettings.h"
       
    43 
       
    44 /**
       
    45 *	--------------------------------------
       
    46 *	How this test works:
       
    47 *	--------------------------------------
       
    48 *
       
    49 *	RUN THIS TEST IN CONFIGURATION 1 (FILECERTSTORE.DLL SHOULD BE THE ONLY 
       
    50 *	ECOM PLUGIN IN Z:\SYSTEM\LIBS\PLUGINS).  IF WAPCERTSTORE.DLL IS PRESENT
       
    51 *	THIS TEST WILL HANG!!!
       
    52 *
       
    53 *	This test is designed to stress concurrent access to the filecertstore
       
    54 *	by multiple threads, and to check that the integrity of the store is
       
    55 *	retained.
       
    56 *
       
    57 *	The test consists of 3 scripts (certstoreconcurrent1-3.txt) which test various
       
    58 *	possible accesses to the filebased store (cert add, delete, set trust, applications
       
    59 *	and certificate retreival.  There are 27 possible ways to combine the 3 scripts.
       
    60 *	For each of these combinations, 3 threads are started and each is assigned a
       
    61 *	separate test handler and one of the scripts for that combination.  The threads
       
    62 *	then run together, accessing the store concurrently. 
       
    63 *	
       
    64 *	BECAUSE THE THREADS ARE RUNNING CONCURRENTLY, IT IS NOT POSSIBLE TO PREDICT
       
    65 *	THE RESULTS OF EACH TEST, EG IT IS NOT POSSIBLE TO DETERMINE WHETHER THE 
       
    66 *	CERTIFICATE THAT ONE THREAD WISHES TO DELETE IS ACTUALLY PRESENT IN THE STORE
       
    67 *	AT THAT TIME, SINCE ANOTHER THREAD MAY HAVE REMOVED IT.  BECAUSE OF THIS 
       
    68 *	THE SCRIPTS ARE MARKED WITH A testconcurrent FLAG TO INDICATE THAT THE FAIL
       
    69 *	RESULTS SHOULD BE DISREGARDED.  The results for each script are written to a
       
    70 *	separate file in EPOC directory \tcertstoreconcurrent\ on system drive thus by the end of the
       
    71 *	the test there are 81 such log files in the directory.
       
    72 *
       
    73 *	Following the 27 combinations of 3 threads, the test then runs a standard
       
    74 *	tcertstore test using one of the scripts used in general certstore testing
       
    75 *	(the script is determined by the command line for the entire test).  This
       
    76 *	runs in a single thread so results can be predicted.  Thus we check that 
       
    77 *	filecertstore integrity is maintained.  The log file for these tests are
       
    78 *	placed in EPOC system drive and should be inspected for errors as part of the
       
    79 *	testing procedure.
       
    80 *
       
    81 *	Thus to run these tests, the following command line should be used:
       
    82 *	tcertstoreconcurrent \tcertstore\scripts\unifiedcertstore2-conf1.txt \tcertstoreconcurrent1.log
       
    83 *	,the script and log file being on system drive.This runs script unifiedcertstore2-conf1 after the 
       
    84 *	threaded tests and logs	the test results to tcertstoreconcurrent1.log
       
    85 */
       
    86 
       
    87 //	3 scripts available, switch between them
       
    88 const static TText* scripts[] = {	_S("dummy for zero element"),
       
    89 									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent1.txt"), 
       
    90 									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent2.txt"),
       
    91 									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent3.txt")};
       
    92 
       
    93 
       
    94 const TInt KMaxIterations = 27;
       
    95 
       
    96 const TInt scriptCombinations[] = {	1,1,1,	1,1,2,	1,1,3,
       
    97 									1,2,1,	1,2,2,	1,2,3,
       
    98 									1,3,1,	1,3,2,	1,3,3,
       
    99 									2,1,1,	2,1,2,	2,1,3,
       
   100 									2,2,1,	2,2,2,	2,2,3,
       
   101 									2,3,1,	2,3,2,	2,3,3,
       
   102 									3,1,1,	3,1,2,	3,1,3,
       
   103 									3,2,1,	3,2,2,	3,2,3,
       
   104 									3,3,1,	3,3,2,	3,3,3};
       
   105 
       
   106 class TThreadData
       
   107 	{
       
   108 public:
       
   109 	void InitialiseL(TInt aIteration, TInt aScriptNum);
       
   110 public:	
       
   111 	TPtrC iScriptFile;
       
   112 	TFileName iLogFile;
       
   113 	};
       
   114 
       
   115 void TThreadData::InitialiseL(TInt aIteration, TInt aThreadNum)
       
   116 	{
       
   117 	ASSERT(aIteration >= 0 && aIteration < KMaxIterations);
       
   118 	ASSERT(aThreadNum >= 1 && aThreadNum <= 3);
       
   119 
       
   120 	TInt script = scriptCombinations[aIteration * 3 + aThreadNum - 1];		
       
   121 	
       
   122 	// Set script file
       
   123 	TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   124 	TDriveName sysdriveName (sysDrive.Name());
       
   125 	TBuf <60> scriptFile (sysdriveName);
       
   126 	scriptFile.Append(scripts[script]);
       
   127 	iScriptFile.Set(scriptFile);
       
   128 
       
   129 	// Set log file
       
   130 	iLogFile.Zero();
       
   131 	TBuf<80> scriptName (sysdriveName);
       
   132 	scriptName.Append(_L("\\tcertstoreconcurrent\\iteration%02d_thread%d_script%d.txt"));
       
   133 	TBuf<80> buf ;
       
   134 	buf.Format(scriptName,aIteration, aThreadNum, script); 
       
   135 	iLogFile.Append(buf);
       
   136 	}
       
   137 
       
   138 
       
   139 LOCAL_C TInt ThreadEntryPoint(TAny* aArg)
       
   140 {
       
   141 	__UHEAP_MARK;
       
   142 
       
   143 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   144 
       
   145 	TThreadData* data = static_cast<TThreadData*>(aArg);
       
   146 	ASSERT(data);
       
   147 
       
   148 	TRAPD(r, DoTests(data->iScriptFile, data->iLogFile, ETrue));
       
   149 	//TRAPD(r, PerformTests(TestTypes(), data->iScriptFile, data->iLogFile));
       
   150 
       
   151 	ASSERT( (r==KErrNone) || (r==KErrInUse) );
       
   152 
       
   153 	delete cleanup;
       
   154 	
       
   155 	__UHEAP_MARKEND;
       
   156 
       
   157 	return (r);
       
   158 }
       
   159 
       
   160 /** Start a thread. */
       
   161 LOCAL_D void StartThreadL(RThread& aThread, TThreadData& aData, TInt aIteration, TInt aThreadNum, TRequestStatus& aStatus)
       
   162 	{
       
   163 	aData.InitialiseL(aIteration, aThreadNum);
       
   164 
       
   165 	TBuf<32> threadName;
       
   166 	threadName.Format(_L("iteration%02d_thread%d"), aIteration, aThreadNum);
       
   167 	
       
   168 	RHeap* heap = User::ChunkHeap(NULL, KMinHeapSize, 0x100000);
       
   169 	User::LeaveIfNull(heap);
       
   170 	User::LeaveIfError(aThread.Create(threadName, ThreadEntryPoint, KDefaultStackSize, heap, (TAny*)&aData));	
       
   171 	aStatus = KRequestPending;
       
   172 	aThread.Logon(aStatus);
       
   173 	aThread.Resume();
       
   174 	}
       
   175 
       
   176 //	Kicks off each thread for multiple concurrent certstore access
       
   177 LOCAL_D TBool DoThreadedTestsL(CConsoleBase* console, HBufC* logFileName, TBool wait)
       
   178 {
       
   179  	RFs myfs;
       
   180  	CleanupClosePushL(myfs);
       
   181  
       
   182  	RFile logfile;
       
   183  	CleanupClosePushL(logfile);
       
   184  
       
   185  	Output* out;
       
   186  	
       
   187  	User::LeaveIfError(myfs.Connect());
       
   188  	User::LeaveIfError(logfile.Replace(myfs, *logFileName, EFileWrite));
       
   189  
       
   190  	out = new (ELeave) FileOutput(logfile);
       
   191  	CleanupStack::PushL(out);
       
   192 
       
   193 	TInt failureCount = 0;
       
   194 	
       
   195 	for (TInt i = 0 ; i < KMaxIterations; ++i)
       
   196 		{
       
   197 		console->Printf(_L("Iteration %d \n"), i);
       
   198 		out->writeNewLine();
       
   199 		out->writeString(_L("Iteration "));
       
   200 		out->writeNum(i);
       
   201 		out->writeNewLine();
       
   202 
       
   203 		RThread thread1;
       
   204 		TThreadData data1;
       
   205 		TRequestStatus status1;
       
   206 		StartThreadL(thread1, data1, i, 1, status1);
       
   207 
       
   208 		RThread thread2;
       
   209 		TThreadData data2;
       
   210 		TRequestStatus status2;
       
   211 		StartThreadL(thread2, data2, i, 2, status2);
       
   212 
       
   213 		RThread thread3;
       
   214 		TThreadData data3;
       
   215 		TRequestStatus status3;
       
   216 		StartThreadL(thread3, data3, i, 3, status3);
       
   217 		
       
   218 		User::WaitForRequest(status1);
       
   219 		User::WaitForRequest(status2);
       
   220 		User::WaitForRequest(status3);
       
   221 
       
   222 		TExitType exit1 = thread1.ExitType();
       
   223 		TExitType exit2 = thread2.ExitType();
       
   224 		TExitType exit3 = thread3.ExitType();
       
   225 		
       
   226 		if (exit1 != EExitKill) 
       
   227 			{
       
   228 			console->Printf(_L("ERROR: Thread 1 exited with exit type: %d \n"), exit1);
       
   229  			out->writeString(_L("ERROR: Thread 1 exited with exit type: "));
       
   230 			out->writeNum(exit1);
       
   231 	 		out->writeNewLine();
       
   232 			failureCount++;
       
   233 			}
       
   234 		if (exit2 != EExitKill) 		
       
   235 			{
       
   236 			console->Printf(_L("ERROR: Thread 2 exited with exit type: %d \n"), exit2);
       
   237  			out->writeString(_L("ERROR: Thread 2 exited with exit type: "));
       
   238 			out->writeNum(exit2);
       
   239 	 		out->writeNewLine();			
       
   240 			failureCount++;
       
   241 			}
       
   242 		if (exit3 != EExitKill) 
       
   243 			{
       
   244 			console->Printf(_L("ERROR: Thread 3 exited with exit type: %d \n"), exit3);
       
   245  			out->writeString(_L("ERROR: Thread 2 exited with exit type: "));
       
   246 			out->writeNum(exit3);
       
   247 	 		out->writeNewLine();			
       
   248 			failureCount++;
       
   249 			}
       
   250 				
       
   251 		thread1.Heap()->Close();
       
   252 		thread2.Heap()->Close();
       
   253 		thread3.Heap()->Close();
       
   254 		
       
   255 		thread1.Close();
       
   256 		thread2.Close();
       
   257 		thread3.Close(); 
       
   258 
       
   259 		User::LeaveIfError(status1.Int());
       
   260 		User::LeaveIfError(status2.Int());
       
   261 		User::LeaveIfError(status3.Int());		
       
   262 	}
       
   263 	if (failureCount > 0) 
       
   264  		{
       
   265  		out->writeNewLine();
       
   266 		console->Printf(_L("\n %d tests failed out of %d \n"), failureCount, (KMaxIterations*3));
       
   267  		out->writeNewLine();
       
   268  		out->writeNum(failureCount);
       
   269  		out->writeString(_L(" tests failed out of "));
       
   270  		out->writeNum(KMaxIterations*3);
       
   271  		out->writeNewLine();		
       
   272  		}
       
   273  	if (wait) 
       
   274  		{
       
   275 		console->Printf(_L("\n Press any key to continue \n"));		
       
   276 		console->Getch();
       
   277  		}
       
   278  	CleanupStack::PopAndDestroy(out);
       
   279  	CleanupStack::PopAndDestroy(&logfile);
       
   280  	CleanupStack::PopAndDestroy(&myfs); 	
       
   281  	if (failureCount>0) 
       
   282  		{
       
   283  		return EFalse;
       
   284  		}
       
   285  	return ETrue;
       
   286 }
       
   287 
       
   288 
       
   289 /**
       
   290  * Extracts the nPos command line argument.
       
   291  */
       
   292 LOCAL_D HBufC* GetArgument(TInt nPos)
       
   293 	{
       
   294 	HBufC *argv = HBufC::NewLC(User::CommandLineLength());
       
   295 	TPtr cmd(argv->Des());
       
   296 	User::CommandLine(cmd);
       
   297 
       
   298 	TLex arguments(cmd);
       
   299 
       
   300 	// finds nth parameter 
       
   301 	while(nPos && !arguments.Eos())
       
   302 		{
       
   303 		TPtrC token = arguments.NextToken();
       
   304 		if(token.Length() > 0)		
       
   305 			nPos--;
       
   306 		}
       
   307 
       
   308 	HBufC* result = NULL;
       
   309 	if(!arguments.Eos())
       
   310 		{
       
   311 		TPtrC testfile(arguments.NextToken());
       
   312 
       
   313 		if(testfile.Length() > 0)
       
   314 			result = testfile.AllocL();
       
   315 		};
       
   316 
       
   317 	// no parameter found, but must return something so..
       
   318 	if(!result)
       
   319 		result = HBufC::NewL(0);
       
   320 
       
   321 	CleanupStack::PopAndDestroy(argv);
       
   322 
       
   323 	return result;
       
   324 	}
       
   325 
       
   326 /**
       
   327  * This function sets up a console, a log file and checks
       
   328  * whether we need to wait for a key pressed after test 
       
   329  * completion.
       
   330  * First DoThreadedTestsL is called, if everything is ok
       
   331  * it return ETrue and we move on to the standard tests.
       
   332  * If something went amiss (return EFalse) we skip 
       
   333  * the standard test and return. 
       
   334  */
       
   335 LOCAL_D void SetupAndRunTests() 
       
   336 {
       
   337 
       
   338 	CConsoleBase* console = Console::NewL(_L("Test code"), TSize(KConsFullScreen, KConsFullScreen));
       
   339 	
       
   340 	HBufC* logFile = GetArgument(1);
       
   341 	
       
   342 	if (logFile->Length()==0) 
       
   343 		{
       
   344 		_LIT(defaultLog, "\\tcertstore.log");
       
   345 		TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   346 		TDriveName sysdriveName (sysDrive.Name());
       
   347 		TBuf <18> fileName (sysdriveName);
       
   348 		fileName.Append(defaultLog);
       
   349 		logFile->ReAlloc(18);
       
   350 		TPtr16 plog = logFile->Des();
       
   351 		plog.Append(fileName);
       
   352 		}
       
   353 		
       
   354 	HBufC* wait = GetArgument(2);
       
   355 
       
   356 	TBool waitAfterCompletion = EFalse;
       
   357 	if (wait->Find(_L("-w")) != KErrNotFound) 
       
   358 		{
       
   359 		waitAfterCompletion = ETrue;
       
   360 		}
       
   361 	
       
   362 	TBool res = EFalse;	
       
   363 	TRAPD(err, res = DoThreadedTestsL(console, logFile, waitAfterCompletion));
       
   364 	
       
   365 	if (res) 
       
   366 		{
       
   367 		// Now run a normal tcertstore test to check store integrity
       
   368 		TRAP(err, DoTests());
       
   369 		}
       
   370 		
       
   371 	delete console;
       
   372 	delete wait;
       
   373 	delete logFile;
       
   374 }
       
   375 
       
   376 GLDEF_C TInt E32Main()
       
   377 {
       
   378 	__UHEAP_MARK;
       
   379 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   380 	
       
   381 	TRAPD(err, SetupAndRunTests());
       
   382 	
       
   383 	REComSession::FinalClose();
       
   384 
       
   385 	delete cleanup;
       
   386 
       
   387 	__UHEAP_MARKEND;
       
   388 	return 0;
       
   389 }