os/security/cryptoservices/certificateandkeymgmt/tcertstore/tcertstoreconcurrent.cpp
First public contribution.
2 * Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "tScriptTests.h"
20 #include "t_testhandler.h"
21 #include "t_certstoretests.h"
22 #include "t_certstoreactions.h"
26 #include <ecom/ecom.h>
31 #include "t_testsetup.h"
32 #include "t_testactionspec.h"
34 #include "t_certstoreactionmemfail.h"
36 #include "t_message.h"
37 #include "tScriptSetup.h"
38 #include "tHardcodedSetup.h"
39 #include "t_testhandler.h"
41 #include "tTestSpec.h"
42 #include "Ttesthandlersettings.h"
45 * --------------------------------------
46 * How this test works:
47 * --------------------------------------
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!!!
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
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.
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.
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
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
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")};
94 const TInt KMaxIterations = 27;
96 const TInt scriptCombinations[] = { 1,1,1, 1,1,2, 1,1,3,
104 3,3,1, 3,3,2, 3,3,3};
109 void InitialiseL(TInt aIteration, TInt aScriptNum);
115 void TThreadData::InitialiseL(TInt aIteration, TInt aThreadNum)
117 ASSERT(aIteration >= 0 && aIteration < KMaxIterations);
118 ASSERT(aThreadNum >= 1 && aThreadNum <= 3);
120 TInt script = scriptCombinations[aIteration * 3 + aThreadNum - 1];
123 TDriveUnit sysDrive (RFs::GetSystemDrive());
124 TDriveName sysdriveName (sysDrive.Name());
125 TBuf <60> scriptFile (sysdriveName);
126 scriptFile.Append(scripts[script]);
127 iScriptFile.Set(scriptFile);
131 TBuf<80> scriptName (sysdriveName);
132 scriptName.Append(_L("\\tcertstoreconcurrent\\iteration%02d_thread%d_script%d.txt"));
134 buf.Format(scriptName,aIteration, aThreadNum, script);
135 iLogFile.Append(buf);
139 LOCAL_C TInt ThreadEntryPoint(TAny* aArg)
143 CTrapCleanup* cleanup=CTrapCleanup::New();
145 TThreadData* data = static_cast<TThreadData*>(aArg);
148 TRAPD(r, DoTests(data->iScriptFile, data->iLogFile, ETrue));
149 //TRAPD(r, PerformTests(TestTypes(), data->iScriptFile, data->iLogFile));
151 ASSERT( (r==KErrNone) || (r==KErrInUse) );
160 /** Start a thread. */
161 LOCAL_D void StartThreadL(RThread& aThread, TThreadData& aData, TInt aIteration, TInt aThreadNum, TRequestStatus& aStatus)
163 aData.InitialiseL(aIteration, aThreadNum);
166 threadName.Format(_L("iteration%02d_thread%d"), aIteration, aThreadNum);
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);
176 // Kicks off each thread for multiple concurrent certstore access
177 LOCAL_D TBool DoThreadedTestsL(CConsoleBase* console, HBufC* logFileName, TBool wait)
180 CleanupClosePushL(myfs);
183 CleanupClosePushL(logfile);
187 User::LeaveIfError(myfs.Connect());
188 User::LeaveIfError(logfile.Replace(myfs, *logFileName, EFileWrite));
190 out = new (ELeave) FileOutput(logfile);
191 CleanupStack::PushL(out);
193 TInt failureCount = 0;
195 for (TInt i = 0 ; i < KMaxIterations; ++i)
197 console->Printf(_L("Iteration %d \n"), i);
199 out->writeString(_L("Iteration "));
205 TRequestStatus status1;
206 StartThreadL(thread1, data1, i, 1, status1);
210 TRequestStatus status2;
211 StartThreadL(thread2, data2, i, 2, status2);
215 TRequestStatus status3;
216 StartThreadL(thread3, data3, i, 3, status3);
218 User::WaitForRequest(status1);
219 User::WaitForRequest(status2);
220 User::WaitForRequest(status3);
222 TExitType exit1 = thread1.ExitType();
223 TExitType exit2 = thread2.ExitType();
224 TExitType exit3 = thread3.ExitType();
226 if (exit1 != EExitKill)
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);
234 if (exit2 != EExitKill)
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);
242 if (exit3 != EExitKill)
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);
251 thread1.Heap()->Close();
252 thread2.Heap()->Close();
253 thread3.Heap()->Close();
259 User::LeaveIfError(status1.Int());
260 User::LeaveIfError(status2.Int());
261 User::LeaveIfError(status3.Int());
263 if (failureCount > 0)
266 console->Printf(_L("\n %d tests failed out of %d \n"), failureCount, (KMaxIterations*3));
268 out->writeNum(failureCount);
269 out->writeString(_L(" tests failed out of "));
270 out->writeNum(KMaxIterations*3);
275 console->Printf(_L("\n Press any key to continue \n"));
278 CleanupStack::PopAndDestroy(out);
279 CleanupStack::PopAndDestroy(&logfile);
280 CleanupStack::PopAndDestroy(&myfs);
290 * Extracts the nPos command line argument.
292 LOCAL_D HBufC* GetArgument(TInt nPos)
294 HBufC *argv = HBufC::NewLC(User::CommandLineLength());
295 TPtr cmd(argv->Des());
296 User::CommandLine(cmd);
300 // finds nth parameter
301 while(nPos && !arguments.Eos())
303 TPtrC token = arguments.NextToken();
304 if(token.Length() > 0)
308 HBufC* result = NULL;
311 TPtrC testfile(arguments.NextToken());
313 if(testfile.Length() > 0)
314 result = testfile.AllocL();
317 // no parameter found, but must return something so..
319 result = HBufC::NewL(0);
321 CleanupStack::PopAndDestroy(argv);
327 * This function sets up a console, a log file and checks
328 * whether we need to wait for a key pressed after test
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.
335 LOCAL_D void SetupAndRunTests()
338 CConsoleBase* console = Console::NewL(_L("Test code"), TSize(KConsFullScreen, KConsFullScreen));
340 HBufC* logFile = GetArgument(1);
342 if (logFile->Length()==0)
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);
354 HBufC* wait = GetArgument(2);
356 TBool waitAfterCompletion = EFalse;
357 if (wait->Find(_L("-w")) != KErrNotFound)
359 waitAfterCompletion = ETrue;
363 TRAPD(err, res = DoThreadedTestsL(console, logFile, waitAfterCompletion));
367 // Now run a normal tcertstore test to check store integrity
368 TRAP(err, DoTests());
376 GLDEF_C TInt E32Main()
379 CTrapCleanup* cleanup=CTrapCleanup::New();
381 TRAPD(err, SetupAndRunTests());
383 REComSession::FinalClose();