|
1 // Copyright (c) 2006-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\secure\t_sprioritycap.cpp |
|
15 // Overview: |
|
16 // Test the platform security aspects of the RThread class as affected by the process priority |
|
17 // specified in the MMP file, mainly capping of higher thread priorities without ProtServ. |
|
18 // API Information: |
|
19 // Process priorities windowserver, fileserver, supervisor and realtimeserver set with |
|
20 // |
|
21 |
|
22 // # 'epocprocesspriority' keyword in MMP files |
|
23 // # 'priority' keyword in OBEY (OBY/IBY) files |
|
24 // Details: |
|
25 // - Tests that the desired thread prioritisation results are obtained for process priorities |
|
26 // SystemServer and RealTimeServer (established by separate MMP files): |
|
27 // # without ECapabilityProtServ - priorities capped to SystemServer/More. |
|
28 // # with ECapabilityProtServ - higher, "real-time" priorities obtainable. |
|
29 // - Tests effect of reduction of SystemServer/More from nanothread priority 24 to 23, |
|
30 // i.e. same priority as AbsoluteHigh |
|
31 // Platforms/Drives/Compatibility: |
|
32 // All. |
|
33 // Assumptions/Requirement/Pre-requisites: |
|
34 // Failures and causes: |
|
35 // Base Port information: |
|
36 // |
|
37 |
|
38 #include <e32test.h> |
|
39 |
|
40 LOCAL_D RTest test(_L("T_SPRIORITYCAP")); |
|
41 RMutex SyncMutex; |
|
42 TInt threadMutexAcquireOrder; // where 132 = thread 1 acquires mutex, then thread 3 then thread 2 |
|
43 _LIT(KTestPanicCategory,"TEST PANIC"); |
|
44 |
|
45 class RTestThread : public RThread |
|
46 { |
|
47 public: |
|
48 void Create(TThreadFunction aFunction,TAny* aArg=0); |
|
49 }; |
|
50 |
|
51 void RTestThread::Create(TThreadFunction aFunction,TAny* aThreadNumber) |
|
52 { |
|
53 TInt threadNumber = reinterpret_cast<TInt>(aThreadNumber); |
|
54 ASSERT((threadNumber > 0) && (threadNumber < 10)); |
|
55 TBuf<20> threadName = _L("TestThread_"); |
|
56 threadName.AppendNum(threadNumber); |
|
57 TInt r=RThread::Create(threadName,aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aThreadNumber); |
|
58 test(r==KErrNone); |
|
59 } |
|
60 |
|
61 TInt TestThreadWaitMutex(TAny* aThreadNumber) |
|
62 { |
|
63 TInt threadNumber = reinterpret_cast<TInt>(aThreadNumber); |
|
64 ASSERT((threadNumber > 0) && (threadNumber < 10)); |
|
65 RThread thisThread; |
|
66 thisThread.Rendezvous(KErrNone); |
|
67 SyncMutex.Wait(); |
|
68 threadMutexAcquireOrder = threadMutexAcquireOrder*10 + threadNumber; |
|
69 SyncMutex.Signal(); |
|
70 return KErrNone; |
|
71 } |
|
72 |
|
73 // Create three threads with priority 1, 2 and 1, each waiting on a mutex that is already held by the |
|
74 // main thread. Signal the mutex from the main thread and return the order the threads acquire it |
|
75 // as an integer where 132 = thread 1 acquires mutex, then thread 3 then thread 2. |
|
76 // |
|
77 // In order to work this test requires the three threads to wait on the mutex in the order listed. |
|
78 // This cannot be guaranteed, but the following points make it a near-certainty: |
|
79 // (1) This main thread runs at lowest priority |
|
80 // (2) The three threads initially resume at higher, decreasing priorities. |
|
81 // (3) We Rendezvous() with the thread just before it waits on the mutex |
|
82 // (4) Wait some time before creating next thread |
|
83 // (5) Actual priorities are set after all test threads are waiting |
|
84 TInt TestThreadMutexAcquireOrder(TThreadPriority aPriorityThread1, TThreadPriority aPriorityThread2) |
|
85 { |
|
86 RTestThread thread1; |
|
87 RTestThread thread2; |
|
88 RTestThread thread3; |
|
89 TRequestStatus logonStatus1; |
|
90 TRequestStatus logonStatus2; |
|
91 TRequestStatus logonStatus3; |
|
92 TRequestStatus rendezvousStatus; |
|
93 |
|
94 threadMutexAcquireOrder = 0; // global variable to hold order in which threads obtain mutex |
|
95 |
|
96 RThread thisThread; |
|
97 thisThread.SetPriority(EPriorityAbsoluteVeryLow); |
|
98 |
|
99 // create the SyncMutex global variable and hold it initially |
|
100 if(SyncMutex.CreateLocal()!=KErrNone) |
|
101 User::Invariant(); |
|
102 SyncMutex.Wait(); |
|
103 |
|
104 thread1.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(1)); |
|
105 thread1.Logon(logonStatus1); |
|
106 thread1.SetPriority(EPriorityAbsoluteHigh); |
|
107 thread1.Rendezvous(rendezvousStatus); |
|
108 thread1.Resume(); |
|
109 User::WaitForRequest(rendezvousStatus); |
|
110 User::After(500000); |
|
111 |
|
112 thread2.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(2)); |
|
113 thread2.Logon(logonStatus2); |
|
114 thread2.SetPriority(EPriorityAbsoluteForeground); |
|
115 thread2.Rendezvous(rendezvousStatus); |
|
116 thread2.Resume(); |
|
117 User::WaitForRequest(rendezvousStatus); |
|
118 User::After(500000); |
|
119 |
|
120 thread3.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(3)); |
|
121 thread3.Logon(logonStatus3); |
|
122 thread3.SetPriority(EPriorityAbsoluteBackground); |
|
123 thread3.Rendezvous(rendezvousStatus); |
|
124 thread3.Resume(); |
|
125 User::WaitForRequest(rendezvousStatus); |
|
126 User::After(500000); |
|
127 |
|
128 thread1.SetPriority(aPriorityThread1); |
|
129 thread2.SetPriority(aPriorityThread2); |
|
130 thread3.SetPriority(aPriorityThread1); |
|
131 |
|
132 SyncMutex.Signal(); |
|
133 |
|
134 User::WaitForRequest(logonStatus1); |
|
135 User::WaitForRequest(logonStatus2); |
|
136 User::WaitForRequest(logonStatus3); |
|
137 test(thread1.ExitType()==EExitKill); |
|
138 test(logonStatus1==KErrNone); |
|
139 test(thread2.ExitType()==EExitKill); |
|
140 test(logonStatus2==KErrNone); |
|
141 test(thread3.ExitType()==EExitKill); |
|
142 test(logonStatus3==KErrNone); |
|
143 |
|
144 thread1.Close(); |
|
145 thread2.Close(); |
|
146 thread3.Close(); |
|
147 SyncMutex.Close(); |
|
148 |
|
149 return threadMutexAcquireOrder; |
|
150 } |
|
151 |
|
152 |
|
153 enum TTestProcessFunctions |
|
154 { |
|
155 ETestProcessThreadPrioritiesEqual, |
|
156 ETestProcessThreadPrioritiesHighLow |
|
157 }; |
|
158 |
|
159 #include "testprocess.h" |
|
160 |
|
161 TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2) |
|
162 { |
|
163 RThread thread; |
|
164 |
|
165 switch(aTestNum) |
|
166 { |
|
167 |
|
168 case ETestProcessThreadPrioritiesEqual: |
|
169 { |
|
170 TInt acquireOrder = TestThreadMutexAcquireOrder((TThreadPriority)aArg1, (TThreadPriority)aArg2); |
|
171 if (acquireOrder != 123) |
|
172 { |
|
173 thread.Panic(KTestPanicCategory,999); |
|
174 } |
|
175 break; |
|
176 } |
|
177 |
|
178 case ETestProcessThreadPrioritiesHighLow: |
|
179 { |
|
180 TInt acquireOrder = TestThreadMutexAcquireOrder((TThreadPriority)aArg1, (TThreadPriority)aArg2); |
|
181 if (acquireOrder != 132) |
|
182 { |
|
183 thread.Panic(KTestPanicCategory,999); |
|
184 } |
|
185 break; |
|
186 } |
|
187 |
|
188 default: |
|
189 User::Panic(_L("T_SPRIORITYCAP"),1); |
|
190 } |
|
191 |
|
192 return KErrNone; |
|
193 } |
|
194 |
|
195 |
|
196 //--------------------------------------------- |
|
197 //! @SYMTestCaseID KBASE-T_SPRIORITYCAP-0121 |
|
198 //! @SYMTestCaseDesc Check prioritisation of threads with ProtServ capability |
|
199 //! @SYMTestType UT |
|
200 //! @SYMREQ PREQ955 |
|
201 //! @SYMTestActions Create sets of three threads with various priorities and have them wait on |
|
202 //! a mutex. Signal the mutex to see whether the threads obtain it in priority or wait order. |
|
203 //! Note: 2 MMP files build test exe with RealTimeServer and WindowServer process priorities. |
|
204 //! Test creates copy of this executable with/without required capabilities. |
|
205 //! @SYMTestExpectedResults All thread priorities are obtainable to processes with ProtServ, so |
|
206 //! confirm they are correctly mapped to absolute priorities, that MuchMore > More etc. and |
|
207 //! that SystemServer/More is correctly mapped for SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES macro. |
|
208 //! @SYMTestPriority Critical |
|
209 //! @SYMTestStatus Implemented |
|
210 //--------------------------------------------- |
|
211 void TestPriorityMappingWithProtServ() |
|
212 { |
|
213 const TUint32 capability = 1u<<ECapabilityProtServ; // only ProtServ capability |
|
214 RTestProcess process; |
|
215 |
|
216 TProcessPriority processPriority = process.Priority(); |
|
217 // only call with the following process priorities |
|
218 ASSERT((processPriority == EPriorityWindowServer) || (processPriority == EPriorityFileServer) |
|
219 || (processPriority == EPrioritySupervisor) || (processPriority == EPriorityRealTimeServer)); |
|
220 |
|
221 test.Start(_L("Test EPriorityRealTime is greater than EPriorityMuchMore")); |
|
222 process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityRealTime,EPriorityMuchMore); |
|
223 process.Run(); |
|
224 |
|
225 test.Next(_L("Test EPriorityMuchMore is greater than EPriorityMore")); |
|
226 process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityMuchMore,EPriorityMore); |
|
227 process.Run(); |
|
228 |
|
229 test.Next(_L("Test EPriorityMore is greater than EPriorityNormal")); |
|
230 process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityMore,EPriorityNormal); |
|
231 process.Run(); |
|
232 |
|
233 test.Next(_L("Test EPriorityNormal is greater than EPriorityLess")); |
|
234 process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityNormal,EPriorityLess); |
|
235 process.Run(); |
|
236 |
|
237 test.Next(_L("Test EPriorityLess is greater than EPriorityMuchLess")); |
|
238 process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityLess,EPriorityMuchLess); |
|
239 process.Run(); |
|
240 |
|
241 test.Next(_L("Test EPriorityMore versus independent capping priority")); |
|
242 process.Create(capability, |
|
243 (processPriority == EPriorityRealTimeServer) ? ETestProcessThreadPrioritiesHighLow : ETestProcessThreadPrioritiesEqual, |
|
244 EPriorityMore, |
|
245 #ifdef SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES |
|
246 EPriorityAbsoluteHigh |
|
247 #else |
|
248 EPriorityAbsoluteRealTime1 |
|
249 #endif |
|
250 ); |
|
251 process.Run(); |
|
252 |
|
253 test.End(); |
|
254 } |
|
255 |
|
256 |
|
257 //--------------------------------------------- |
|
258 //! @SYMTestCaseID KBASE-T_SPRIORITYCAP-0122 |
|
259 //! @SYMTestCaseDesc Check prioritisation of threads without ProtServ capability |
|
260 //! @SYMTestType UT |
|
261 //! @SYMREQ PREQ955 |
|
262 //! @SYMTestActions Create sets of three threads with various priorities and have them wait on |
|
263 //! a mutex. Signal the mutex to see whether the threads obtain it in priority or wait order. |
|
264 //! Note: 2 MMP files build test exe with RealTimeServer and WindowServer process priorities. |
|
265 //! Test creates copy of this executable with/without required capabilities. |
|
266 //! @SYMTestExpectedResults Confirm thread priorities are capped at SystemServer/More without ProtServ, |
|
267 //! so many priority enumerations will map to the same absolute priority. Confirm that |
|
268 //! SystemServer/More is correctly mapped for SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES macro. |
|
269 //! @SYMTestPriority Critical |
|
270 //! @SYMTestStatus Implemented |
|
271 //--------------------------------------------- |
|
272 void TestPriorityMappingWithoutProtServ() |
|
273 { |
|
274 const TUint32 capability = ~(1u<<ECapabilityProtServ); // all capabilities except ProtServ |
|
275 RTestProcess process; |
|
276 |
|
277 TProcessPriority processPriority = process.Priority(); |
|
278 // only call with the following process priorities |
|
279 ASSERT((processPriority == EPriorityWindowServer) || (processPriority == EPriorityFileServer) |
|
280 || (processPriority == EPrioritySupervisor) || (processPriority == EPriorityRealTimeServer)); |
|
281 |
|
282 test.Start(_L("Test EPriorityRealTime and EPriorityMuchMore are capped and equal")); |
|
283 process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityRealTime,EPriorityMuchMore); |
|
284 process.Run(); |
|
285 |
|
286 test.Next(_L("Test EPriorityMuchMore and EPriorityMore are capped and equal")); |
|
287 process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityMuchMore,EPriorityMore); |
|
288 process.Run(); |
|
289 |
|
290 if (processPriority == EPriorityRealTimeServer) |
|
291 { |
|
292 test.Next(_L("Test EPriorityMore and EPriorityMuchLess are capped and equal")); |
|
293 process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityMore,EPriorityMuchLess); |
|
294 process.Run(); |
|
295 |
|
296 test.Next(_L("Test EPriorityNormal and EPriorityMuchLess are capped and equal")); |
|
297 process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityNormal,EPriorityMuchLess); |
|
298 process.Run(); |
|
299 |
|
300 test.Next(_L("Test EPriorityLess and EPriorityMuchLess are capped and equal")); |
|
301 process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityLess,EPriorityMuchLess); |
|
302 process.Run(); |
|
303 } |
|
304 |
|
305 test.Next(_L("Test EPriorityMore versus EPriorityAbsoluteHigh")); |
|
306 process.Create(capability, |
|
307 #ifdef SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES |
|
308 ETestProcessThreadPrioritiesEqual, |
|
309 #else |
|
310 ETestProcessThreadPrioritiesHighLow, |
|
311 #endif |
|
312 EPriorityMore,EPriorityAbsoluteHigh); |
|
313 process.Run(); |
|
314 |
|
315 test.End(); |
|
316 } |
|
317 |
|
318 |
|
319 GLDEF_C TInt E32Main() |
|
320 { |
|
321 TBuf16<512> cmd; |
|
322 User::CommandLine(cmd); |
|
323 if(cmd.Length() && TChar(cmd[0]).IsDigit()) |
|
324 { |
|
325 TInt function = -1; |
|
326 TInt arg1 = -1; |
|
327 TInt arg2 = -1; |
|
328 TLex lex(cmd); |
|
329 |
|
330 lex.Val(function); |
|
331 lex.SkipSpace(); |
|
332 lex.Val(arg1); |
|
333 lex.SkipSpace(); |
|
334 lex.Val(arg2); |
|
335 return DoTestProcess(function,arg1,arg2); |
|
336 } |
|
337 |
|
338 test.Title(); |
|
339 |
|
340 if(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)) |
|
341 { |
|
342 test.Start(_L("TESTS NOT RUN - EPlatSecEnforcement is OFF")); |
|
343 test.End(); |
|
344 return 0; |
|
345 } |
|
346 |
|
347 test.Next(_L("Test thread priority mappings for processes with ECapabilityProtServ")); |
|
348 TestPriorityMappingWithProtServ(); |
|
349 |
|
350 test.Start(_L("Test thread priority mappings for processes without ECapabilityProtServ")); |
|
351 TestPriorityMappingWithoutProtServ(); |
|
352 |
|
353 test.End(); |
|
354 |
|
355 return(0); |
|
356 } |
|
357 |