|
1 // Copyright (c) 2002-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 // f32test\server\t_csfsoakfn.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <f32file.h> |
|
19 #include <e32test.h> |
|
20 #include <e32math.h> |
|
21 #include <f32dbg.h> |
|
22 #include "t_server.h" |
|
23 #include "t_tdebug.h" |
|
24 #include "t_cfssoak.h" |
|
25 |
|
26 /// Time value constants |
|
27 LOCAL_D const TInt KSecond = 1000000; |
|
28 LOCAL_D const TInt KTenthSec = KSecond / 10; |
|
29 |
|
30 /// Time to wait before session/subsession close, to allow some writes to |
|
31 /// complete but not all (1 second per write with slow FS) |
|
32 LOCAL_D const TInt KSessionWaitTime = 25 * KTenthSec; |
|
33 |
|
34 /// Number of writes we expect to have completed |
|
35 LOCAL_D const TInt KSessionNumEnded = KSessionWaitTime / KSecond; |
|
36 |
|
37 GLREF_D TExtension gPrimaryExtensions[]; |
|
38 // ----------------------------------------------------------------- |
|
39 |
|
40 void TSoakStats::Print() |
|
41 /// |
|
42 /// Print a statistics header. |
|
43 /// |
|
44 { |
|
45 TTest::Printf(_L(" Total Fail\n")); |
|
46 } |
|
47 |
|
48 void TSoakStats::Print(const TDesC& aTitle) |
|
49 /// |
|
50 /// Print the statistics for this item (title, total executed, number executed |
|
51 /// this time, total failures, failures this time) then reset the "this time" |
|
52 /// values. |
|
53 /// |
|
54 { |
|
55 TTest::Printf(_L(" %-8S %8d %+8d %8d %+8d\n"), |
|
56 &aTitle, iTotal, iThis, iFail, iThisF); |
|
57 iThis = 0; |
|
58 iThisF = 0; |
|
59 } |
|
60 |
|
61 void TSoakStats::Inc() |
|
62 /// |
|
63 /// Increment both the total and "this time" execution numbers. |
|
64 /// |
|
65 { |
|
66 iTotal++; |
|
67 iThis++; |
|
68 } |
|
69 |
|
70 void TSoakStats::Fail() |
|
71 /// |
|
72 /// Increment both the total and "this time" failure numbers. |
|
73 /// |
|
74 { |
|
75 iFail++; |
|
76 iThisF++; |
|
77 } |
|
78 |
|
79 |
|
80 // ----------------------------------------------------------------- |
|
81 |
|
82 TSoakReadOnly::TSoakReadOnly() : iDrive(-1) |
|
83 /// |
|
84 /// Initialise the "read only" tests, connect the file session. |
|
85 /// |
|
86 { |
|
87 TInt r = iFs.Connect(); |
|
88 if (r != KErrNone) |
|
89 TTest::Fail(HERE, r, _L("iFs connect")); |
|
90 } |
|
91 |
|
92 TSoakReadOnly::TSoakReadOnly(TInt aDriveCh) : iDrive(aDriveCh) |
|
93 /// |
|
94 /// Initialise the "read only" tests, connect the file session, setting up |
|
95 /// a drive to be excluded from the reading. |
|
96 /// @param aDriveCh Drive letter to be excluded. |
|
97 /// |
|
98 { |
|
99 TInt r = iFs.Connect(); |
|
100 if (r != KErrNone) |
|
101 TTest::Fail(HERE, r, _L("iFs connect")); |
|
102 } |
|
103 |
|
104 TSoakReadOnly::~TSoakReadOnly() |
|
105 /// |
|
106 /// Destructor -- close the file session. |
|
107 /// |
|
108 { |
|
109 iFs.Close(); |
|
110 } |
|
111 |
|
112 TInt TSoakReadOnly::ReadFile(const TDesC& aName, TInt aSize) |
|
113 /// |
|
114 /// Read a file, expecting a certain size. No check is done on the actual |
|
115 /// data, just that it can be read. |
|
116 /// @param aName Name of the file. |
|
117 /// @param aSize Expected file size. |
|
118 /// |
|
119 { |
|
120 TInt r = KErrNone; |
|
121 RFile f; |
|
122 iReads.Inc(); |
|
123 r = f.Open(iFs, aName, EFileStreamText); |
|
124 if (r == KErrNotFound || r == KErrPathNotFound) |
|
125 return KErrNone; |
|
126 TBuf<256> errbuf; |
|
127 if (r != KErrNone) |
|
128 { |
|
129 if (r != KErrInUse) |
|
130 { |
|
131 iFiles.Fail(); |
|
132 TTest::Printf(_L("%S -- open failed %S\n"), &aName, &TTest::ErrStr(r, errbuf)); |
|
133 } |
|
134 else |
|
135 TTest::Printf(_L("Warning: %S -- open failed %S\n"), &aName, &TTest::ErrStr(r, errbuf)); |
|
136 return r; |
|
137 } |
|
138 TBuf8<256> buf; |
|
139 TInt len = 0; |
|
140 while ((r = f.Read(buf)) == KErrNone && buf.Length() > 0) |
|
141 len += buf.Length(); |
|
142 f.Close(); |
|
143 if (r != KErrNone && r != KErrEof) |
|
144 { |
|
145 iReads.Fail(); |
|
146 TTest::Printf(_L("ERROR %S -- READ FAILED %S\n"), &aName, &TTest::ErrStr(r, errbuf)); |
|
147 } |
|
148 else if (len < aSize) |
|
149 { |
|
150 iReads.Fail(); |
|
151 TTest::Printf(_L("ERROR %S -- %d READ, %d EXPECTED\n"), &aName, len, aSize); |
|
152 } |
|
153 else if (len > aSize) |
|
154 TTest::Printf(_L("Warning: %S -- %d read, %d expected\n"), &aName, len, aSize); |
|
155 return r; |
|
156 } |
|
157 |
|
158 TInt TSoakReadOnly::ScanDirs(TInt aDriveCh, TInt aReadInterval) |
|
159 /// |
|
160 /// Scan directories on a drive, reading a selection of the files found. |
|
161 /// @param aDriveCh Drive letter to be scanned. |
|
162 /// @param aReadInterval Approximate number of files to be read (they are |
|
163 /// read at random, so the actual number read may be |
|
164 /// less than this number). |
|
165 /// |
|
166 { |
|
167 TInt r = KErrNone; |
|
168 CDirScan* scanner=NULL; |
|
169 TRAP(r, scanner=CDirScan::NewL(iFs)); |
|
170 ScanDirFunc(scanner, aDriveCh, aReadInterval); |
|
171 delete scanner; |
|
172 return r; |
|
173 } |
|
174 |
|
175 TInt TSoakReadOnly::ScanDirFunc(CDirScan* aScanner, TInt aDriveCh, TInt aReadInterval) |
|
176 /// |
|
177 /// Scan directories on a drive, reading a selection of the files found. |
|
178 /// @param aDriveCh Drive letter to be scanned. |
|
179 /// @param aReadInterval Approximate number of files to be read (they are |
|
180 /// read at random, so the actual number read may be |
|
181 /// less than this number). |
|
182 /// |
|
183 { |
|
184 TInt r = KErrNone; |
|
185 TBuf<8> name; |
|
186 name.Format(_L("%c:\\"), aDriveCh); |
|
187 // TTest::Printf(_L("Scanning %S\n"), &name); |
|
188 TParse dirName; |
|
189 r=iFs.Parse(name, dirName); |
|
190 if (r != KErrNone) |
|
191 { |
|
192 iDrives.Fail(); |
|
193 return r; |
|
194 } |
|
195 CDir* entryList = NULL; |
|
196 TInt nfiles = 0; |
|
197 TRAP(r, aScanner->SetScanDataL(dirName.FullName(),KEntryAttDir,ESortByName)); |
|
198 if (r != KErrNone) |
|
199 { |
|
200 TTest::Fail(HERE, r, _L("SetScanData %S"), &dirName.FullName()); |
|
201 } |
|
202 TRAP(r, aScanner->NextL(entryList)); |
|
203 if (r == KErrPathNotFound) |
|
204 return KErrNone; |
|
205 if (r != KErrNone) |
|
206 { |
|
207 TTest::Fail(HERE, r, _L("Scan Next %S"), &dirName.FullName()); |
|
208 } |
|
209 while (entryList) |
|
210 { |
|
211 for (TInt i = 0; i < entryList->Count(); i++) |
|
212 { |
|
213 TEntry e = (*entryList)[i]; |
|
214 if (!e.IsDir()) |
|
215 ++nfiles; |
|
216 } |
|
217 delete entryList; |
|
218 TRAP(r, aScanner->NextL(entryList)); |
|
219 if (r == KErrPathNotFound) |
|
220 break; |
|
221 if (r != KErrNone) |
|
222 { |
|
223 TTest::Fail(HERE, r, _L("Scan Next %S"), &dirName.FullName()); |
|
224 } |
|
225 } |
|
226 TInt prob = (nfiles / aReadInterval) + 1; |
|
227 TRAP(r, aScanner->SetScanDataL(dirName.FullName(),KEntryAttDir,ESortByName)); |
|
228 if (r == KErrPathNotFound) |
|
229 return KErrNone; |
|
230 if (r != KErrNone) |
|
231 { |
|
232 TTest::Fail(HERE, r, _L("Scan Next %S"), &dirName.FullName()); |
|
233 } |
|
234 for (;;) |
|
235 { |
|
236 TRAP(r, aScanner->NextL(entryList)); |
|
237 if (r == KErrPathNotFound) |
|
238 return KErrNone; |
|
239 if (r != KErrNone) |
|
240 { |
|
241 TTest::Fail(HERE, r, _L("Scan Next %S"), &dirName.FullName()); |
|
242 } |
|
243 if (entryList==NULL) |
|
244 break; |
|
245 TInt count=entryList->Count(); |
|
246 while (count--) |
|
247 { |
|
248 TEntry e = (*entryList)[count]; |
|
249 TFileName path=aScanner->FullPath(); |
|
250 path.Append(e.iName); |
|
251 TBuf<16> attr; |
|
252 for (TInt j = 0; j < 16; j++) |
|
253 { |
|
254 if ((1 << j) & e.iAtt) |
|
255 attr.Append(TText("RHSVDA X "[j])); |
|
256 } |
|
257 if (e.IsDir()) |
|
258 { |
|
259 iDirs.Inc(); |
|
260 // TTest::Printf(_L("%c:%-50S <DIR> %S\n"), aDriveCh, &path, &attr); |
|
261 } |
|
262 else |
|
263 { |
|
264 iFiles.Inc(); |
|
265 TBool read = (aReadInterval && Math::Rand(iSeed) % prob == 0); |
|
266 if (read) |
|
267 { |
|
268 // TTest::Printf(_L("%-50S %8d %-8S test\n"), &path, e.iSize, &attr); |
|
269 r = ReadFile(path, e.iSize); |
|
270 } |
|
271 else |
|
272 { |
|
273 // TTest::Printf(_L("%c:%-50S %8d %S\n"), aDriveCh, &path, e.iSize, &attr); |
|
274 } |
|
275 } |
|
276 } |
|
277 delete entryList; |
|
278 entryList=NULL; |
|
279 } |
|
280 return r; |
|
281 } |
|
282 |
|
283 TInt TSoakReadOnly::ScanDrives(TBool aScanDirs, TInt aReadInterval) |
|
284 /// |
|
285 /// Scan all drives (except the one excluded) for directories and files. |
|
286 /// @param aScanDirs If true, read subdirectories, if false don't. |
|
287 /// @param aReadInterval approximate number of files to read. |
|
288 /// |
|
289 { |
|
290 TInt r = KErrNone; |
|
291 TInt i; |
|
292 for (i = EDriveA; i <= EDriveZ; i++) |
|
293 { |
|
294 TChar drv; |
|
295 r=iFs.DriveToChar(i, drv); |
|
296 if (r != KErrNone) |
|
297 return r; |
|
298 TDriveInfo info; |
|
299 r=iFs.Drive(info, i); |
|
300 if (r != KErrNone) |
|
301 return r; |
|
302 if (i != iDrive |
|
303 && info.iDriveAtt != 0 |
|
304 && info.iType != EMediaUnknown |
|
305 && info.iType != EMediaNotPresent) |
|
306 { |
|
307 iDrives.Inc(); |
|
308 // TTest::Printf(_L("Drive %c:"), drv); |
|
309 if (aScanDirs) |
|
310 { |
|
311 iDirs.Inc(); |
|
312 r = ScanDirs(drv, aReadInterval); |
|
313 if (r != KErrNone) |
|
314 return r; |
|
315 } |
|
316 } |
|
317 } |
|
318 return r; |
|
319 } |
|
320 |
|
321 void |
|
322 TSoakReadOnly::ExcludeDrive(TInt aDriveCh) |
|
323 /// |
|
324 /// Set a drive to be excluded from scanning. |
|
325 /// @param aDriveCh Drive letter to be excluded. |
|
326 /// |
|
327 { |
|
328 iDrive = aDriveCh; |
|
329 } |
|
330 |
|
331 |
|
332 // -------------------------------------------------------------------------- |
|
333 |
|
334 TSoakFill::TSoakFill() |
|
335 /// |
|
336 /// Initialise the fill/clean cycle. |
|
337 /// |
|
338 { |
|
339 iSeed = 186483; |
|
340 TInt r = iFs.Connect(); |
|
341 if (r != KErrNone) |
|
342 TTest::Fail(HERE, r, _L("iFs connect")); |
|
343 } |
|
344 |
|
345 TInt TSoakFill::SetDrive(TInt aDriveCh) |
|
346 /// |
|
347 /// Set a drive to be stressed. The test directory is created and then it is |
|
348 /// cleaned (in case anything was left over from previous tests). Note that |
|
349 /// other directories on the drive are untouched. |
|
350 /// @param aDriveCh Drive letter to be used. |
|
351 /// @leave The drive scanning can cause the function to leave. |
|
352 /// |
|
353 { |
|
354 TInt r = KErrNone; |
|
355 iDrive = aDriveCh; |
|
356 if (aDriveCh) |
|
357 { |
|
358 iDrvCh = aDriveCh; |
|
359 iFs.CharToDrive(iDrvCh, iDrive); |
|
360 r=iFs.Volume(iInfo, iDrive); |
|
361 if (r != KErrNone) |
|
362 TTest::Fail(HERE, r, _L("volume info for %C:"), aDriveCh); |
|
363 iFree = iInfo.iSize; |
|
364 iName.Format(_L("%c:\\SOAK\\"), iDrvCh); |
|
365 r = iFs.MkDir(iName); |
|
366 if (r != KErrNone && r != KErrAlreadyExists) |
|
367 TTest::Fail(HERE, r, _L("mkdir %S"), &iName); |
|
368 r = KErrNone; |
|
369 } |
|
370 return r; |
|
371 } |
|
372 |
|
373 TInt TSoakFill::FillDrive() |
|
374 /// |
|
375 /// Fill the drive with files and directories of random lengths. |
|
376 /// @param aDriveCh Drive letter to be tested, or zero (absent) to use the one |
|
377 /// set up with SetDrive(). |
|
378 /// @leave Setting up a new drive can cause this function to leave. |
|
379 /// |
|
380 { |
|
381 TInt r = KErrNone; |
|
382 r=iFs.Volume(iInfo, iDrive); |
|
383 if (r != KErrNone) |
|
384 TTest::Fail(HERE, r, _L("volume info for %C:"), iDrvCh); |
|
385 iFree = iInfo.iFree; |
|
386 r = iFs.MkDir(iName); |
|
387 if (r != KErrNone && r != KErrAlreadyExists && r != KErrNotSupported) |
|
388 TTest::Fail(HERE, r, _L("mkdir %S"), &iName); |
|
389 do |
|
390 { |
|
391 r = Fill(iName); |
|
392 if (r == KErrDiskFull) |
|
393 { |
|
394 // TTest::Printf(_L("Disk full on %c:\n"), iDrvCh); |
|
395 break; |
|
396 } |
|
397 if (r != KErrNone) |
|
398 TTest::Fail(HERE, r, _L("Filling drive %c"), iDrvCh); |
|
399 r=iFs.Volume(iInfo, iDrive); |
|
400 if (r != KErrNone) |
|
401 TTest::Fail(HERE, r, _L("volume info for %c:"), iDrvCh); |
|
402 } while (iInfo.iFree > 0); |
|
403 r=iFs.Volume(iInfo, iDrive); |
|
404 if (r != KErrNone) |
|
405 TTest::Fail(HERE, r, _L("volume info for %c:"), iDrvCh); |
|
406 if (iInfo.iFree > 0) |
|
407 TTest::Printf(_L("Free space on %c: %S %ld KB (out of %ld KB)\n"), |
|
408 iDrvCh, |
|
409 &iInfo.iName, |
|
410 I64LOW(iInfo.iFree / 1024), |
|
411 I64LOW(iInfo.iSize / 1024)); |
|
412 return r; |
|
413 } |
|
414 |
|
415 TInt TSoakFill::CleanDrive() |
|
416 /// |
|
417 /// Clean the test directory on the selected drive, removing all files and |
|
418 /// subdirectories. Other directories on the drive are left untouched. |
|
419 /// @leave Scanning the drive can cause the function to leave. |
|
420 /// |
|
421 { |
|
422 TInt r = KErrNone; |
|
423 CDirScan* scanner=0; |
|
424 TRAP(r, scanner=CDirScan::NewL(iFs)); |
|
425 if (r != KErrNone || !scanner) |
|
426 TTest::Fail(HERE, r, _L("creating scanner")); |
|
427 TParse dirName; |
|
428 r=iFs.Parse(iName, dirName); |
|
429 if (r != KErrNone) |
|
430 { |
|
431 if (r == KErrInUse || r == KErrNotFound || r == KErrPathNotFound) |
|
432 { |
|
433 // valid conditions, don't report error |
|
434 r = KErrNone; |
|
435 } |
|
436 else |
|
437 TTest::Fail(HERE, r, _L("Parse %S"), &iName); |
|
438 } |
|
439 else |
|
440 { |
|
441 // TTest::Printf(_L("scan %S\n"), &iName); |
|
442 CDir* entryList = NULL; |
|
443 TRAP(r, scanner->SetScanDataL(dirName.FullName(),KEntryAttDir,ESortByName,CDirScan::EScanUpTree)); |
|
444 if (r != KErrNone) |
|
445 TTest::Fail(HERE, r, _L("SetScanDataL(%S)"), &dirName.FullName()); |
|
446 TRAP(r, scanner->NextL(entryList)); |
|
447 if (r != KErrNone && r != KErrPathNotFound) |
|
448 TTest::Fail(HERE, r, _L("Scan NextL()")); |
|
449 while (entryList) |
|
450 { |
|
451 for (TInt i = 0; i < entryList->Count(); i++) |
|
452 { |
|
453 TEntry e = (*entryList)[i]; |
|
454 TFileName path = iName; |
|
455 if (path.Right(1) == _L("\\")) |
|
456 path.SetLength(path.Length()-1); |
|
457 path.Append(scanner->AbbreviatedPath()); |
|
458 path.Append(e.iName); |
|
459 // TTest::Printf(_L("remove %S\n"), &path); |
|
460 TBuf<256> buf; |
|
461 TInt maxInUseCount = 120; |
|
462 do |
|
463 { |
|
464 if (e.IsDir()) |
|
465 { |
|
466 if (path.Right(1) != _L("\\")) |
|
467 path.Append(_L("\\")); |
|
468 r = iFs.RmDir(path); |
|
469 } |
|
470 else |
|
471 r = iFs.Delete(path); |
|
472 if (r == KErrInUse) |
|
473 { |
|
474 TTest::Printf(_L("Warning: %S deleting %S\n"), &TTest::ErrStr(r, buf), &path); |
|
475 User::After(1*KSecond); |
|
476 } |
|
477 } |
|
478 while (r == KErrInUse && maxInUseCount-- > 0); |
|
479 if (r != KErrNone) |
|
480 { |
|
481 TTest::Printf(_L("ERROR %S deleting %S\n"), &TTest::ErrStr(r, buf), &path); |
|
482 } |
|
483 } |
|
484 delete entryList; |
|
485 TRAP(r, scanner->NextL(entryList)); |
|
486 if (r != KErrNone) |
|
487 TTest::Fail(HERE, r, _L("Scan NextL()")); |
|
488 } |
|
489 } |
|
490 delete scanner; |
|
491 r = iFs.RmDir(iName); |
|
492 if (r != KErrNone && r != KErrNotFound && r != KErrPathNotFound) |
|
493 { |
|
494 TTest::Fail(HERE, r, _L("volume info for %C:"), iName[0]); |
|
495 } |
|
496 r=iFs.Volume(iInfo, iDrive); |
|
497 if (r != KErrNone) |
|
498 { |
|
499 TTest::Fail(HERE, r, _L("volume info for %C:"), iName[0]); |
|
500 } |
|
501 if (iInfo.iFree > iFree) |
|
502 { |
|
503 TTest::Printf(_L("Warning: %C: changed size -- was %ld now %ld\n"), |
|
504 iName[0], iFree, iInfo.iFree); |
|
505 return r; |
|
506 } |
|
507 iFree = iInfo.iFree; |
|
508 return r; |
|
509 } |
|
510 |
|
511 TInt TSoakFill::Fill(TFileName& aName, TInt aNfiles) |
|
512 /// |
|
513 /// Recursively create files and subdirectories at random. If a subdirectory |
|
514 /// is created, the function recurses to fill it. This generates a mixture of |
|
515 /// directories and files of varying lengths. |
|
516 /// @param aName Directory in which to create other stuff. |
|
517 /// @param aNfiles Maximum number of files to create. |
|
518 /// @return Status of last thing created, KErrDiskFull when out of space. |
|
519 /// |
|
520 { |
|
521 TInt oldlen = aName.Length(); |
|
522 if (oldlen + 10 > aName.MaxLength()) |
|
523 return KErrNone; |
|
524 TInt r=iFs.Volume(iInfo, iDrive); |
|
525 if (r != KErrNone) |
|
526 return r; |
|
527 TInt nfiles = I64LOW(iInfo.iFree/10000) + 5; |
|
528 if (aNfiles > 0 && nfiles > aNfiles) |
|
529 nfiles = aNfiles; |
|
530 nfiles = Math::Rand(iSeed) % nfiles + 5; |
|
531 TInt filesz = I64LOW(iInfo.iFree/nfiles/256) + 5; |
|
532 // TTest::Printf(_L("nfiles = %d\n"), nfiles); |
|
533 TInt i; |
|
534 for (i = 0; i < nfiles; i++) |
|
535 { |
|
536 aName.SetLength(oldlen); |
|
537 TBool dir = (Math::Rand(iSeed) % 5 == 0); |
|
538 if (dir && oldlen < 80) |
|
539 { |
|
540 aName.Append(_L("d")); |
|
541 aName.AppendNum(i); |
|
542 aName.Append(_L("\\")); |
|
543 r = iFs.MkDir(aName); |
|
544 TInt busycount = 120; |
|
545 while (busycount-- > 0) |
|
546 { |
|
547 r = iFs.MkDir(aName); |
|
548 if (r == KErrDiskFull) |
|
549 TTest::Printf(_L("Disk full creating %S\n"), &aName); |
|
550 if (r != KErrInUse) |
|
551 break; |
|
552 TTest::Printf(_L("Warning: KErrInUse creating %S\n"), &aName); |
|
553 User::After(1*KSecond); |
|
554 } |
|
555 // TTest::Printf(_L("mkdir %S = %d\n"), &aName, r); |
|
556 if (r == KErrNone || r == KErrAlreadyExists) |
|
557 { |
|
558 r = Fill(aName, nfiles - i - 2); |
|
559 } |
|
560 if (r != KErrNone) |
|
561 break; |
|
562 } |
|
563 else |
|
564 { |
|
565 aName.Append(_L("F")); |
|
566 aName.AppendNum(i); |
|
567 RFile f; |
|
568 TInt busycount = 120; |
|
569 while (busycount-- > 0) |
|
570 { |
|
571 r = f.Replace(iFs, aName, EFileStreamText | EFileWrite); |
|
572 if (r != KErrInUse) |
|
573 break; |
|
574 TTest::Printf(_L("Warning: KErrInUse creating %S\n"), &aName); |
|
575 User::After(1*KSecond); |
|
576 } |
|
577 if (r == KErrNone) |
|
578 { |
|
579 // iNames.AppendL(aName); |
|
580 TInt num = Math::Rand(iSeed) % filesz + 10; |
|
581 TBuf8<256> buf; |
|
582 buf.Fill(TText(' '), 256); |
|
583 TInt wr = 0; |
|
584 while (num-- > 0 && r == KErrNone) |
|
585 { |
|
586 r = f.Write(buf); |
|
587 if (r == KErrNone) |
|
588 wr += 256; |
|
589 else |
|
590 break; |
|
591 } |
|
592 f.Close(); |
|
593 /* |
|
594 if (r == KErrDiskFull) |
|
595 TTest::Printf(_L("Disk full writing %S\n"), &aName); |
|
596 */ |
|
597 if (r != KErrNone) |
|
598 break; |
|
599 } |
|
600 else |
|
601 { |
|
602 // TTest::Printf(_L("creat %S = %d\n"), &aName, r); |
|
603 if (r == KErrDiskFull) |
|
604 TTest::Printf(_L("Disk full creating %S\n"), &aName); |
|
605 break; |
|
606 } |
|
607 } |
|
608 } |
|
609 aName.SetLength(oldlen); |
|
610 return r; |
|
611 } |
|
612 |
|
613 |
|
614 TSoakRemote::TSoakRemote(TInt aDriveCh) |
|
615 /// |
|
616 /// Initialise testing for 'remote' drive (special filesystem). Connects to |
|
617 /// file session, initialises the drive and timer, sets up the buffers and |
|
618 /// file name. |
|
619 /// @param aDriveCh Drive letter for the drive to test. |
|
620 /// |
|
621 { |
|
622 TInt r = iFs.Connect(); |
|
623 if (r != KErrNone) |
|
624 TTest::Fail(HERE, r, _L("iFs connect")); |
|
625 iDrvCh = aDriveCh; |
|
626 iSync = EFalse; |
|
627 iFs.CharToDrive(iDrvCh, iDrive); |
|
628 iTimer.CreateLocal(); |
|
629 Setup(); |
|
630 } |
|
631 |
|
632 void TSoakRemote::Setup() |
|
633 /// Set up the buffers and the filename to be used. |
|
634 { |
|
635 for (TInt i = 0; i < KSoakNumBuf; i++) |
|
636 { |
|
637 iBuff[i].Fill('_', KSoakBufLen); |
|
638 iStat[i] = KErrNone; |
|
639 } |
|
640 iName.Format(_L("%c:\\SOAKTEST.FILE"), iDrvCh); |
|
641 } |
|
642 |
|
643 void TSoakRemote::Remount(TBool aSync) |
|
644 /// |
|
645 /// Remount the test drive as (a)synchronous. |
|
646 /// @param aSync If true, the drive is set as synchronous access, otherwise |
|
647 /// as asynchronous. |
|
648 /// |
|
649 { |
|
650 TFileName fsname; |
|
651 iSync = aSync; |
|
652 TInt r = iFs.FileSystemName(fsname, iDrive); |
|
653 TEST(r == KErrNone || r == KErrNotFound); |
|
654 |
|
655 if (fsname.Length() > 0) |
|
656 { |
|
657 r = iFs.ExtensionName(gPrimaryExtensions[iDrive].iName, iDrive, 0); |
|
658 if (r == KErrNone) |
|
659 gPrimaryExtensions[iDrive].iExists = ETrue; |
|
660 |
|
661 r = iFs.DismountFileSystem(fsname, iDrive); |
|
662 if(r != KErrNone) |
|
663 { |
|
664 TTest::Fail(HERE, r, _L("Dismounting file system %S"), &fsname); |
|
665 } |
|
666 } |
|
667 |
|
668 TBufC<16> type = _L("asynchronous"); |
|
669 if (iSync) |
|
670 type = _L("synchronous"); |
|
671 TTest::Printf(_L("Remount filesystem %c: %S as %S\n"), iDrvCh, &fsname, &type); |
|
672 |
|
673 #ifdef __CONCURRENT_FILE_ACCESS__ |
|
674 if (gPrimaryExtensions[iDrive].iExists == EFalse) |
|
675 r=iFs.MountFileSystem(fsname,iDrive,iSync); |
|
676 else |
|
677 r=iFs.MountFileSystem(fsname,gPrimaryExtensions[iDrive].iName,iDrive,iSync); |
|
678 #else |
|
679 if (gPrimaryExtensions[aDrive].iExists == EFalse) |
|
680 r=iFs.MountFileSystem(fsname,iDrive); |
|
681 else |
|
682 r=iFs.MountFileSystem(fsname,gPrimaryExtensions[iDrive].iName,iDrive); |
|
683 #endif |
|
684 TEST(r==KErrNone); |
|
685 } |
|
686 |
|
687 TInt TSoakRemote::TestSubSession() |
|
688 /// |
|
689 /// Test what happens when a file is closed in the middle of writing it. Note |
|
690 /// that this assumes that the filesystem under test takes a second for each |
|
691 /// write operation (i.e. is the special test filesystem). |
|
692 /// |
|
693 { |
|
694 TInt r = iFile.Replace(iFs, iName, EFileStreamText | EFileWrite); |
|
695 if (r != KErrNone) |
|
696 TTest::Fail(HERE, r, _L("opening %S for writing"), iName.Ptr()); |
|
697 TInt i; |
|
698 for (i = 0; i < KSoakNumBuf; i++) |
|
699 { |
|
700 iFile.Write(iBuff[i], iStat[i]); |
|
701 } |
|
702 // wait for a couple of writes to complete, then close the file before the |
|
703 // others finish |
|
704 User::After(KSessionWaitTime); |
|
705 TTest::Printf(_L("Wait ended")); |
|
706 iFile.Close(); |
|
707 TTest::Printf(_L("Close ended")); |
|
708 // test what has happened |
|
709 TBool bad = EFalse; |
|
710 for (i = 0; i < KSoakNumBuf; i++) |
|
711 { |
|
712 User::WaitForRequest(iStat[i]); |
|
713 r = iStat[i].Int(); |
|
714 switch (r) |
|
715 { |
|
716 case KErrNone: |
|
717 if (i >= KSessionNumEnded) |
|
718 { |
|
719 TTest::Printf(_L("Write %d not cancelled"), i); |
|
720 bad = ETrue; |
|
721 } |
|
722 break; |
|
723 case KErrCancel: |
|
724 if (i <= KSessionNumEnded) |
|
725 { |
|
726 TTest::Printf(_L("Write %d incorrectly cancelled"), i); |
|
727 bad = ETrue; |
|
728 } |
|
729 TTest::Printf(_L("write %d cancelled\n"), i); |
|
730 break; |
|
731 default: |
|
732 TTest::Fail(HERE, r, _L("incorrect status for write %d"), i); |
|
733 } |
|
734 } |
|
735 iFs.Delete(iName); |
|
736 TPtrC sbuf(iSync ? _L("sync") : _L("async")); |
|
737 if (bad) |
|
738 { |
|
739 TTest::Printf(_L("TestSubSession %c: %S FAILED\n"), iName[0], &sbuf); |
|
740 // Commented out for the moment as result is undefined |
|
741 // TTest::Fail(HERE, _L("TestSubSession %c: %S FAILED\n"), iName[0], &sbuf); |
|
742 } |
|
743 TTest::Printf(_L("TestSubSession %c: %S OK\n"), iName[0], &sbuf); |
|
744 return KErrNone; |
|
745 } |
|
746 |
|
747 TInt TSoakRemote::TestSession() |
|
748 /// |
|
749 /// Test what happens when a session is closed in the middle of writing a file. |
|
750 /// Note that this assumes that the filesystem under test takes a second for |
|
751 /// each write operation (i.e. is the special test filesystem). |
|
752 /// |
|
753 { |
|
754 TInt r; |
|
755 TInt i; |
|
756 TPtrC sbuf(iSync ? _L("sync") : _L("async")); |
|
757 |
|
758 r = iFile.Replace(iFs, iName, EFileStreamText | EFileWrite); |
|
759 if (r != KErrNone) |
|
760 TTest::Fail(HERE, r, _L("opening %S for writing"), iName.Ptr()); |
|
761 for (i = 0; i < KSoakNumBuf; i++) |
|
762 { |
|
763 iFile.Write(iBuff[i], iStat[i]); |
|
764 } |
|
765 // wait for a couple of them to complete, then close the session |
|
766 User::After(KSessionWaitTime); |
|
767 TTest::Printf(_L("Close FS %S"), &sbuf); |
|
768 // iFs.SetDebugRegister(KFSYS | KFSERV | KTHRD); |
|
769 iFs.Close(); |
|
770 TTest::Printf(_L("FS closed %S"), &sbuf); |
|
771 // see what has happened to the writes (wait for at most another 10 seconds). |
|
772 TRequestStatus tstat; |
|
773 iTimer.After(tstat, 10*KSecond); |
|
774 TBool busy = ETrue; |
|
775 TInt file = 0; |
|
776 while (tstat == KRequestPending && busy) |
|
777 { |
|
778 User::WaitForAnyRequest(); |
|
779 busy = EFalse; |
|
780 for (i = file; i < KSoakNumBuf; i++) |
|
781 { |
|
782 r = iStat[i].Int(); |
|
783 switch (r) |
|
784 { |
|
785 case KRequestPending: |
|
786 busy = ETrue; |
|
787 TTest::Printf(_L("write %d pending\n"), i); |
|
788 break; |
|
789 case KErrNone: |
|
790 file = i + 1; |
|
791 TTest::Printf(_L("write %d finished\n"), i); |
|
792 break; |
|
793 case KErrCancel: |
|
794 file = i + 1; |
|
795 TTest::Printf(_L("write %d cancelled\n"), i); |
|
796 break; |
|
797 default: |
|
798 file = i + 1; |
|
799 TTest::Fail(HERE, r, _L("incorrect status for write %d"), i); |
|
800 } |
|
801 } |
|
802 } |
|
803 TBool bad = EFalse; |
|
804 if (busy) |
|
805 { |
|
806 for (i = 0; i < KSoakNumBuf; i++) |
|
807 { |
|
808 TBuf<64> buf; |
|
809 r = iStat[i].Int(); |
|
810 if (r != KErrNone) |
|
811 { |
|
812 // We expect that the third and subsequent requests will either |
|
813 // have failed with cancel or be still outstanding. If either |
|
814 // of the first two have failed or are outstanding, that's an |
|
815 // error. |
|
816 if (i < KSessionNumEnded || (r != KErrCancel && r != KRequestPending)) |
|
817 { |
|
818 TTest::Fail(HERE, _L("write %d: %S\n"), i, &TTest::ErrStr(r, buf)); |
|
819 bad = ETrue; |
|
820 } |
|
821 } |
|
822 } |
|
823 } |
|
824 iTimer.Cancel(); |
|
825 // if it's got this far, re-connect the file session |
|
826 // User::After(100000); |
|
827 // TTest::Printf(_L("FS closed (%S) yet?"), &sbuf); |
|
828 r = iFs.Connect(); |
|
829 iFs.SetDebugRegister(0); |
|
830 // TTest::Printf(_L("FS opened")); |
|
831 if (r != KErrNone) |
|
832 TTest::Fail(HERE, r, _L("iFs connect")); |
|
833 r = iFs.Delete(iName); |
|
834 for (TInt nr = 0; r == KErrInUse && nr < 100; nr++) |
|
835 { |
|
836 TTest::Printf(_L("Wait for previous session to close")); |
|
837 User::After(10*KSecond); |
|
838 r = iFs.Delete(iName); |
|
839 } |
|
840 if (r == KErrNotFound) |
|
841 r = KErrNone; |
|
842 if (r != KErrNone) |
|
843 bad = ETrue; |
|
844 TPtrC obuf(bad ? _L("FAIL") : _L("OK")); |
|
845 TTest::Printf(_L("TestSession %c: %S %S\n"), iName[0], &sbuf, &obuf); |
|
846 if (bad) |
|
847 { |
|
848 TTest::Printf(_L("Test session close %c: %S FAILED\n"), iName[0], &sbuf); |
|
849 // Commented out for the moment as result is undefined |
|
850 // TTest::Fail(HERE, _L("Test session close failed")); |
|
851 } |
|
852 return r; |
|
853 } |
|
854 |
|
855 TInt TSoakRemote::TestMount() |
|
856 /// |
|
857 /// Test dismounting with a file open (should fail) |
|
858 /// |
|
859 { |
|
860 TFileName fsname; |
|
861 TInt r = iFs.FileSystemName(fsname, iDrive); |
|
862 TEST(r == KErrNone || r == KErrNotFound); |
|
863 |
|
864 TPtrC sbuf(iSync ? _L("sync") : _L("async")); |
|
865 |
|
866 r = iFile.Replace(iFs, iName, EFileStreamText | EFileWrite); |
|
867 for (TInt nr = 0; r == KErrInUse && nr < 100; nr++) |
|
868 { |
|
869 TTest::Printf(_L("Warning: KErrInUse opening %S for writing\n"), &iName); |
|
870 User::After(10*KSecond); |
|
871 r = iFile.Replace(iFs, iName, EFileStreamText | EFileWrite); |
|
872 } |
|
873 if (r != KErrNone) |
|
874 TTest::Fail(HERE, r, _L("opening %S for writing"), &iName); |
|
875 |
|
876 if (fsname.Length() > 0) |
|
877 { |
|
878 r = iFs.DismountFileSystem(fsname, iDrive); |
|
879 if (r == KErrNone) |
|
880 { |
|
881 #ifdef __CONCURRENT_FILE_ACCESS__ |
|
882 r = iFs.MountFileSystem(fsname, iDrive, iSync); |
|
883 #else |
|
884 r = iFs.MountFileSystem(fsname, iDrive); |
|
885 #endif |
|
886 if (r != KErrNone) |
|
887 TTest::Fail(HERE, r, _L("MountFileSystem(%S, %C:)"), &fsname, iDrvCh); |
|
888 } |
|
889 else if (r != KErrInUse) |
|
890 { |
|
891 TTest::Fail(HERE, r, _L("DismountFileSystem(%S, %C:)"), &fsname, iDrvCh); |
|
892 } |
|
893 } |
|
894 |
|
895 iFile.Close(); |
|
896 iFs.Delete(iName); |
|
897 |
|
898 TTest::Printf(_L("TestMount %c: %S OK\n"), iName[0], &sbuf); |
|
899 |
|
900 return KErrNone; |
|
901 } |
|
902 |
|
903 |