|
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\mmu\t_wsd_tst.cpp |
|
15 // Test exporting and importing writable static data in DLLs. |
|
16 // This test relies on three dlls: |
|
17 // - t_wsd_dl1_[cx][pu] Which is statically linked, and exports both code & data |
|
18 // - t_wsd_dl2_[cx][pu] Which is dyanamically loaded, and imports code & writable static data from |
|
19 // - t_wsd_dl3_[cx][pu] Which exports code and writable static data |
|
20 // The [cx] suffix indicates code-in-RAM vs XIP (ROM), and [pu] indicate paged or unpaged code. |
|
21 // |
|
22 |
|
23 //! @SYMTestCaseID KBASE-T_CODEPAGING-0335 |
|
24 //! @SYMTestType UT |
|
25 //! @SYMPREQ PREQ1110 |
|
26 //! @SYMTestCaseDesc Demand Paging Code Paging tests. |
|
27 //! @SYMTestActions 001 Code paging tests |
|
28 //! @SYMTestExpectedResults All tests should pass. |
|
29 //! @SYMTestPriority High |
|
30 //! @SYMTestStatus Implemented |
|
31 |
|
32 #define __E32TEST_EXTENSION__ |
|
33 #include <e32test.h> |
|
34 #include <e32math.h> |
|
35 #include <f32file.h> |
|
36 #include <f32dbg.h> |
|
37 |
|
38 #include "mmudetect.h" |
|
39 #include "t_wsd_tst.h" |
|
40 |
|
41 // Global data ///////////////////////////////////////////////////////////////// |
|
42 |
|
43 _LIT(KSearchPathTemplate, "%c:\\sys\\bin"); // drive letter |
|
44 _LIT(KLibraryName, "t_wsd_dl%d_%c%c"); // [23] [cx] [pu] |
|
45 |
|
46 TInt TheFailure = KErrNone; |
|
47 TChar CurrentDrive = 'Z'; |
|
48 |
|
49 void SetCurrentDrive(TChar aDrive) |
|
50 { |
|
51 CurrentDrive = aDrive; |
|
52 } |
|
53 |
|
54 class TPagingDriveInfo |
|
55 { |
|
56 public: |
|
57 TChar iDriveLetter; |
|
58 TDriveInfo iDriveInfo; |
|
59 }; |
|
60 |
|
61 RArray<TPagingDriveInfo> SupportedDrives; |
|
62 |
|
63 // RTest stuff ///////////////////////////////////////////////////////////////// |
|
64 |
|
65 RTest test(_L("T_WSD")); |
|
66 |
|
67 #define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); } |
|
68 #define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); } |
|
69 #define test_equal(e, a) { TInt _e = TInt(e); TInt _a = TInt(a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); } |
|
70 |
|
71 void HandleError(TInt aError, TInt aLine) |
|
72 { |
|
73 test.Printf(_L("Error %d\n"), aError); |
|
74 test.operator()(EFalse, aLine); |
|
75 } |
|
76 |
|
77 void HandleNull(TInt aLine) |
|
78 { |
|
79 test.Printf(_L("Null value\n")); |
|
80 test.operator()(EFalse, aLine); |
|
81 } |
|
82 |
|
83 void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine) |
|
84 { |
|
85 test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual); |
|
86 test.operator()(EFalse, aLine); |
|
87 } |
|
88 |
|
89 // Utility functions /////////////////////////////////////////////////////////// |
|
90 |
|
91 TPtrC16 GetMediaType(TInt aMediaType) |
|
92 { |
|
93 _LIT(KMediaNotPresent, "MediaNotPresent"); |
|
94 _LIT(KMediaUnknown, "MediaUnknown"); |
|
95 _LIT(KMediaFloppy, "MediaFloppy"); |
|
96 _LIT(KMediaHardDisk, "MediaHardDisk"); |
|
97 _LIT(KMediaCdRom, "MediaCdRom"); |
|
98 _LIT(KMediaRam, "MediaRam"); |
|
99 _LIT(KMediaFlash, "MediaFlash"); |
|
100 _LIT(KMediaRom, "MediaRom"); |
|
101 _LIT(KMediaRemote, "MediaRemote"); |
|
102 _LIT(KMediaNANDFlash, "MediaNANDFlash"); |
|
103 _LIT(KMediaUnKnown, "MediaUnKnown"); |
|
104 |
|
105 switch (aMediaType) |
|
106 { |
|
107 case EMediaNotPresent: |
|
108 return KMediaNotPresent(); |
|
109 case EMediaUnknown: |
|
110 return KMediaUnknown(); |
|
111 case EMediaFloppy: |
|
112 return KMediaFloppy(); |
|
113 case EMediaHardDisk: |
|
114 return KMediaHardDisk(); |
|
115 case EMediaCdRom: |
|
116 return KMediaCdRom(); |
|
117 case EMediaRam: |
|
118 return KMediaRam(); |
|
119 case EMediaFlash: |
|
120 return KMediaFlash(); |
|
121 case EMediaRom: |
|
122 return KMediaRom(); |
|
123 case EMediaRemote: |
|
124 return KMediaRemote(); |
|
125 case EMediaNANDFlash: |
|
126 return KMediaNANDFlash(); |
|
127 default: |
|
128 return KMediaUnKnown(); |
|
129 } |
|
130 } |
|
131 |
|
132 // Get the list of testable drives |
|
133 void GetSupportedDrives(TBool aVerbose = EFalse) |
|
134 { |
|
135 TUint32 memModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL); |
|
136 TBool codePagingSupported = (memModelAttributes & EMemModelAttrCodePaging) != 0; |
|
137 TUint32 pagingPolicy = E32Loader::PagingPolicy(); |
|
138 TBool pagingPolicyAllowsPaging = pagingPolicy != EKernelConfigCodePagingPolicyNoPaging; |
|
139 test_Equal(codePagingSupported, pagingPolicyAllowsPaging); |
|
140 if (codePagingSupported) |
|
141 test.Printf(_L("Code paging is enabled.\n")); |
|
142 else |
|
143 test.Printf(_L("Code paging is NOT enabled.\n")); |
|
144 |
|
145 if (aVerbose) |
|
146 { |
|
147 test.Printf(_L("Available drives:\n")); |
|
148 test.Printf(_L(" Type Attr MedAttr Filesystem\n")); |
|
149 } |
|
150 |
|
151 RFs fs; |
|
152 test_noError(fs.Connect()); |
|
153 |
|
154 TDriveList driveList; |
|
155 TInt r = fs.DriveList(driveList); |
|
156 test_noError(r); |
|
157 |
|
158 TBool NandPageableMediaFound = EFalse; |
|
159 for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum) |
|
160 { |
|
161 if (!driveList[drvNum]) |
|
162 continue; //-- skip unexisting drive |
|
163 |
|
164 TDriveInfo driveInfo; |
|
165 r = fs.Drive(driveInfo, drvNum); |
|
166 test_noError(r); |
|
167 |
|
168 TChar ch; |
|
169 r = fs.DriveToChar(drvNum, ch); |
|
170 test_noError(r); |
|
171 |
|
172 TBuf<256> fileSystemName; |
|
173 r = fs.FileSystemName(fileSystemName, drvNum); |
|
174 test_noError(r); |
|
175 |
|
176 // Decide which drives to exclude: |
|
177 // Locked/nonwritable drives, except the Z: ROM drive |
|
178 // Win32 drives on the emulator |
|
179 // Remote/nonlocal, removable/noninternal, redirected, substed drives |
|
180 // All others are included by default iff code paging is supported |
|
181 // If not, only the Z: ROM/XIP drive is tested |
|
182 _LIT(KWin32FS, "Win32"); |
|
183 TBool include = codePagingSupported; |
|
184 if (driveInfo.iDriveAtt & KDriveAttRom) |
|
185 include = (ch == 'Z'); |
|
186 else if (driveInfo.iMediaAtt & (KMediaAttWriteProtected|KMediaAttLocked)) |
|
187 include = EFalse; |
|
188 else if (fileSystemName == KWin32FS()) |
|
189 include = EFalse; |
|
190 else if (driveInfo.iDriveAtt & (KDriveAttRedirected|KDriveAttSubsted|KDriveAttRemovable|KDriveAttRemote)) |
|
191 include = EFalse; |
|
192 else if ((KDriveAttInternal|KDriveAttLocal) & ~driveInfo.iDriveAtt) |
|
193 include = EFalse; |
|
194 |
|
195 if (include) |
|
196 { |
|
197 TPagingDriveInfo pagingDriveInfo; |
|
198 pagingDriveInfo.iDriveLetter = ch; |
|
199 pagingDriveInfo.iDriveInfo = driveInfo; |
|
200 r = SupportedDrives.Append(pagingDriveInfo); |
|
201 test_noError(r); |
|
202 } |
|
203 |
|
204 TBool pageable = EFalse; |
|
205 if (driveInfo.iDriveAtt & KDriveAttPageable) |
|
206 { |
|
207 pageable = ETrue; |
|
208 if (driveInfo.iType == EMediaNANDFlash) |
|
209 NandPageableMediaFound = ETrue; |
|
210 } |
|
211 |
|
212 // If we've already found a pageable NAND drive, then assume the |
|
213 // Z: drive is pageable too if it's got a composite file system |
|
214 _LIT(KCompositeName,"Composite"); |
|
215 if (NandPageableMediaFound && fileSystemName == KCompositeName()) |
|
216 pageable = ETrue; |
|
217 |
|
218 if (aVerbose) |
|
219 { |
|
220 TPtrC16 mediaType = GetMediaType(driveInfo.iType); |
|
221 _LIT(KPageable, "pageable"); |
|
222 test.Printf(_L("%c %c: %16S %08x %08x %10S %S\n"), |
|
223 include ? '*' : ' ', (TUint)ch, &mediaType, |
|
224 driveInfo.iDriveAtt, driveInfo.iMediaAtt, |
|
225 &fileSystemName, (pageable ? &KPageable : &KNullDesC)); |
|
226 } |
|
227 } |
|
228 |
|
229 fs.Close(); |
|
230 } |
|
231 |
|
232 const TDesC& LibrarySearchPath(TChar aDrive) |
|
233 { |
|
234 static TBuf<64> path; |
|
235 path.Format(KSearchPathTemplate, (TUint)aDrive); |
|
236 return path; |
|
237 } |
|
238 |
|
239 const TDesC& LibraryName(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged) |
|
240 { |
|
241 // this gives DLL#2 a different name on each drive so we can be sure we're loading the right one |
|
242 static TBuf<64> name; |
|
243 name.Format(KLibraryName, aLibNo, aRam ? 'c' : 'x', aPaged ? 'p' : 'u'); |
|
244 if (aLibNo == 2 && aDrive != 'Z') |
|
245 name.AppendFormat(_L("_%c"), (TUint)aDrive); |
|
246 return name; |
|
247 } |
|
248 |
|
249 const TDesC& LibraryFilename(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged) |
|
250 { |
|
251 static TBuf<64> filename; |
|
252 filename = LibrarySearchPath(aDrive); |
|
253 filename.AppendFormat(_L("\\%S.dll"), &LibraryName(aDrive, aLibNo, aRam, aPaged)); |
|
254 return filename; |
|
255 } |
|
256 |
|
257 TInt LoadSpecificLibrary(RLibrary& aLibrary, TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged) |
|
258 { |
|
259 const TDesC& path = LibrarySearchPath(aDrive); |
|
260 const TDesC& name = LibraryName(aDrive, aLibNo, aRam, aPaged); |
|
261 TInt err = aLibrary.Load(name, path); |
|
262 TBuf<256> message; |
|
263 message.Format(_L("Loading %S\\%S.dll returns %d\n"), &path, &name, err); |
|
264 test.Printf(message); |
|
265 return err; |
|
266 } |
|
267 |
|
268 // Test functions ////////////////////////////////////////////////////////////// |
|
269 |
|
270 void CopyDllToCurrentDrive(RFs& aFs, TBool aPaged, TInt aLibNo) |
|
271 { |
|
272 TBuf<64> source = LibraryFilename('Z', aLibNo, ETrue, aPaged); |
|
273 TBuf<64> dest = LibraryFilename(CurrentDrive, aLibNo, ETrue, aPaged); |
|
274 test.Printf(_L("Copying %S to %S\n"), &source, &dest); |
|
275 |
|
276 TInt r = aFs.MkDirAll(dest); |
|
277 test(r == KErrNone || r == KErrAlreadyExists); |
|
278 |
|
279 TBuf<64> tempName(dest); |
|
280 tempName.Append(_L(".tmp")); |
|
281 |
|
282 RFile in, out, temp; |
|
283 test_noError(in.Open(aFs, source, EFileRead)); |
|
284 test_noError(out.Replace(aFs, dest, EFileWrite)); |
|
285 test_noError(temp.Replace(aFs, tempName, EFileWrite)); |
|
286 |
|
287 const TInt KBufferSize = 3333; |
|
288 TBuf8<KBufferSize> buffer; |
|
289 |
|
290 test_noError(temp.Write(buffer)); |
|
291 test_noError(temp.Flush()); |
|
292 |
|
293 TInt size; |
|
294 test_noError(in.Size(size)); |
|
295 TInt pos = 0; |
|
296 while (pos < size) |
|
297 { |
|
298 test_noError(in.Read(buffer)); |
|
299 test_noError(out.Write(buffer)); |
|
300 test_noError(out.Flush()); |
|
301 test_noError(temp.Write(buffer)); |
|
302 test_noError(temp.Flush()); |
|
303 pos += buffer.Length(); |
|
304 } |
|
305 |
|
306 out.SetAtt(KEntryAttNormal, KEntryAttReadOnly| |
|
307 KEntryAttHidden| |
|
308 KEntryAttSystem| |
|
309 KEntryAttArchive| |
|
310 KEntryAttXIP); |
|
311 |
|
312 in.Close(); |
|
313 out.Close(); |
|
314 temp.Close(); |
|
315 } |
|
316 |
|
317 void CopyDllsToCurrentDrive() |
|
318 { |
|
319 RFs fs; |
|
320 test_noError(fs.Connect()); |
|
321 |
|
322 CopyDllToCurrentDrive(fs, EFalse, 2); // Unpaged library 2 |
|
323 CopyDllToCurrentDrive(fs, EFalse, 3); // Unpaged library 3 |
|
324 CopyDllToCurrentDrive(fs, ETrue, 2); // Paged library 2 |
|
325 CopyDllToCurrentDrive(fs, ETrue, 3); // Paged library 3 |
|
326 |
|
327 fs.Close(); |
|
328 } |
|
329 |
|
330 void EraseDllsFromCurrentDrive() |
|
331 { |
|
332 RFs fs; |
|
333 test_noError(fs.Connect()); |
|
334 |
|
335 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
336 test_notNull(cleanup); |
|
337 |
|
338 CFileMan* fileMan = NULL; |
|
339 TRAPD(r, fileMan = CFileMan::NewL(fs)); |
|
340 test_noError(r); |
|
341 |
|
342 TBuf<64> libdir = LibrarySearchPath(CurrentDrive); |
|
343 test.Printf(_L("Erasing %S\n"), &libdir); |
|
344 fileMan->RmDir(libdir); |
|
345 |
|
346 delete fileMan; |
|
347 delete cleanup; |
|
348 fs.Close(); |
|
349 } |
|
350 |
|
351 void CheckRelocatableData(RLibrary& library) |
|
352 { |
|
353 TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal); |
|
354 test_notNull(func); |
|
355 |
|
356 TInt size; |
|
357 void* codeAddr; |
|
358 void* dataAddr; |
|
359 void*** dataPtrPtr = (void***)func(size, codeAddr, dataAddr); |
|
360 void **dp = (void **)dataAddr; |
|
361 |
|
362 for (TInt i = 0; i < size/4; i += 2) |
|
363 { |
|
364 test_equal(dp[i], codeAddr); |
|
365 test_equal(dp[i+1], dataAddr); |
|
366 } |
|
367 |
|
368 test_equal(*dataPtrPtr, dp); |
|
369 } |
|
370 |
|
371 void CheckWritableStaticData(RLibrary& library) |
|
372 { |
|
373 TInt (*func)(void) = (TInt (*)(void))library.Lookup(KCheckWritableStaticDataFunctionOrdinal); |
|
374 RDebug::Printf("CheckWritableStaticData() is export %d at %08x", KCheckWritableStaticDataFunctionOrdinal, func); |
|
375 test_notNull(func); |
|
376 TInt err = func(); |
|
377 RDebug::Printf("CheckWritableStaticData() returned %d", err); |
|
378 // test_noError(err); |
|
379 if (TheFailure == KErrNone) |
|
380 TheFailure = err; |
|
381 } |
|
382 |
|
383 void RunPerDriveTests(TBool aPaged, TBool aRam) |
|
384 { |
|
385 TBuf<64> message = _L("Running "); |
|
386 if (!aPaged) |
|
387 message.Append(_L("un")); |
|
388 message.AppendFormat(_L("paged R%cM tests on drive %c:"), |
|
389 aRam ? 'A' : 'O', (TUint)CurrentDrive); |
|
390 test.Next(message); |
|
391 |
|
392 RFs fs; |
|
393 test_noError(fs.Connect()); |
|
394 fs.SetDebugRegister(KFLDR); |
|
395 |
|
396 // Explicitly loading dl2 will implicitly load dl3 as well |
|
397 RLibrary dl2; |
|
398 test_noError(LoadSpecificLibrary(dl2, CurrentDrive, 2, aRam, aPaged)); |
|
399 CheckRelocatableData(dl2); |
|
400 CheckWritableStaticData(dl2); |
|
401 dl2.Close(); |
|
402 |
|
403 fs.SetDebugRegister(0); |
|
404 fs.Close(); |
|
405 } |
|
406 |
|
407 TInt E32Main() |
|
408 { |
|
409 test.Title(); |
|
410 test.Start(_L("WSD tests")); |
|
411 |
|
412 // Check static linkage to dl1 |
|
413 test_noError(CheckExportedDataAddress(&ExportedData)); |
|
414 |
|
415 GetSupportedDrives(ETrue); |
|
416 test(SupportedDrives.Count() > 0); |
|
417 |
|
418 // Turn off evil lazy dll unloading |
|
419 RLoader l; |
|
420 test(l.Connect()==KErrNone); |
|
421 test(l.CancelLazyDllUnload()==KErrNone); |
|
422 l.Close(); |
|
423 |
|
424 // Make sure there aren't any DLLs left over from earlier tests |
|
425 TInt i = SupportedDrives.Count(); |
|
426 while (--i >= 0) |
|
427 { |
|
428 SetCurrentDrive(SupportedDrives[i].iDriveLetter); |
|
429 if (CurrentDrive != 'Z') |
|
430 EraseDllsFromCurrentDrive(); |
|
431 } |
|
432 |
|
433 // We want to test all supported drives in order of increasing priority, so |
|
434 // that the CurrentDrive is always the hghest priority of those tested so far. |
|
435 // Therefore, if Z (XIP ROM, lowest priority) is a valid test drive, do it first |
|
436 i = SupportedDrives.Count(); |
|
437 if (--i >= 0) |
|
438 { |
|
439 SetCurrentDrive(SupportedDrives[i].iDriveLetter); |
|
440 if (CurrentDrive == 'Z') |
|
441 { |
|
442 // ROM (XIP) tests can only be run from Z: |
|
443 RunPerDriveTests(EFalse, EFalse); // Unpaged ROM |
|
444 RunPerDriveTests(ETrue, EFalse); // Paged ROM |
|
445 RunPerDriveTests(EFalse, ETrue); // Unpaged RAM |
|
446 RunPerDriveTests(ETrue, ETrue); // Paged RAM |
|
447 } |
|
448 } |
|
449 |
|
450 // Now run the RAM-based versions from each remaining drive in turn |
|
451 for (i = 0; i < SupportedDrives.Count(); ++i) |
|
452 { |
|
453 SetCurrentDrive(SupportedDrives[i].iDriveLetter); |
|
454 if (CurrentDrive != 'Z') |
|
455 { |
|
456 CopyDllsToCurrentDrive(); |
|
457 RunPerDriveTests(EFalse, ETrue); // Unpaged RAM |
|
458 RunPerDriveTests(ETrue, ETrue); // Paged RAM |
|
459 } |
|
460 } |
|
461 |
|
462 test_noError(TheFailure); |
|
463 test.End(); |
|
464 return 0; |
|
465 } |
|
466 |