os/security/cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp
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 +}