First public contribution.
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\stack\t_stacksize.cpp
16 // Verifies the correct implementation of CreateStackOverride method of RProcess.
17 // Meanings of constants:
19 // - System wide default stack size in actual version;
20 // KNumberOfFitIteration:
21 // - Number of DummyRecursion which can fit in KDefaultStackSize.
22 // Value = KDefaultStackSize / 2KB - 1
23 // KNumberOfUnfitIteration:
24 // - Number of DummyRecursion which is raised a Panic based on stack overflow.
25 // Value = KDefaultStackSize / 2KB rounded up to nearest integer
27 // ETestProcess1: Create a process with original RProcess::Create() and start it
28 // - it passes with KNumberOfFitIteration DummyRecursion .
29 // ETestProcess2: Create a process with RProcess::CreateWithStackOverride(), default
30 // stack size and start it
31 // - it passes with KNumberOfFitIteration DummyRecursion.
32 // ETestProcess3: Create a process with original RProcess::Create() and start it
33 // - it raised Panic on Stack overflow with KNumberOfUnfitIteration DummyRecursion.
34 // ETestProcess4: Create a process with RProcess::CreateWithStackOverride(), default
35 // stack size and start it
36 // - it raised Panic on Stack overflow with KNumberOfUnfitIteration DummyRecursion.
37 // ETestProcess5: Create a process with RProcess::CreateWithStackOverride(), 2*KDefaultStackSize
39 // - it passes with KNumberOfUnfitIteration DummyRecursion.
40 // ETestProcess6: Create a process with RProcess::CreateWithStackOverride(), -2*KDefaultStackSize
42 // - the process creation interrupted with KErrArgument error code
43 // ETestProcess7: Create a process with RProcess::CreateWithStackOverride(), KDefaultStackSize/2
45 // - it passes with KNumberOfFitIteration DummyRecursion, because the process will be
46 // create with (App. image) default stack size.
47 // Platforms/Drives/Compatibility:
48 // It is won't work on emulator, because the unlimited stack size.
49 // Assumptions/Requirement/Pre-requisites:
51 // Failures and causes:
52 // Failures of this test will indicate defects in the implementation of CreateWithStackOverride().
53 // Base Port information:
63 LOCAL_D RTest test(_L("T_STACKSIZE"));
64 LOCAL_D RTest test2(_L("*** T_STACKSIZE SLAVE ***"));
66 // We are here making the assumption that one quarter of the stack should be sufficient
67 // to accommodate for the overhead generated by the recursive calls as well as
68 // unpredictable compiler optimisations.
69 const TInt KStackGobbleSize = KDefaultStackSize / 4 - 8;
70 const TInt KNumberOfFitIteration = 3;
71 const TInt KNumberOfUnfitIteration = 4;
73 const TInt KImageStackSize = 0x2000; // Test app image stack size (epocstacksize in MMP file)
75 enum TTestProcessFunctions
86 class RTestProcess : public RProcess
89 TInt Create(TTestProcessFunctions aFunction, TInt aStackSize=0, TInt aArg1=-1,TInt aArg2=-1);
92 TInt RTestProcess::Create(TTestProcessFunctions aFunction, TInt aStackSize, TInt aArg1,TInt aArg2)
95 test.Printf(_L("RTestProcess::Create started with stack size:%d bytes\n"), aStackSize);
97 aArg1 = RProcess().Id();
98 TBuf<512> commandLine;
99 commandLine.Num((TInt)aFunction);
100 commandLine.Append(_L(" "));
101 commandLine.AppendNum(aArg1);
102 commandLine.Append(_L(" "));
103 commandLine.AppendNum(aArg2);
105 TFileName filename(RProcess().FileName());
106 TInt pos=filename.LocateReverse(TChar('\\'));
107 filename.SetLength(pos+1);
108 filename+=_L("T_STACKSIZE.EXE");
114 test.Printf(_L("Call original Create.\n"));
115 r = RProcess::Create(filename,commandLine);
119 test.Printf(_L("Call CreateWithStackOverride\n"));
120 r = RProcess::CreateWithStackOverride(filename, commandLine, TUidType(), aStackSize, EOwnerProcess);
124 test.Printf(_L("Call original Create.\n"));
125 r = RProcess::Create(filename,commandLine);
129 test.Printf(_L("Call CreateWithStackOverride\n"));
130 r = RProcess::CreateWithStackOverride(filename, commandLine, TUidType(), aStackSize, EOwnerProcess);
134 test.Printf(_L("Call CreateWithStackOverride\n"));
135 r = RProcess::CreateWithStackOverride(filename, commandLine, TUidType(), aStackSize, EOwnerProcess);
139 test.Printf(_L("Call CreateWithStackOverride\n"));
140 r = RProcess::CreateWithStackOverride(filename, commandLine, TUidType(), aStackSize, EOwnerProcess);
144 test.Printf(_L("Call CreateWithStackOverride\n"));
145 r = RProcess::CreateWithStackOverride(filename, commandLine, TUidType(), aStackSize, EOwnerProcess);
149 User::Panic(_L("T_STACKSIZE"),1);
153 test.Printf(_L("RTestProcess::Create end.\n"));
158 TInt DummyRecursion(TInt aA)
160 TBuf8<KStackGobbleSize> gobble; // gobble 1/4 of the stack
161 gobble.Append(TChar(aA)); // stop compiler optimising out gobble buffer
164 return 1 + DummyRecursion(aA-1);
167 // Make these global so we don't push too much stuff on the stack
168 TThreadStackInfo ThreadStackInfo;
169 _LIT(KStackSizeText, "Stack size is %d bytes\n");
171 TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
175 RThread().StackInfo(ThreadStackInfo);
181 test2.Printf(_L("ETestProcess1 started with %d recursion...\n"), KNumberOfFitIteration);
182 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
184 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KDefaultStackSize);
186 test2(DummyRecursion(KNumberOfFitIteration)==KNumberOfFitIteration);
192 test2.Printf(_L("ETestProcess2 started with %d recursion...\n"), KNumberOfFitIteration);
193 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
195 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KDefaultStackSize);
197 test2(DummyRecursion(KNumberOfFitIteration)==KNumberOfFitIteration);
203 test2.Printf(_L("ETestProcess3 started with %d recusion...\n"), KNumberOfUnfitIteration);
204 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
206 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KDefaultStackSize);
208 test2(DummyRecursion(KNumberOfUnfitIteration)==KNumberOfUnfitIteration);
214 test2.Printf(_L("ETestProcess4 started with %d recursion...\n"), KNumberOfUnfitIteration);
215 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
217 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KDefaultStackSize);
219 test2(DummyRecursion(KNumberOfUnfitIteration)==KNumberOfUnfitIteration);
225 test2.Printf(_L("ETestProcess5 started with %d recursion...\n"), KNumberOfUnfitIteration);
226 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
228 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KDefaultStackSize * 2);
230 test2(DummyRecursion(KNumberOfUnfitIteration)==KNumberOfUnfitIteration);
236 test2(EFalse); // Process creation should have failed
241 test2.Printf(_L("ETestProcess7 started with %d recursion\n"), KNumberOfFitIteration);
242 test2.Printf(KStackSizeText, ThreadStackInfo.iBase - ThreadStackInfo.iLimit);
244 test2((TInt) (ThreadStackInfo.iBase - ThreadStackInfo.iLimit) == KImageStackSize); // Should default to stack size set in image header
245 if (KImageStackSize == KDefaultStackSize) // If this is not the case, results can be a bit unpredictable
247 test2(DummyRecursion(KNumberOfFitIteration)==KNumberOfFitIteration);
254 User::Panic(_L("T_STACKSIZE"),1);
257 test2.Printf(_L("\n\t finished.\n"));
262 GLDEF_C TInt E32Main()
267 User::CommandLine(cmd);
268 if(cmd.Length() && TChar(cmd[0]).IsDigit())
271 test2.Start(_L("Slave process started..."));
281 int r = DoTestProcess(function,arg1,arg2);
289 TRequestStatus rendezvous;
291 test.Start(_L("Create process with original Create and default stack size"));
292 TInt r = rogueP.Create(ETestProcess1, KDefaultStackSize);
294 rogueP.Rendezvous(rendezvous);
296 User::WaitForRequest(rendezvous);
297 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType() );
298 test(rogueP.ExitType()==EExitKill);
299 CLOSE_AND_WAIT(rogueP);
301 test.Next(_L("Create process with CreateWithStackOverride and default stack size"));
302 r = rogueP.Create(ETestProcess2, KDefaultStackSize);
304 rogueP.Rendezvous(rendezvous);
306 User::WaitForRequest(rendezvous);
307 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType() );
308 test(rogueP.ExitType()==EExitKill);
309 CLOSE_AND_WAIT(rogueP);
311 test.Next(_L("Create process with original Create and default stack size"));
312 r = rogueP.Create(ETestProcess3, KDefaultStackSize);
314 rogueP.Rendezvous(rendezvous);
316 User::WaitForRequest(rendezvous);
317 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType() );
318 #if !defined(__WINS__)
319 test(rogueP.ExitType()==EExitPanic);
321 test(rogueP.ExitType()==EExitKill);
323 CLOSE_AND_WAIT(rogueP);
325 test.Next(_L("Create process with CreateWithStackOverride and default stack size"));
326 r = rogueP.Create(ETestProcess4, KDefaultStackSize);
328 rogueP.Rendezvous(rendezvous);
330 User::WaitForRequest(rendezvous);
331 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType());
332 #if !defined(__WINS__)
333 test(rogueP.ExitType()==EExitPanic);
335 test(rogueP.ExitType()==EExitKill);
337 CLOSE_AND_WAIT(rogueP);
339 test.Next(_L("Create process with CreateWithStackOverride and 2 * KDefaultStackSize stack size"));
340 r = rogueP.Create(ETestProcess5, 2 * KDefaultStackSize );
342 rogueP.Rendezvous(rendezvous);
344 User::WaitForRequest(rendezvous);
345 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType() );
346 test(rogueP.ExitType()==EExitKill);
347 CLOSE_AND_WAIT(rogueP);
349 #if !defined(__WINS__)
350 test.Next(_L("Create process with CreateWithStackOverride and negative stack size"));
351 r = rogueP.Create(ETestProcess6, - 2 * KDefaultStackSize );
352 test(r==KErrArgument);
355 test.Next(_L("Create process with CreateWithStackOverride and KImageStackSize/2 stack size"));
356 r = rogueP.Create(ETestProcess7, KImageStackSize / 2 );
358 rogueP.Rendezvous(rendezvous);
360 User::WaitForRequest(rendezvous);
361 test.Printf(_L("ExitType:%d\n"),rogueP.ExitType() );
362 test(rogueP.ExitType()==EExitKill);
363 CLOSE_AND_WAIT(rogueP);
365 test.Printf(_L("Test finished.\n"));