os/security/cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,389 @@
     1.4 +/*
     1.5 +* Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +#include "tScriptTests.h"
    1.23 +#include "t_testhandler.h"
    1.24 +#include "t_certstoretests.h"
    1.25 +#include "t_certstoreactions.h"
    1.26 +
    1.27 +#include <e32std.h>
    1.28 +#include <f32file.h>
    1.29 +#include <ecom/ecom.h>
    1.30 +
    1.31 +
    1.32 +///////////////
    1.33 +
    1.34 +#include "t_testsetup.h"
    1.35 +#include "t_testactionspec.h"
    1.36 +#include "t_input.h"
    1.37 +#include "t_certstoreactionmemfail.h"
    1.38 +#include "tcancel.h"
    1.39 +#include "t_message.h"
    1.40 +#include "tScriptSetup.h"
    1.41 +#include "tHardcodedSetup.h"
    1.42 +#include "t_testhandler.h"
    1.43 +#include "t_output.h"
    1.44 +#include "tTestSpec.h"
    1.45 +#include "Ttesthandlersettings.h"
    1.46 +
    1.47 +/**
    1.48 +*	--------------------------------------
    1.49 +*	How this test works:
    1.50 +*	--------------------------------------
    1.51 +*
    1.52 +*	RUN THIS TEST IN CONFIGURATION 1 (FILECERTSTORE.DLL SHOULD BE THE ONLY 
    1.53 +*	ECOM PLUGIN IN Z:\SYSTEM\LIBS\PLUGINS).  IF WAPCERTSTORE.DLL IS PRESENT
    1.54 +*	THIS TEST WILL HANG!!!
    1.55 +*
    1.56 +*	This test is designed to stress concurrent access to the filecertstore
    1.57 +*	by multiple threads, and to check that the integrity of the store is
    1.58 +*	retained.
    1.59 +*
    1.60 +*	The test consists of 3 scripts (certstoreconcurrent1-3.txt) which test various
    1.61 +*	possible accesses to the filebased store (cert add, delete, set trust, applications
    1.62 +*	and certificate retreival.  There are 27 possible ways to combine the 3 scripts.
    1.63 +*	For each of these combinations, 3 threads are started and each is assigned a
    1.64 +*	separate test handler and one of the scripts for that combination.  The threads
    1.65 +*	then run together, accessing the store concurrently. 
    1.66 +*	
    1.67 +*	BECAUSE THE THREADS ARE RUNNING CONCURRENTLY, IT IS NOT POSSIBLE TO PREDICT
    1.68 +*	THE RESULTS OF EACH TEST, EG IT IS NOT POSSIBLE TO DETERMINE WHETHER THE 
    1.69 +*	CERTIFICATE THAT ONE THREAD WISHES TO DELETE IS ACTUALLY PRESENT IN THE STORE
    1.70 +*	AT THAT TIME, SINCE ANOTHER THREAD MAY HAVE REMOVED IT.  BECAUSE OF THIS 
    1.71 +*	THE SCRIPTS ARE MARKED WITH A testconcurrent FLAG TO INDICATE THAT THE FAIL
    1.72 +*	RESULTS SHOULD BE DISREGARDED.  The results for each script are written to a
    1.73 +*	separate file in EPOC directory \tcertstoreconcurrent\ on system drive thus by the end of the
    1.74 +*	the test there are 81 such log files in the directory.
    1.75 +*
    1.76 +*	Following the 27 combinations of 3 threads, the test then runs a standard
    1.77 +*	tcertstore test using one of the scripts used in general certstore testing
    1.78 +*	(the script is determined by the command line for the entire test).  This
    1.79 +*	runs in a single thread so results can be predicted.  Thus we check that 
    1.80 +*	filecertstore integrity is maintained.  The log file for these tests are
    1.81 +*	placed in EPOC system drive and should be inspected for errors as part of the
    1.82 +*	testing procedure.
    1.83 +*
    1.84 +*	Thus to run these tests, the following command line should be used:
    1.85 +*	tcertstoreconcurrent \tcertstore\scripts\unifiedcertstore2-conf1.txt \tcertstoreconcurrent1.log
    1.86 +*	,the script and log file being on system drive.This runs script unifiedcertstore2-conf1 after the 
    1.87 +*	threaded tests and logs	the test results to tcertstoreconcurrent1.log
    1.88 +*/
    1.89 +
    1.90 +//	3 scripts available, switch between them
    1.91 +const static TText* scripts[] = {	_S("dummy for zero element"),
    1.92 +									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent1.txt"), 
    1.93 +									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent2.txt"),
    1.94 +									_S("\\tcertstoreconcurrent\\scripts\\certstoreconcurrent3.txt")};
    1.95 +
    1.96 +
    1.97 +const TInt KMaxIterations = 27;
    1.98 +
    1.99 +const TInt scriptCombinations[] = {	1,1,1,	1,1,2,	1,1,3,
   1.100 +									1,2,1,	1,2,2,	1,2,3,
   1.101 +									1,3,1,	1,3,2,	1,3,3,
   1.102 +									2,1,1,	2,1,2,	2,1,3,
   1.103 +									2,2,1,	2,2,2,	2,2,3,
   1.104 +									2,3,1,	2,3,2,	2,3,3,
   1.105 +									3,1,1,	3,1,2,	3,1,3,
   1.106 +									3,2,1,	3,2,2,	3,2,3,
   1.107 +									3,3,1,	3,3,2,	3,3,3};
   1.108 +
   1.109 +class TThreadData
   1.110 +	{
   1.111 +public:
   1.112 +	void InitialiseL(TInt aIteration, TInt aScriptNum);
   1.113 +public:	
   1.114 +	TPtrC iScriptFile;
   1.115 +	TFileName iLogFile;
   1.116 +	};
   1.117 +
   1.118 +void TThreadData::InitialiseL(TInt aIteration, TInt aThreadNum)
   1.119 +	{
   1.120 +	ASSERT(aIteration >= 0 && aIteration < KMaxIterations);
   1.121 +	ASSERT(aThreadNum >= 1 && aThreadNum <= 3);
   1.122 +
   1.123 +	TInt script = scriptCombinations[aIteration * 3 + aThreadNum - 1];		
   1.124 +	
   1.125 +	// Set script file
   1.126 +	TDriveUnit sysDrive (RFs::GetSystemDrive());
   1.127 +	TDriveName sysdriveName (sysDrive.Name());
   1.128 +	TBuf <60> scriptFile (sysdriveName);
   1.129 +	scriptFile.Append(scripts[script]);
   1.130 +	iScriptFile.Set(scriptFile);
   1.131 +
   1.132 +	// Set log file
   1.133 +	iLogFile.Zero();
   1.134 +	TBuf<80> scriptName (sysdriveName);
   1.135 +	scriptName.Append(_L("\\tcertstoreconcurrent\\iteration%02d_thread%d_script%d.txt"));
   1.136 +	TBuf<80> buf ;
   1.137 +	buf.Format(scriptName,aIteration, aThreadNum, script); 
   1.138 +	iLogFile.Append(buf);
   1.139 +	}
   1.140 +
   1.141 +
   1.142 +LOCAL_C TInt ThreadEntryPoint(TAny* aArg)
   1.143 +{
   1.144 +	__UHEAP_MARK;
   1.145 +
   1.146 +	CTrapCleanup* cleanup=CTrapCleanup::New();
   1.147 +
   1.148 +	TThreadData* data = static_cast<TThreadData*>(aArg);
   1.149 +	ASSERT(data);
   1.150 +
   1.151 +	TRAPD(r, DoTests(data->iScriptFile, data->iLogFile, ETrue));
   1.152 +	//TRAPD(r, PerformTests(TestTypes(), data->iScriptFile, data->iLogFile));
   1.153 +
   1.154 +	ASSERT( (r==KErrNone) || (r==KErrInUse) );
   1.155 +
   1.156 +	delete cleanup;
   1.157 +	
   1.158 +	__UHEAP_MARKEND;
   1.159 +
   1.160 +	return (r);
   1.161 +}
   1.162 +
   1.163 +/** Start a thread. */
   1.164 +LOCAL_D void StartThreadL(RThread& aThread, TThreadData& aData, TInt aIteration, TInt aThreadNum, TRequestStatus& aStatus)
   1.165 +	{
   1.166 +	aData.InitialiseL(aIteration, aThreadNum);
   1.167 +
   1.168 +	TBuf<32> threadName;
   1.169 +	threadName.Format(_L("iteration%02d_thread%d"), aIteration, aThreadNum);
   1.170 +	
   1.171 +	RHeap* heap = User::ChunkHeap(NULL, KMinHeapSize, 0x100000);
   1.172 +	User::LeaveIfNull(heap);
   1.173 +	User::LeaveIfError(aThread.Create(threadName, ThreadEntryPoint, KDefaultStackSize, heap, (TAny*)&aData));	
   1.174 +	aStatus = KRequestPending;
   1.175 +	aThread.Logon(aStatus);
   1.176 +	aThread.Resume();
   1.177 +	}
   1.178 +
   1.179 +//	Kicks off each thread for multiple concurrent certstore access
   1.180 +LOCAL_D TBool DoThreadedTestsL(CConsoleBase* console, HBufC* logFileName, TBool wait)
   1.181 +{
   1.182 + 	RFs myfs;
   1.183 + 	CleanupClosePushL(myfs);
   1.184 + 
   1.185 + 	RFile logfile;
   1.186 + 	CleanupClosePushL(logfile);
   1.187 + 
   1.188 + 	Output* out;
   1.189 + 	
   1.190 + 	User::LeaveIfError(myfs.Connect());
   1.191 + 	User::LeaveIfError(logfile.Replace(myfs, *logFileName, EFileWrite));
   1.192 + 
   1.193 + 	out = new (ELeave) FileOutput(logfile);
   1.194 + 	CleanupStack::PushL(out);
   1.195 +
   1.196 +	TInt failureCount = 0;
   1.197 +	
   1.198 +	for (TInt i = 0 ; i < KMaxIterations; ++i)
   1.199 +		{
   1.200 +		console->Printf(_L("Iteration %d \n"), i);
   1.201 +		out->writeNewLine();
   1.202 +		out->writeString(_L("Iteration "));
   1.203 +		out->writeNum(i);
   1.204 +		out->writeNewLine();
   1.205 +
   1.206 +		RThread thread1;
   1.207 +		TThreadData data1;
   1.208 +		TRequestStatus status1;
   1.209 +		StartThreadL(thread1, data1, i, 1, status1);
   1.210 +
   1.211 +		RThread thread2;
   1.212 +		TThreadData data2;
   1.213 +		TRequestStatus status2;
   1.214 +		StartThreadL(thread2, data2, i, 2, status2);
   1.215 +
   1.216 +		RThread thread3;
   1.217 +		TThreadData data3;
   1.218 +		TRequestStatus status3;
   1.219 +		StartThreadL(thread3, data3, i, 3, status3);
   1.220 +		
   1.221 +		User::WaitForRequest(status1);
   1.222 +		User::WaitForRequest(status2);
   1.223 +		User::WaitForRequest(status3);
   1.224 +
   1.225 +		TExitType exit1 = thread1.ExitType();
   1.226 +		TExitType exit2 = thread2.ExitType();
   1.227 +		TExitType exit3 = thread3.ExitType();
   1.228 +		
   1.229 +		if (exit1 != EExitKill) 
   1.230 +			{
   1.231 +			console->Printf(_L("ERROR: Thread 1 exited with exit type: %d \n"), exit1);
   1.232 + 			out->writeString(_L("ERROR: Thread 1 exited with exit type: "));
   1.233 +			out->writeNum(exit1);
   1.234 +	 		out->writeNewLine();
   1.235 +			failureCount++;
   1.236 +			}
   1.237 +		if (exit2 != EExitKill) 		
   1.238 +			{
   1.239 +			console->Printf(_L("ERROR: Thread 2 exited with exit type: %d \n"), exit2);
   1.240 + 			out->writeString(_L("ERROR: Thread 2 exited with exit type: "));
   1.241 +			out->writeNum(exit2);
   1.242 +	 		out->writeNewLine();			
   1.243 +			failureCount++;
   1.244 +			}
   1.245 +		if (exit3 != EExitKill) 
   1.246 +			{
   1.247 +			console->Printf(_L("ERROR: Thread 3 exited with exit type: %d \n"), exit3);
   1.248 + 			out->writeString(_L("ERROR: Thread 2 exited with exit type: "));
   1.249 +			out->writeNum(exit3);
   1.250 +	 		out->writeNewLine();			
   1.251 +			failureCount++;
   1.252 +			}
   1.253 +				
   1.254 +		thread1.Heap()->Close();
   1.255 +		thread2.Heap()->Close();
   1.256 +		thread3.Heap()->Close();
   1.257 +		
   1.258 +		thread1.Close();
   1.259 +		thread2.Close();
   1.260 +		thread3.Close(); 
   1.261 +
   1.262 +		User::LeaveIfError(status1.Int());
   1.263 +		User::LeaveIfError(status2.Int());
   1.264 +		User::LeaveIfError(status3.Int());		
   1.265 +	}
   1.266 +	if (failureCount > 0) 
   1.267 + 		{
   1.268 + 		out->writeNewLine();
   1.269 +		console->Printf(_L("\n %d tests failed out of %d \n"), failureCount, (KMaxIterations*3));
   1.270 + 		out->writeNewLine();
   1.271 + 		out->writeNum(failureCount);
   1.272 + 		out->writeString(_L(" tests failed out of "));
   1.273 + 		out->writeNum(KMaxIterations*3);
   1.274 + 		out->writeNewLine();		
   1.275 + 		}
   1.276 + 	if (wait) 
   1.277 + 		{
   1.278 +		console->Printf(_L("\n Press any key to continue \n"));		
   1.279 +		console->Getch();
   1.280 + 		}
   1.281 + 	CleanupStack::PopAndDestroy(out);
   1.282 + 	CleanupStack::PopAndDestroy(&logfile);
   1.283 + 	CleanupStack::PopAndDestroy(&myfs); 	
   1.284 + 	if (failureCount>0) 
   1.285 + 		{
   1.286 + 		return EFalse;
   1.287 + 		}
   1.288 + 	return ETrue;
   1.289 +}
   1.290 +
   1.291 +
   1.292 +/**
   1.293 + * Extracts the nPos command line argument.
   1.294 + */
   1.295 +LOCAL_D HBufC* GetArgument(TInt nPos)
   1.296 +	{
   1.297 +	HBufC *argv = HBufC::NewLC(User::CommandLineLength());
   1.298 +	TPtr cmd(argv->Des());
   1.299 +	User::CommandLine(cmd);
   1.300 +
   1.301 +	TLex arguments(cmd);
   1.302 +
   1.303 +	// finds nth parameter 
   1.304 +	while(nPos && !arguments.Eos())
   1.305 +		{
   1.306 +		TPtrC token = arguments.NextToken();
   1.307 +		if(token.Length() > 0)		
   1.308 +			nPos--;
   1.309 +		}
   1.310 +
   1.311 +	HBufC* result = NULL;
   1.312 +	if(!arguments.Eos())
   1.313 +		{
   1.314 +		TPtrC testfile(arguments.NextToken());
   1.315 +
   1.316 +		if(testfile.Length() > 0)
   1.317 +			result = testfile.AllocL();
   1.318 +		};
   1.319 +
   1.320 +	// no parameter found, but must return something so..
   1.321 +	if(!result)
   1.322 +		result = HBufC::NewL(0);
   1.323 +
   1.324 +	CleanupStack::PopAndDestroy(argv);
   1.325 +
   1.326 +	return result;
   1.327 +	}
   1.328 +
   1.329 +/**
   1.330 + * This function sets up a console, a log file and checks
   1.331 + * whether we need to wait for a key pressed after test 
   1.332 + * completion.
   1.333 + * First DoThreadedTestsL is called, if everything is ok
   1.334 + * it return ETrue and we move on to the standard tests.
   1.335 + * If something went amiss (return EFalse) we skip 
   1.336 + * the standard test and return. 
   1.337 + */
   1.338 +LOCAL_D void SetupAndRunTests() 
   1.339 +{
   1.340 +
   1.341 +	CConsoleBase* console = Console::NewL(_L("Test code"), TSize(KConsFullScreen, KConsFullScreen));
   1.342 +	
   1.343 +	HBufC* logFile = GetArgument(1);
   1.344 +	
   1.345 +	if (logFile->Length()==0) 
   1.346 +		{
   1.347 +		_LIT(defaultLog, "\\tcertstore.log");
   1.348 +		TDriveUnit sysDrive (RFs::GetSystemDrive());
   1.349 +		TDriveName sysdriveName (sysDrive.Name());
   1.350 +		TBuf <18> fileName (sysdriveName);
   1.351 +		fileName.Append(defaultLog);
   1.352 +		logFile->ReAlloc(18);
   1.353 +		TPtr16 plog = logFile->Des();
   1.354 +		plog.Append(fileName);
   1.355 +		}
   1.356 +		
   1.357 +	HBufC* wait = GetArgument(2);
   1.358 +
   1.359 +	TBool waitAfterCompletion = EFalse;
   1.360 +	if (wait->Find(_L("-w")) != KErrNotFound) 
   1.361 +		{
   1.362 +		waitAfterCompletion = ETrue;
   1.363 +		}
   1.364 +	
   1.365 +	TBool res = EFalse;	
   1.366 +	TRAPD(err, res = DoThreadedTestsL(console, logFile, waitAfterCompletion));
   1.367 +	
   1.368 +	if (res) 
   1.369 +		{
   1.370 +		// Now run a normal tcertstore test to check store integrity
   1.371 +		TRAP(err, DoTests());
   1.372 +		}
   1.373 +		
   1.374 +	delete console;
   1.375 +	delete wait;
   1.376 +	delete logFile;
   1.377 +}
   1.378 +
   1.379 +GLDEF_C TInt E32Main()
   1.380 +{
   1.381 +	__UHEAP_MARK;
   1.382 +	CTrapCleanup* cleanup=CTrapCleanup::New();
   1.383 +	
   1.384 +	TRAPD(err, SetupAndRunTests());
   1.385 +	
   1.386 +	REComSession::FinalClose();
   1.387 +
   1.388 +	delete cleanup;
   1.389 +
   1.390 +	__UHEAP_MARKEND;
   1.391 +	return 0;
   1.392 +}