|
1 // Copyright (c) 1995-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\mmu\t_chunk4.cpp |
|
15 // Overview: |
|
16 // Test disconnected chunks |
|
17 // API Information: |
|
18 // RChunk, CBase |
|
19 // Details: |
|
20 // - Check Allocate/Commit/Decommit methods on local disconnected chunk and write/read |
|
21 // access to both committed and uncommitted regions. |
|
22 // - Check IPC that involves local disconnected chunk and verify results are as expected. |
|
23 // Platforms/Drives/Compatibility: |
|
24 // All. |
|
25 // Assumptions/Requirement/Pre-requisites: |
|
26 // Failures and causes: |
|
27 // Base Port information: |
|
28 // |
|
29 // |
|
30 |
|
31 #define __E32TEST_EXTENSION__ |
|
32 #include <e32test.h> |
|
33 #include "u32std.h" |
|
34 #include "mmudetect.h" |
|
35 #include "../misc/prbs.h" |
|
36 #include "d_memorytest.h" |
|
37 #include "freeram.h" |
|
38 |
|
39 RTest test(_L("T_CHUNK4")); |
|
40 |
|
41 RMemoryTestLdd TestLdd; |
|
42 |
|
43 TUint RndSeed[2]; |
|
44 |
|
45 class CChunk : public CBase |
|
46 { |
|
47 public: |
|
48 static CChunk* New(TInt aMaxSize); |
|
49 public: |
|
50 virtual ~CChunk(); |
|
51 TInt Verify(); |
|
52 TInt Commit(TInt anOffset, TInt aSize); |
|
53 TInt Allocate(TInt aSize); |
|
54 TInt Decommit(TInt anOffset, TInt aSize); |
|
55 void CheckL(volatile TUint* aPtr); |
|
56 TInt AddPages(TInt anOffset, TInt aSize); |
|
57 TInt RemovePages(TInt anOffset, TInt aSize); |
|
58 public: |
|
59 RChunk iChunk; |
|
60 TUint8* iPageInfo; |
|
61 TInt iPageSize; |
|
62 TInt iMaxSize; |
|
63 TInt iNumPages; |
|
64 }; |
|
65 |
|
66 CChunk* CChunk::New(TInt aMaxSize) |
|
67 { |
|
68 CChunk* pC=new CChunk; |
|
69 if (pC) |
|
70 { |
|
71 TInt p; |
|
72 UserHal::PageSizeInBytes(p); |
|
73 pC->iPageSize=p; |
|
74 pC->iMaxSize=aMaxSize; |
|
75 TInt n=aMaxSize/p; |
|
76 pC->iNumPages=n; |
|
77 TInt r=pC->iChunk.CreateDisconnectedLocal(0,0,aMaxSize); |
|
78 if (r==KErrNone) |
|
79 { |
|
80 TUint8* pI=(TUint8*)User::Alloc(n); |
|
81 if (pI) |
|
82 { |
|
83 pC->iPageInfo=pI; |
|
84 Mem::FillZ(pI,n); |
|
85 } |
|
86 else |
|
87 r=KErrNoMemory; |
|
88 } |
|
89 if (r!=KErrNone) |
|
90 { |
|
91 delete pC; |
|
92 pC=NULL; |
|
93 } |
|
94 } |
|
95 return pC; |
|
96 } |
|
97 |
|
98 CChunk::~CChunk() |
|
99 { |
|
100 delete iPageInfo; |
|
101 iChunk.Close(); |
|
102 } |
|
103 |
|
104 void CChunk::CheckL(volatile TUint* aPtr) |
|
105 { |
|
106 TUint x=*aPtr; |
|
107 *aPtr=x; |
|
108 } |
|
109 |
|
110 TInt CChunk::Verify() |
|
111 { |
|
112 // test.Getch(); |
|
113 TInt i; |
|
114 TUint8* base=iChunk.Base(); |
|
115 for (i=0; i<iNumPages; i++) |
|
116 { |
|
117 volatile TUint* pX=(volatile TUint*)base; |
|
118 TInt r=TestLdd.ReadWriteMemory((TAny*)pX); |
|
119 TUint8 info=iPageInfo[i]; |
|
120 if (info==0 && r==KErrNone) |
|
121 return KErrGeneral; |
|
122 if (info!=0 && r!=KErrNone) |
|
123 return KErrAccessDenied; |
|
124 if (info!=0) |
|
125 { |
|
126 TUint seed[2]; |
|
127 seed[0]=info<<8; |
|
128 seed[1]=0; |
|
129 TInt j; |
|
130 for (j=0; j<iPageSize; j+=4) |
|
131 { |
|
132 if (*pX++!=Random(seed)) |
|
133 return KErrArgument; |
|
134 } |
|
135 } |
|
136 base+=iPageSize; |
|
137 } |
|
138 return KErrNone; |
|
139 } |
|
140 |
|
141 TInt CChunk::AddPages(TInt anOffset, TInt aSize) |
|
142 { |
|
143 TInt i=anOffset/iPageSize; |
|
144 TInt n=aSize/iPageSize; |
|
145 TInt e=i+n; |
|
146 TUint* p=(TUint*)(iChunk.Base()+anOffset); |
|
147 for (; i<e; i++) |
|
148 { |
|
149 TUint8 s=(TUint8)Random(RndSeed); |
|
150 if (s==0) |
|
151 s=1; |
|
152 iPageInfo[i]=s; |
|
153 TUint seed[2]; |
|
154 seed[0]=s<<8; |
|
155 seed[1]=0; |
|
156 TInt j; |
|
157 for (j=0; j<iPageSize; j+=4) |
|
158 { |
|
159 *p++=Random(seed); |
|
160 } |
|
161 } |
|
162 return KErrNone; |
|
163 } |
|
164 |
|
165 TInt CChunk::RemovePages(TInt anOffset, TInt aSize) |
|
166 { |
|
167 TInt i=anOffset/iPageSize; |
|
168 TInt n=aSize/iPageSize; |
|
169 TInt e=i+n; |
|
170 for (; i<e; i++) |
|
171 iPageInfo[i]=0; |
|
172 return KErrNone; |
|
173 } |
|
174 |
|
175 TInt CChunk::Commit(TInt anOffset, TInt aSize) |
|
176 { |
|
177 TInt r=iChunk.Commit(anOffset,aSize); |
|
178 if (r==KErrNone) |
|
179 { |
|
180 AddPages(anOffset,aSize); |
|
181 } |
|
182 return r; |
|
183 } |
|
184 |
|
185 TInt CChunk::Allocate(TInt aSize) |
|
186 { |
|
187 TInt r=iChunk.Allocate(aSize); |
|
188 if (r>=0) |
|
189 { |
|
190 AddPages(r,aSize); |
|
191 } |
|
192 return r; |
|
193 } |
|
194 |
|
195 TInt CChunk::Decommit(TInt anOffset, TInt aSize) |
|
196 { |
|
197 TInt r=iChunk.Decommit(anOffset,aSize); |
|
198 if (r==KErrNone) |
|
199 { |
|
200 RemovePages(anOffset,aSize); |
|
201 } |
|
202 return r; |
|
203 } |
|
204 |
|
205 // Stuff to test remote writes |
|
206 _LIT(KServerName, "Chunk4Test"); |
|
207 |
|
208 class CTestSession : public CSession2 |
|
209 { |
|
210 public: |
|
211 CTestSession(); |
|
212 virtual void ServiceL(const RMessage2& aMessage); |
|
213 }; |
|
214 |
|
215 class CTestServer : public CServer2 |
|
216 { |
|
217 public: |
|
218 CTestServer(); |
|
219 virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; |
|
220 }; |
|
221 |
|
222 class RTestSession : public RSessionBase |
|
223 { |
|
224 public: |
|
225 enum {ETestIpc, ETestStop}; |
|
226 TInt Connect(); |
|
227 void Stop(); |
|
228 TInt TestRemoteWrite(TInt aLength, TInt anOffset1, TInt anOffset2, TInt anOffset3, TInt anOffset4); |
|
229 TInt IpcWrite(TDes8* aRemoteDest, const TAny* aLocalSrc, TInt aOffset); |
|
230 }; |
|
231 |
|
232 CTestSession::CTestSession() |
|
233 { |
|
234 } |
|
235 |
|
236 void CTestSession::ServiceL(const RMessage2& aMessage) |
|
237 { |
|
238 switch (aMessage.Function()) |
|
239 { |
|
240 case RTestSession::ETestIpc: |
|
241 { |
|
242 const TDesC8& localSrc = *(const TDesC8*)aMessage.Ptr1(); |
|
243 TInt offset = aMessage.Int2(); |
|
244 TInt r = aMessage.Write(0, localSrc, offset); |
|
245 aMessage.Complete(r); |
|
246 break; |
|
247 } |
|
248 case RTestSession::ETestStop: |
|
249 CActiveScheduler::Stop(); |
|
250 break; |
|
251 default: |
|
252 User::Invariant(); |
|
253 } |
|
254 } |
|
255 |
|
256 CTestServer::CTestServer() |
|
257 : CServer2(0) |
|
258 { |
|
259 } |
|
260 |
|
261 CSession2* CTestServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const |
|
262 { |
|
263 return new (ELeave) CTestSession; |
|
264 } |
|
265 |
|
266 TInt ServerThread(TAny*) |
|
267 { |
|
268 CActiveScheduler* pA = new CActiveScheduler; |
|
269 CTestServer* pS = new CTestServer; |
|
270 if (!pA || !pS) |
|
271 return KErrNoMemory; |
|
272 CActiveScheduler::Install(pA); |
|
273 TInt r = pS->Start(KServerName); |
|
274 if (r!=KErrNone) |
|
275 return r; |
|
276 RThread::Rendezvous(KErrNone); |
|
277 CActiveScheduler::Start(); |
|
278 return KErrNone; |
|
279 } |
|
280 |
|
281 TInt RTestSession::Connect() |
|
282 { |
|
283 RThread t; |
|
284 TInt r = t.Create(KServerName, ServerThread, 0x1000, 0x1000, 0x10000, NULL); |
|
285 test(r==KErrNone); |
|
286 t.SetPriority(EPriorityMore); |
|
287 TRequestStatus s; |
|
288 t.Rendezvous(s); |
|
289 test(s==KRequestPending); |
|
290 t.Resume(); |
|
291 User::WaitForRequest(s); |
|
292 test(t.ExitType()==EExitPending); |
|
293 test(s==KErrNone); |
|
294 t.Close(); |
|
295 r = CreateSession(KServerName, TVersion()); |
|
296 return r; |
|
297 } |
|
298 |
|
299 void RTestSession::Stop() |
|
300 { |
|
301 TInt r = SendReceive(ETestStop); |
|
302 test(r==KErrServerTerminated); |
|
303 Close(); |
|
304 } |
|
305 |
|
306 TInt RTestSession::IpcWrite(TDes8* aRemoteDest, const TAny* aLocalSrc, TInt aOffset) |
|
307 { |
|
308 return SendReceive(ETestIpc, TIpcArgs(aRemoteDest, aLocalSrc, aOffset)); |
|
309 } |
|
310 |
|
311 TInt RTestSession::TestRemoteWrite(TInt aLength, TInt anOffset1, TInt anOffset2, TInt anOffset3, TInt anOffset4) |
|
312 { |
|
313 test.Printf(_L("%x %x %x %x %x\n"),aLength,anOffset1,anOffset2,anOffset3,anOffset4); |
|
314 |
|
315 TBool ptr=(anOffset1>=0); |
|
316 TDes8* pDes; |
|
317 TUint8* pData; |
|
318 RChunk c; |
|
319 TInt r=c.CreateDisconnectedLocal(0,0,0x800000); |
|
320 test(r==KErrNone); |
|
321 TUint8* base=c.Base(); |
|
322 if (ptr) |
|
323 { |
|
324 r=c.Commit(anOffset1,(TInt)sizeof(TPtr8)); |
|
325 test(r==KErrNone); |
|
326 pDes=(TDes8*)(base+anOffset1); |
|
327 Mem::FillZ(pDes,(TInt)sizeof(TPtr8)); |
|
328 r=c.Commit(anOffset2,aLength); |
|
329 test(r==KErrNone); |
|
330 pData=base+anOffset2; |
|
331 Mem::FillZ(pData,aLength); |
|
332 new(pDes) TPtr8(pData,0,aLength); |
|
333 test(pDes->Length()==0); |
|
334 test(pDes->MaxLength()==aLength); |
|
335 test(pDes->Ptr()==pData); |
|
336 } |
|
337 else |
|
338 { |
|
339 TInt len=(TInt)sizeof(TDes8)+aLength; |
|
340 r=c.Commit(anOffset2,len); |
|
341 test(r==KErrNone); |
|
342 pDes=(TDes8*)(base+anOffset2); |
|
343 Mem::FillZ(pDes,len); |
|
344 pData=base+anOffset2+(TInt)sizeof(TDes8); |
|
345 new(pDes) TBuf8<1>; |
|
346 ((TInt*)pDes)[1]=aLength; |
|
347 test(pDes->Length()==0); |
|
348 test(pDes->MaxLength()==aLength); |
|
349 test(pDes->Ptr()==pData); |
|
350 } |
|
351 TInt slen=aLength-anOffset3; |
|
352 TUint8* pS=(TUint8*)User::Alloc(aLength); |
|
353 test(pS!=NULL); |
|
354 Mem::FillZ(pS,aLength); |
|
355 TPtrC8 src(pS+anOffset3,slen); |
|
356 TInt i; |
|
357 for (i=anOffset3; i<aLength; i++) |
|
358 pS[i]=(TUint8)Random(RndSeed); |
|
359 if (anOffset4>=0) |
|
360 c.Decommit(anOffset4,0x1000); |
|
361 r = IpcWrite(pDes, &src, anOffset3); |
|
362 if (r==KErrNone) |
|
363 { |
|
364 TPtrC8 tsrc(pS,aLength); |
|
365 if (*pDes!=tsrc) |
|
366 r=KErrCorrupt; |
|
367 } |
|
368 User::Free(pS); |
|
369 c.Close(); |
|
370 test.Printf(_L("Return value %d\n"),r); |
|
371 return r; |
|
372 } |
|
373 |
|
374 GLDEF_C TInt E32Main() |
|
375 { |
|
376 RndSeed[0]=0xddb3d743; |
|
377 RndSeed[1]=0; |
|
378 |
|
379 test.Title(); |
|
380 if (!HaveVirtMem()) |
|
381 { |
|
382 test.Printf(_L("This test requires an MMU\n")); |
|
383 return KErrNone; |
|
384 } |
|
385 test.Start(_L("Testing Disconnected Chunks")); |
|
386 |
|
387 test.Printf(_L("Load test LDD\n")); |
|
388 test(TestLdd.Open()==KErrNone); |
|
389 |
|
390 CChunk* pC=CChunk::New(0x800000); |
|
391 test(pC!=NULL); |
|
392 TInt free=FreeRam(); |
|
393 test.Printf(_L("Free RAM %08x\n"),free); |
|
394 test(pC->Verify()==KErrNone); |
|
395 test.Printf(_L("Commit 0+0x1000\n")); |
|
396 test(pC->Commit(0,0x1000)==KErrNone); |
|
397 test(pC->Verify()==KErrNone); |
|
398 test.Printf(_L("Commit 0+0x1000 (again)\n")); |
|
399 test(pC->Commit(0,0x1000)==KErrAlreadyExists); |
|
400 test(pC->Verify()==KErrNone); |
|
401 test.Printf(_L("Commit 0x3000+0x1000\n")); |
|
402 test(pC->Commit(0x3000,0x1000)==KErrNone); |
|
403 test(pC->Verify()==KErrNone); |
|
404 test.Printf(_L("Commit 0x2000+0x3000 (overlaps previous)\n")); |
|
405 test(pC->Commit(0x2000,0x3000)==KErrAlreadyExists); |
|
406 test(pC->Verify()==KErrNone); |
|
407 test.Printf(_L("Allocate 0x5000\n")); |
|
408 test(pC->Allocate(0x5000)==0x4000); |
|
409 test(pC->Verify()==KErrNone); |
|
410 test.Printf(_L("Allocate 0x1000\n")); |
|
411 test(pC->Allocate(0x1000)==0x1000); |
|
412 test(pC->Verify()==KErrNone); |
|
413 test.Printf(_L("Decommit 0+0x4000\n")); |
|
414 test(pC->Decommit(0,0x4000)==KErrNone); |
|
415 test(pC->Verify()==KErrNone); |
|
416 test.Printf(_L("Decommit 0+0x4000 (again)\n")); |
|
417 test(pC->Decommit(0,0x4000)==KErrNone); |
|
418 test(pC->Verify()==KErrNone); |
|
419 test.Printf(_L("Allocate 0x4000\n")); |
|
420 test(pC->Allocate(0x4000)==0x0000); |
|
421 test(pC->Verify()==KErrNone); |
|
422 test.Printf(_L("Decommit 0+0x10000\n")); |
|
423 test(pC->Decommit(0,0x10000)==KErrNone); |
|
424 test(pC->Verify()==KErrNone); |
|
425 test.Printf(_L("Check Free RAM\n")); |
|
426 test(FreeRam()==free); |
|
427 |
|
428 test.Printf(_L("Commit 0x700000+0x10000\n")); |
|
429 test(pC->Commit(0x700000,0x10000)==KErrNone); |
|
430 test(pC->Verify()==KErrNone); |
|
431 test.Printf(_L("Allocate 0x4000\n")); |
|
432 test(pC->Allocate(0x4000)==0x0000); |
|
433 test(pC->Verify()==KErrNone); |
|
434 test.Printf(_L("Decommit 0+0x800000\n")); |
|
435 test(pC->Decommit(0,0x800000)==KErrNone); |
|
436 test(pC->Verify()==KErrNone); |
|
437 test.Printf(_L("Check Free RAM\n")); |
|
438 test(FreeRam()==free); |
|
439 |
|
440 delete pC; |
|
441 |
|
442 // Test decommiting from a chunk which has no memory commited |
|
443 // in the first megabyte. On the moving memory model, such |
|
444 // chunks have a non-zero iHomeRegionOffset value and has been |
|
445 // the cause of defects (DEF121857) |
|
446 test.Printf(_L("Create new chunk\n")); |
|
447 pC=CChunk::New(0x800000); |
|
448 test(pC!=NULL); |
|
449 test.Printf(_L("Commit 0x100000+0x3000\n")); |
|
450 test(pC->Commit(0x100000,0x3000)==KErrNone); |
|
451 test(pC->Verify()==KErrNone); |
|
452 test.Printf(_L("Decommit 0+0x101000\n")); |
|
453 test(pC->Decommit(0,0x101000)==KErrNone); |
|
454 test(pC->Verify()==KErrNone); |
|
455 test.Printf(_L("Decommit 0x101000+0x1000\n")); |
|
456 test(pC->Decommit(0x101000,0x1000)==KErrNone); |
|
457 test(pC->Verify()==KErrNone); |
|
458 test.Printf(_L("Decommit 0x100000+0x100000\n")); |
|
459 test(pC->Decommit(0x100000,0x100000)==KErrNone); |
|
460 test(pC->Verify()==KErrNone); |
|
461 delete pC; |
|
462 |
|
463 test.Next(_L("Testing RThread::Write to disconnected chunks")); |
|
464 RTestSession ts; |
|
465 TInt r = ts.Connect(); |
|
466 test(r==KErrNone); |
|
467 test(ts.TestRemoteWrite(64,0,0x3000,0,-1)==KErrNone); |
|
468 test(ts.TestRemoteWrite(64,0xffc,0x8000,0,-1)==KErrNone); |
|
469 test(ts.TestRemoteWrite(256,0xffc,0x7f80,0,-1)==KErrNone); |
|
470 test(ts.TestRemoteWrite(256,0xffc,0x7f80,128,-1)==KErrNone); |
|
471 test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0,-1)==KErrNone); |
|
472 test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0x2000,-1)==KErrNone); |
|
473 test(ts.TestRemoteWrite(64,-1,0x3000,0,-1)==KErrNone); |
|
474 test(ts.TestRemoteWrite(0x10000,-1,0xfff00,0x2000,-1)==KErrNone); |
|
475 test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0)==KErrBadDescriptor); |
|
476 test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x1000)==KErrBadDescriptor); |
|
477 test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x7000)==KErrBadDescriptor); |
|
478 test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x8000)==KErrBadDescriptor); |
|
479 test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0x2000,0x710000)==KErrBadDescriptor); |
|
480 test(ts.TestRemoteWrite(0x10000,-1,0xfff00,0x1000,0x100000)==KErrBadDescriptor); |
|
481 ts.Stop(); |
|
482 |
|
483 test.End(); |
|
484 return 0; |
|
485 } |