os/security/cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 1998-2010 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/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 }