|
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 "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 // |
|
15 |
|
16 #include <e32test.h> |
|
17 #include <bautils.h> |
|
18 #include <sqldb.h> |
|
19 #include <e32math.h> |
|
20 |
|
21 #include "SqlBur.h" |
|
22 #include "t_sqlbur.h" |
|
23 |
|
24 /////////////////////////////////////////////////////////////////////////////////////// |
|
25 |
|
26 RTest TheTest(_L("SQL Backup and Restore Test")); |
|
27 |
|
28 _LIT(KPrivateDir, "C:\\private\\10281e17\\"); |
|
29 |
|
30 const TUid KClientUid = {0x21212122}; // the data owner's UID |
|
31 |
|
32 _LIT(KBackupDir, "C:\\TEST\\"); |
|
33 _LIT(KBackupFile, "C:\\TEST\\Backup.bak"); |
|
34 _LIT(KBackupFile2Z, "Z:\\TEST\\t_sqlbur_backup_ver0.bak"); |
|
35 _LIT(KBackupFile2, "C:\\TEST\\t_sqlbur_backup_ver0.bak"); |
|
36 |
|
37 const TUint KBufferSize = 2048; // used for reading backup files for validation |
|
38 |
|
39 static CActiveScheduler* TheScheduler = NULL; |
|
40 static CSqlBurTestHarness* TheTestHarness = NULL; |
|
41 |
|
42 ///////////////////////////////////// |
|
43 |
|
44 const TInt KMaxDbFileSize = 10 * 1024;//The max test db file size |
|
45 const TInt KTestDbFileCnt = 2; |
|
46 |
|
47 //Test db files |
|
48 _LIT(KTestFileName1,"[21212122]AADB2.db");//Created outside this test app |
|
49 _LIT(KTestFileName2,"[21212122]BBDB2.db");//Created outside this test app |
|
50 _LIT(KTestDbFileName1,"C:[21212122]AADB2.db"); |
|
51 _LIT(KTestDbFileName2,"C:[21212122]BBDB2.db"); |
|
52 |
|
53 const TPtrC KTestFileNames[KTestDbFileCnt] = {KTestFileName1(), KTestFileName2()}; |
|
54 |
|
55 static TInt TheDbFileSizes[KTestDbFileCnt];//An array where the real db file size will be stored |
|
56 static TUint8 TheDbFileData[KTestDbFileCnt][KMaxDbFileSize];//An array where the original db file content will be stored |
|
57 static TUint8 TheBuf[KMaxDbFileSize]; |
|
58 |
|
59 ///////////////////////////////////// |
|
60 |
|
61 /////////////////////////////////////////////////////////////////////////////////////// |
|
62 |
|
63 void TestEnvDestroy() |
|
64 { |
|
65 delete TheTestHarness; |
|
66 TheTestHarness = NULL; |
|
67 |
|
68 delete TheScheduler; |
|
69 TheScheduler = NULL; |
|
70 } |
|
71 |
|
72 //////////////////////////// |
|
73 // Test macros and functions |
|
74 //////////////////////////// |
|
75 |
|
76 void Check(TInt aValue, TInt aLine) |
|
77 { |
|
78 if(!aValue) |
|
79 { |
|
80 TestEnvDestroy(); |
|
81 TheTest(EFalse, aLine); |
|
82 } |
|
83 } |
|
84 |
|
85 void Check(TInt aValue, TInt aExpected, TInt aLine) |
|
86 { |
|
87 if(aValue != aExpected) |
|
88 { |
|
89 TestEnvDestroy(); |
|
90 RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue); |
|
91 TheTest(EFalse, aLine); |
|
92 } |
|
93 } |
|
94 #define TEST(arg) ::Check((arg), __LINE__) |
|
95 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__) |
|
96 |
|
97 /////////////////////////////////////////////////////////////////////////////////////// |
|
98 |
|
99 //CSqlBurTestHarness - test implementation of the MSqlSrvBurInterface, implemented in the production code by the SQL server. |
|
100 CSqlBurTestHarness *CSqlBurTestHarness::New() |
|
101 { |
|
102 CSqlBurTestHarness* self = new CSqlBurTestHarness; |
|
103 TEST(self != NULL); |
|
104 self->Construct(); |
|
105 return self; |
|
106 } |
|
107 |
|
108 CSqlBurTestHarness::CSqlBurTestHarness() |
|
109 { |
|
110 } |
|
111 |
|
112 void CSqlBurTestHarness::Construct() |
|
113 { |
|
114 TInt err = iFs.Connect(); |
|
115 TEST2(err, KErrNone); |
|
116 err = iFs.MkDir(KBackupDir); |
|
117 TEST(err == KErrNone || err == KErrAlreadyExists); |
|
118 err = iFs.CreatePrivatePath(EDriveC); |
|
119 TEST2(err, KErrNone); |
|
120 } |
|
121 |
|
122 CSqlBurTestHarness::~CSqlBurTestHarness() |
|
123 { |
|
124 (void)iFs.Delete(KBackupFile); |
|
125 iFs.Close(); |
|
126 } |
|
127 |
|
128 //Called by the backup client ot get a list of database files to backup |
|
129 //The array is owned by the caller |
|
130 //The SQL server would have the job to get a list of databases owned by |
|
131 //the given SID and to determine whether the backup flag is set |
|
132 //All databases that satisfy this requirement will be added to the array |
|
133 void CSqlBurTestHarness::GetBackUpListL(TSecureId /*aUid*/, RArray<TParse>& aFileList) |
|
134 { |
|
135 //TheTest.Printf(_L("Getting backup file list for SID=%x\r\n"),aUid); |
|
136 for(TInt i=0;i<KTestDbFileCnt;++i) |
|
137 { |
|
138 TParse parse; |
|
139 parse.Set(KTestFileNames[i], &KPrivateDir, NULL); |
|
140 aFileList.AppendL(parse); |
|
141 } |
|
142 } |
|
143 |
|
144 //Notification that a backup is starting |
|
145 TBool CSqlBurTestHarness::StartBackupL(const RArray<TParse>& /*aFileList*/) |
|
146 { |
|
147 //TheTest.Printf(_L("Start \"backup\". %d files in the list.\r\n"), aFileList.Count()); |
|
148 return ETrue; |
|
149 } |
|
150 |
|
151 //Notification that a backup has ended |
|
152 void CSqlBurTestHarness::EndBackup(const RArray<TParse>& /*aFileList*/) |
|
153 { |
|
154 //TheTest.Printf(_L("End \"backup\". %d files in the list.\r\n"), aFileList.Count()); |
|
155 } |
|
156 |
|
157 //Notification that a restore is starting |
|
158 TBool CSqlBurTestHarness::StartRestoreL(TSecureId /*aUid*/) |
|
159 { |
|
160 //TheTest.Printf(_L("Start \"restore\" for UID=%X\r\n"), aUid); |
|
161 return ETrue; |
|
162 } |
|
163 |
|
164 //Notification that a restore has ended |
|
165 void CSqlBurTestHarness::EndRestore(TSecureId /*aUid*/) |
|
166 { |
|
167 //TheTest.Printf(_L("End \"restore\" for UID=%X\r\n"), aUid); |
|
168 } |
|
169 |
|
170 //Returns the file system resource handle to the caller. |
|
171 RFs& CSqlBurTestHarness::Fs() |
|
172 { |
|
173 return iFs; |
|
174 } |
|
175 |
|
176 /////////////////////////////////////////////////////////////////////////////////////// |
|
177 /////////////////////////////////////////////////////////////////////////////////////// |
|
178 /////////////////////////////////////////////////////////////////////////////////////// |
|
179 |
|
180 TBool FileExists(RFs& aFs, const TDesC& aFileName) |
|
181 { |
|
182 TEntry entry; |
|
183 return aFs.Entry(aFileName, entry) == KErrNone; |
|
184 } |
|
185 |
|
186 void TestEnvCreate() |
|
187 { |
|
188 TheScheduler = new CActiveScheduler; |
|
189 TEST(TheScheduler != NULL); |
|
190 |
|
191 CActiveScheduler::Install(TheScheduler); |
|
192 |
|
193 TheTestHarness = CSqlBurTestHarness::New(); |
|
194 TEST(TheTestHarness != NULL); |
|
195 } |
|
196 |
|
197 //Reads the content of the db files and stores the content to a global memory buffer. |
|
198 //That buffer content will be sued later for a verification of the restore process. |
|
199 void StoreDbContentToBuf(RFs& aFs) |
|
200 { |
|
201 for(TInt i=0;i<KTestDbFileCnt;++i) |
|
202 { |
|
203 RFile dbFile; |
|
204 TInt err = dbFile.Open(aFs, KTestFileNames[i], EFileRead); |
|
205 TEST2(err, KErrNone); |
|
206 |
|
207 TInt fileSize = 0; |
|
208 err = dbFile.Size(fileSize); |
|
209 TEST2(err, KErrNone); |
|
210 TEST(fileSize > 0); |
|
211 |
|
212 TPtr8 bufptr(TheDbFileData[i], 0, KMaxDbFileSize); |
|
213 err = dbFile.Read(bufptr, fileSize); |
|
214 TEST2(err, KErrNone); |
|
215 TEST(fileSize == bufptr.Length()); |
|
216 |
|
217 TheDbFileSizes[i] = fileSize; |
|
218 |
|
219 dbFile.Close(); |
|
220 } |
|
221 } |
|
222 |
|
223 //At the moment when this function is called, the db files content is already restored. |
|
224 //The function will open the restored db files and compare their content against the content |
|
225 //of the original db files (kept in a global memory buffer). |
|
226 void CompareDbContentWithBuf(RFs& aFs) |
|
227 { |
|
228 for(TInt i=0;i<KTestDbFileCnt;++i) |
|
229 { |
|
230 TEST(TheDbFileSizes[i] > 0); |
|
231 |
|
232 RFile dbFile; |
|
233 TInt err = dbFile.Open(aFs, KTestFileNames[i], EFileRead); |
|
234 TEST2(err, KErrNone); |
|
235 |
|
236 TInt fileSize = 0; |
|
237 err = dbFile.Size(fileSize); |
|
238 TEST2(err, KErrNone); |
|
239 TEST(fileSize > 0); |
|
240 TEST(TheDbFileSizes[i] == fileSize); |
|
241 |
|
242 TPtr8 bufptr(TheBuf, 0, KMaxDbFileSize); |
|
243 err = dbFile.Read(bufptr, fileSize); |
|
244 TEST2(err, KErrNone); |
|
245 TEST(fileSize == bufptr.Length()); |
|
246 |
|
247 err = Mem::Compare(TheBuf, fileSize, TheDbFileData[i], TheDbFileSizes[i]); |
|
248 TEST2(err, 0); |
|
249 |
|
250 dbFile.Close(); |
|
251 } |
|
252 } |
|
253 |
|
254 //////////////////////////////////////////////////////////////////////////////////////// |
|
255 |
|
256 //The backup client will return a series of data chunks representing |
|
257 //one of more databases for the uid of the data owner. |
|
258 //This data is stored in a file on the C drive for the purposes of the test |
|
259 TInt TestBackupL(CSqlBackupClient &aBackupClient, RFs& aFs, TInt aDataChunkSize = KBufferSize) |
|
260 { |
|
261 RFile file; |
|
262 CleanupClosePushL(file); |
|
263 TInt err = file.Replace(aFs, KBackupFile, EFileWrite | EFileStream | EFileShareExclusive); |
|
264 User::LeaveIfError(err); |
|
265 aBackupClient.InitialiseGetProxyBackupDataL(KClientUid, EDriveC); |
|
266 |
|
267 TBuf8<KBufferSize> buf; |
|
268 TPtr8 ptr((TUint8*)buf.Ptr(), aDataChunkSize); |
|
269 TBool finishedFlag = EFalse; |
|
270 TInt count = 0; |
|
271 |
|
272 do |
|
273 { |
|
274 aBackupClient.GetBackupDataSectionL(ptr, finishedFlag); |
|
275 count += ptr.Length(); |
|
276 err = file.Write(ptr); |
|
277 User::LeaveIfError(err); |
|
278 ptr.SetLength(0); |
|
279 } |
|
280 while(!finishedFlag); |
|
281 |
|
282 CleanupStack::PopAndDestroy(&file); |
|
283 |
|
284 if(count == 0) |
|
285 { |
|
286 User::Leave(KErrEof); |
|
287 } |
|
288 if(!FileExists(aFs, KBackupFile)) |
|
289 { |
|
290 User::Leave(KErrNotFound); |
|
291 } |
|
292 TheTest.Printf(_L("Backup complete. %d bytes processed.\r\n"), count); |
|
293 return count; |
|
294 } |
|
295 |
|
296 //This sends the data in chunks form back to the BUR client |
|
297 //for nupacking and restoration of the original databases files |
|
298 TInt TestRestoreL(CSqlBackupClient &aRestoreClient, RFs& aFs, TInt aDataChunkSize = KBufferSize) |
|
299 { |
|
300 RFile file; |
|
301 CleanupClosePushL(file); |
|
302 TInt err = file.Open(aFs, KBackupFile, EFileRead | EFileShareExclusive); |
|
303 User::LeaveIfError(err); |
|
304 aRestoreClient.InitialiseRestoreProxyBaseDataL(KClientUid, EDriveC); |
|
305 |
|
306 TBuf8<KBufferSize> buf; |
|
307 TPtr8 ptr((TUint8*)buf.Ptr(), aDataChunkSize); |
|
308 TBool finishedFlag = EFalse; |
|
309 |
|
310 TInt fileSize = 0; |
|
311 err = file.Size(fileSize); |
|
312 User::LeaveIfError(err); |
|
313 TInt count = fileSize; |
|
314 |
|
315 do |
|
316 { |
|
317 err = file.Read(ptr, aDataChunkSize); |
|
318 User::LeaveIfError(err); |
|
319 fileSize -= ptr.Length(); |
|
320 finishedFlag = fileSize == 0; |
|
321 aRestoreClient.RestoreBaseDataSectionL(ptr, finishedFlag); |
|
322 ptr.SetLength(0); |
|
323 } |
|
324 while(fileSize > 0); |
|
325 |
|
326 CleanupStack::PopAndDestroy(&file); |
|
327 |
|
328 aRestoreClient.RestoreComplete(EDriveC); |
|
329 |
|
330 if(!finishedFlag) |
|
331 { |
|
332 User::Leave(KErrEof); |
|
333 } |
|
334 for(TInt i=0;i<KTestDbFileCnt;++i) |
|
335 { |
|
336 if(!FileExists(aFs, KTestFileNames[i])) |
|
337 { |
|
338 User::Leave(KErrNotFound); |
|
339 } |
|
340 } |
|
341 |
|
342 TheTest.Printf(_L("Restore complete. %d bytes processed.\r\n"), count); |
|
343 return count; |
|
344 } |
|
345 |
|
346 //Verifies the integrity of the backup file. |
|
347 void TestArchiveIntegrityL(CSqlBackupClient &aBackupClient, RFs& aFs) |
|
348 { |
|
349 RFile bkpFile; |
|
350 CleanupClosePushL(bkpFile); |
|
351 |
|
352 TInt err = bkpFile.Open(aFs, KBackupFile, EFileRead | EFileShareExclusive); |
|
353 User::LeaveIfError(err); |
|
354 |
|
355 TBuf8<KBufferSize> buf; |
|
356 TPtr8 ptr((TUint8*)buf.Ptr(), buf.MaxLength()); |
|
357 |
|
358 TInt bkpFileSize = 0; |
|
359 err = bkpFile.Size(bkpFileSize); |
|
360 User::LeaveIfError(err); |
|
361 |
|
362 while(bkpFileSize > 0) |
|
363 { |
|
364 // get the checksum |
|
365 err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters |
|
366 User::LeaveIfError(err); |
|
367 if(ptr.Length() != 16) |
|
368 { |
|
369 User::Leave(KErrCorrupt); |
|
370 } |
|
371 TPtr ptr16((TUint16*) ptr.Ptr(), 8, 8); |
|
372 TLex lex(ptr16); |
|
373 TUint32 checksum; |
|
374 lex.SkipSpace(); |
|
375 err = lex.Val(checksum, EHex); |
|
376 User::LeaveIfError(err); |
|
377 bkpFileSize -= 16; |
|
378 |
|
379 // get the old file size |
|
380 err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters |
|
381 User::LeaveIfError(err); |
|
382 if(ptr.Length() != 16) |
|
383 { |
|
384 User::Leave(KErrCorrupt); |
|
385 } |
|
386 ptr16.Set((TUint16*) ptr.Ptr(), 8, 8); |
|
387 lex.Assign(ptr16); |
|
388 TUint32 oldFileSize; |
|
389 lex.SkipSpace(); |
|
390 err = lex.Val(oldFileSize, EHex); |
|
391 User::LeaveIfError(err); |
|
392 bkpFileSize -= 16; |
|
393 |
|
394 // get the backup file header version |
|
395 err = bkpFile.Read(ptr, 8); // 4 UTF-16 characters |
|
396 User::LeaveIfError(err); |
|
397 ptr16.Set((TUint16*)ptr.Ptr(), 4, 4); |
|
398 lex.Assign(ptr16); |
|
399 TUint32 hdrVer; |
|
400 lex.SkipSpace(); |
|
401 err = lex.Val(hdrVer, EHex); |
|
402 User::LeaveIfError(err); |
|
403 bkpFileSize -= 8; |
|
404 |
|
405 // get the file size |
|
406 err = bkpFile.Read(ptr, 32); // 16 UTF-16 characters |
|
407 User::LeaveIfError(err); |
|
408 if(ptr.Length() != 32) |
|
409 { |
|
410 User::Leave(KErrCorrupt); |
|
411 } |
|
412 ptr16.Set((TUint16*) ptr.Ptr(), 16, 16); |
|
413 lex.Assign(ptr16); |
|
414 TInt64 fileSize; |
|
415 lex.SkipSpace(); |
|
416 err = lex.Val(fileSize, EHex); |
|
417 User::LeaveIfError(err); |
|
418 bkpFileSize -= 32; |
|
419 |
|
420 // get the filename size |
|
421 err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters |
|
422 User::LeaveIfError(err); |
|
423 ptr16.Set((TUint16*)ptr.Ptr(), 8, 8); |
|
424 lex.Assign(ptr16); |
|
425 TUint32 fileNameSize; |
|
426 lex.SkipSpace(); |
|
427 err = lex.Val(fileNameSize, EHex); |
|
428 User::LeaveIfError(err); |
|
429 bkpFileSize -= 16; |
|
430 |
|
431 // get the filename |
|
432 err = bkpFile.Read(ptr, fileNameSize * 2); // fileName UTF-16 characters |
|
433 User::LeaveIfError(err); |
|
434 if(ptr.Length() != (fileNameSize * 2)) |
|
435 { |
|
436 User::Leave(KErrCorrupt); |
|
437 } |
|
438 ptr16.Set((TUint16*) ptr.Ptr(), fileNameSize, fileNameSize); |
|
439 lex.Assign(ptr16); |
|
440 TParse tp; |
|
441 tp.Set(ptr16, NULL, NULL); |
|
442 TPtrC dbFileName = tp.Name(); |
|
443 bkpFileSize -= fileNameSize * 2; |
|
444 |
|
445 // open a local file - replaces any previous one |
|
446 RFile64 dbFile; |
|
447 CleanupClosePushL(dbFile); |
|
448 err = dbFile.Replace(aFs, dbFileName, EFileWrite | EFileShareExclusive); |
|
449 User::LeaveIfError(err); |
|
450 |
|
451 // copy all the data (file size bytes) |
|
452 TInt bytesLeftToRead = fileSize; |
|
453 |
|
454 while(bytesLeftToRead > 0) |
|
455 { |
|
456 TInt readSize = bytesLeftToRead > KBufferSize ? KBufferSize : bytesLeftToRead; |
|
457 err = bkpFile.Read(ptr, readSize); |
|
458 User::LeaveIfError(err); |
|
459 if(ptr.Length() != readSize) |
|
460 { |
|
461 User::Leave(KErrCorrupt); |
|
462 } |
|
463 bytesLeftToRead -= readSize; |
|
464 err = dbFile.Write(ptr, readSize); |
|
465 User::LeaveIfError(err); |
|
466 } |
|
467 |
|
468 bkpFileSize -= fileSize; |
|
469 |
|
470 // checksum the file |
|
471 TUint32 dbChecksum = aBackupClient.CheckSumL(dbFile) & 0xFFFFFFFF; |
|
472 |
|
473 if(checksum != dbChecksum) |
|
474 { |
|
475 User::Leave(KErrCorrupt); |
|
476 } |
|
477 |
|
478 // all done with this file |
|
479 CleanupStack::PopAndDestroy(&dbFile); |
|
480 err = aFs.Delete(dbFileName); |
|
481 User::LeaveIfError(err); |
|
482 } |
|
483 |
|
484 CleanupStack::PopAndDestroy(&bkpFile); |
|
485 } |
|
486 |
|
487 /** |
|
488 @SYMTestCaseID SYSLIB-SQL-UT-4002 |
|
489 @SYMTestCaseDesc Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" |
|
490 The test backups 2 test db files, then verifies the backup file integrity, |
|
491 then restores the test db files content from the backup file. |
|
492 At the end, the test checks that the restored test db files content is the |
|
493 same as the content of the original test db file. |
|
494 @SYMTestPriority High |
|
495 @SYMTestActions Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" |
|
496 @SYMTestExpectedResults Test must not fail |
|
497 @SYMDEF DEF113598 |
|
498 */ |
|
499 void FunctionalTest() |
|
500 { |
|
501 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4002 Backup: functional test ")); |
|
502 |
|
503 CSqlBackupClient* backupClient = NULL; |
|
504 TRAPD(err, backupClient = CSqlBackupClient::NewL(TheTestHarness)); |
|
505 TEST(backupClient != NULL); |
|
506 |
|
507 //////////////////////////////////////// |
|
508 |
|
509 const TDriveNumber KDrive = EDriveC; |
|
510 |
|
511 //Virtual functions - with default implementation |
|
512 |
|
513 (void)backupClient->GetExpectedDataSize(KDrive); |
|
514 |
|
515 (void)backupClient->GetDataChecksum(KDrive); |
|
516 |
|
517 TBool finished = EFalse; |
|
518 TPtr8 ptr(0, 0, 0); |
|
519 TRAP(err, backupClient->GetSnapshotDataL(KDrive, ptr, finished)); |
|
520 TEST2(err, KErrNotSupported); |
|
521 |
|
522 TRAP(err, backupClient->InitialiseGetBackupDataL(KDrive)); |
|
523 TEST2(err, KErrNotSupported); |
|
524 |
|
525 TRAP(err, backupClient->InitialiseRestoreBaseDataL(KDrive)); |
|
526 TEST2(err, KErrNotSupported); |
|
527 |
|
528 TRAP(err, backupClient->InitialiseRestoreIncrementDataL(KDrive)); |
|
529 TEST2(err, KErrNotSupported); |
|
530 |
|
531 TPtrC8 ptr2(KNullDesC8); |
|
532 TRAP(err, backupClient->RestoreIncrementDataSectionL(ptr2, finished)); |
|
533 TEST2(err, KErrNotSupported); |
|
534 |
|
535 TRAP(err, backupClient->AllSnapshotsSuppliedL()); |
|
536 TEST2(err, KErrNone); |
|
537 |
|
538 TRAP(err, backupClient->ReceiveSnapshotDataL(KDrive, ptr2, finished)); |
|
539 TEST2(err, KErrNotSupported); |
|
540 |
|
541 backupClient->TerminateMultiStageOperation(); |
|
542 |
|
543 //////////////////////////////////////// |
|
544 |
|
545 TInt bytesStored = 0; |
|
546 TRAP(err, bytesStored = TestBackupL(*backupClient, TheTestHarness->Fs())); |
|
547 TEST2(err, KErrNone); |
|
548 |
|
549 TheTest.Next(_L("Archive integrity test")); |
|
550 |
|
551 TRAP(err, TestArchiveIntegrityL(*backupClient, TheTestHarness->Fs())); |
|
552 TEST2(err, KErrNone); |
|
553 |
|
554 delete backupClient; |
|
555 |
|
556 TheTest.Next(_L("Restore: functional test")); |
|
557 |
|
558 CSqlBackupClient* restoreClient = NULL; |
|
559 TRAP(err, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); |
|
560 TEST(restoreClient != NULL); |
|
561 |
|
562 TInt bytesRestored = 0; |
|
563 TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs())); |
|
564 TEST2(err, KErrNone); |
|
565 |
|
566 TEST(bytesRestored == bytesStored); |
|
567 |
|
568 delete restoreClient; |
|
569 |
|
570 CompareDbContentWithBuf(TheTestHarness->Fs()); |
|
571 } |
|
572 |
|
573 TInt DoBackupL() |
|
574 { |
|
575 CSqlBackupClient* backupClient = CSqlBackupClient::NewLC(TheTestHarness); |
|
576 TInt bytesStored = TestBackupL(*backupClient, TheTestHarness->Fs()); |
|
577 CleanupStack::PopAndDestroy(backupClient); |
|
578 return bytesStored; |
|
579 } |
|
580 |
|
581 TInt DoRestoreL() |
|
582 { |
|
583 CSqlBackupClient* restoreClient = CSqlBackupClient::NewLC(TheTestHarness); |
|
584 TInt bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs()); |
|
585 CleanupStack::PopAndDestroy(restoreClient); |
|
586 return bytesRestored; |
|
587 } |
|
588 |
|
589 /** |
|
590 @SYMTestCaseID SYSLIB-SQL-UT-4003 |
|
591 @SYMTestCaseDesc Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" |
|
592 Under simulated OOM condition, the test backups 2 test db files, |
|
593 then restores the test db files content from the backup file. |
|
594 At the end, the test checks that the restored test db files content is the |
|
595 same as the content of the original test db file. |
|
596 @SYMTestPriority High |
|
597 @SYMTestActions Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" |
|
598 @SYMTestExpectedResults Test must not fail |
|
599 @SYMDEF DEF113598 |
|
600 */ |
|
601 void OomTest() |
|
602 { |
|
603 /////////////////////////////////////////////////////////////////////////////// |
|
604 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4003 Backup: OOM test ")); |
|
605 TInt err = KErrNoMemory; |
|
606 TInt bytesStored = 0; |
|
607 TInt count = 0; |
|
608 |
|
609 for(count=1;err==KErrNoMemory;++count) |
|
610 { |
|
611 TInt startProcessHandleCount; |
|
612 TInt startThreadHandleCount; |
|
613 RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); |
|
614 |
|
615 User::__DbgMarkStart(RHeap::EUser); |
|
616 User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext, count); |
|
617 TRAP(err, bytesStored = DoBackupL()); |
|
618 User::__DbgMarkEnd(RHeap::EUser, 0); |
|
619 |
|
620 TInt endProcessHandleCount; |
|
621 TInt endThreadHandleCount; |
|
622 RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); |
|
623 |
|
624 TEST(startProcessHandleCount == endProcessHandleCount); |
|
625 TEST(startThreadHandleCount == endThreadHandleCount); |
|
626 } |
|
627 TEST2(err, KErrNone); |
|
628 TheTest.Printf(_L("OOM backup test succeeded at heap failure rate of %d\r\n"), count); |
|
629 |
|
630 /////////////////////////////////////////////////////////////////////////////// |
|
631 TheTest.Next(_L("Restore: OOM test")); |
|
632 err = KErrNoMemory; |
|
633 TInt bytesRestored = 0; |
|
634 |
|
635 for(count=1;err==KErrNoMemory;++count) |
|
636 { |
|
637 TInt startProcessHandleCount; |
|
638 TInt startThreadHandleCount; |
|
639 RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); |
|
640 |
|
641 User::__DbgMarkStart(RHeap::EUser); |
|
642 User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext, count); |
|
643 TRAP(err, bytesRestored = DoRestoreL()); |
|
644 User::__DbgMarkEnd(RHeap::EUser, 0); |
|
645 |
|
646 TInt endProcessHandleCount; |
|
647 TInt endThreadHandleCount; |
|
648 RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); |
|
649 |
|
650 TEST(startProcessHandleCount == endProcessHandleCount); |
|
651 TEST(startThreadHandleCount == endThreadHandleCount); |
|
652 } |
|
653 TEST2(err, KErrNone); |
|
654 User::__DbgSetAllocFail(RHeap::EUser, RAllocator::ENone, 0); |
|
655 TheTest.Printf(_L("OOM restore test succeeded at heap failure rate of %d\r\n"), count); |
|
656 |
|
657 TEST(bytesStored == bytesRestored); |
|
658 |
|
659 CompareDbContentWithBuf(TheTestHarness->Fs()); |
|
660 } |
|
661 |
|
662 /** |
|
663 @SYMTestCaseID PDS-SQL-UT-4143 |
|
664 @SYMTestCaseDesc SQL Backup&Restore - data chunk size test. |
|
665 The test uses an integer array of 10 elements with randomly generated data chunk sizes. |
|
666 Then the test runs 10 backup iterations using each time different data chunk size. |
|
667 After each backup iteration the test performs a restore operation and checks that the |
|
668 data has been backup&restored without errors. |
|
669 @SYMTestActions SQL Backup&Restore - data chunk size test. |
|
670 @SYMTestExpectedResults Test must not fail |
|
671 @SYMTestPriority Medium |
|
672 @SYMREQ REQ12104 |
|
673 */ |
|
674 void FunctionalTest2() |
|
675 { |
|
676 TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4143 Backup&Restore: functional test 2")); |
|
677 |
|
678 TTime now; |
|
679 now.UniversalTime(); |
|
680 TInt64 seed = now.Int64(); |
|
681 |
|
682 const TInt KArraySize = 10; |
|
683 TInt dataChunks[10] = {2, 6, 0, 0, 0, 0, 0, 0, 0, 0}; |
|
684 const TInt KMaxDataChunkSize = 50; |
|
685 |
|
686 for(TInt i=2;i<KArraySize;) |
|
687 { |
|
688 TInt dataChunkSize = Math::Rand(seed) % KMaxDataChunkSize; |
|
689 if((dataChunkSize % 2) == 0 && dataChunkSize != 0) //The code works only with data chunks with even sizes!!! |
|
690 { |
|
691 dataChunks[i++] = dataChunkSize; |
|
692 } |
|
693 } |
|
694 |
|
695 for(TInt i=0;i<KArraySize;++i) |
|
696 { |
|
697 TheTest.Printf(_L(" === Iteration %d, chunk size %d\r\n"), i + 1, dataChunks[i]); |
|
698 CSqlBackupClient* backupClient = NULL; |
|
699 TRAPD(err, backupClient = CSqlBackupClient::NewL(TheTestHarness)); |
|
700 TEST(backupClient != NULL); |
|
701 |
|
702 TInt bytesStored = 0; |
|
703 TRAP(err, bytesStored = TestBackupL(*backupClient, TheTestHarness->Fs(), dataChunks[i])); |
|
704 TEST2(err, KErrNone); |
|
705 |
|
706 TRAP(err, TestArchiveIntegrityL(*backupClient, TheTestHarness->Fs())); |
|
707 TEST2(err, KErrNone); |
|
708 |
|
709 delete backupClient; |
|
710 |
|
711 CSqlBackupClient* restoreClient = NULL; |
|
712 TRAP(err, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); |
|
713 TEST(restoreClient != NULL); |
|
714 |
|
715 TInt bytesRestored = 0; |
|
716 TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs(), dataChunks[i])); |
|
717 TEST2(err, KErrNone); |
|
718 |
|
719 TEST(bytesRestored == bytesStored); |
|
720 |
|
721 delete restoreClient; |
|
722 |
|
723 CompareDbContentWithBuf(TheTestHarness->Fs()); |
|
724 } |
|
725 } |
|
726 |
|
727 /** |
|
728 @SYMTestCaseID PDS-SQL-UT-4144 |
|
729 @SYMTestCaseDesc SQL Backup&Restore - legacy backup file format header test. |
|
730 The 64-bit file system related changes made in the SQL server required some |
|
731 changes to be made in the format of the backup file header. |
|
732 The test checks that a backup file created with the previous format of the file header |
|
733 can be restored without errors by the updated Backup&Restore implementation. |
|
734 @SYMTestActions SQL Backup&Restore - legacy backup file format header test. |
|
735 @SYMTestExpectedResults Test must not fail |
|
736 @SYMTestPriority Medium |
|
737 @SYMREQ REQ12104 |
|
738 */ |
|
739 void LegacyFileFormatTest() |
|
740 { |
|
741 TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4144 Backup&Restore: legacy file format test")); |
|
742 |
|
743 //KBackupFile2 is a database backup file with header version 0. |
|
744 (void)TheTestHarness->Fs().Delete(KBackupFile2); |
|
745 TInt rc = BaflUtils::CopyFile(TheTestHarness->Fs(), KBackupFile2Z, KBackupFile2); |
|
746 TEST2(rc, KErrNone); |
|
747 (void)TheTestHarness->Fs().SetAtt(KBackupFile2, 0, KEntryAttReadOnly); |
|
748 |
|
749 //Restore the databases from KBackupFile2. |
|
750 CSqlBackupClient* restoreClient = NULL; |
|
751 TRAP(rc, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); |
|
752 TEST(restoreClient != NULL); |
|
753 |
|
754 RFile file; |
|
755 rc = file.Open(TheTestHarness->Fs(), KBackupFile2, EFileRead | EFileShareExclusive); |
|
756 TEST2(rc, KErrNone); |
|
757 |
|
758 TRAP(rc, restoreClient->InitialiseRestoreProxyBaseDataL(KClientUid, EDriveC)); |
|
759 TEST2(rc, KErrNone); |
|
760 |
|
761 TBuf8<KBufferSize> buf; |
|
762 TPtr8 ptr((TUint8*)buf.Ptr(), buf.MaxSize()); |
|
763 TBool finishedFlag = EFalse; |
|
764 |
|
765 TInt fileSize = 0; |
|
766 rc = file.Size(fileSize); |
|
767 TEST2(rc, KErrNone); |
|
768 |
|
769 do |
|
770 { |
|
771 rc = file.Read(ptr); |
|
772 TEST2(rc, KErrNone); |
|
773 fileSize -= ptr.Size(); |
|
774 finishedFlag = fileSize == 0; |
|
775 TRAP(rc, restoreClient->RestoreBaseDataSectionL(ptr, finishedFlag)); |
|
776 ptr.SetLength(0); |
|
777 } |
|
778 while(fileSize > 0); |
|
779 |
|
780 file.Close(); |
|
781 |
|
782 restoreClient->RestoreComplete(EDriveC); |
|
783 |
|
784 TEST(finishedFlag); |
|
785 |
|
786 delete restoreClient; |
|
787 |
|
788 //At this point we have two restored databases: KTestDbFileName1 and KTestDbFileName2. |
|
789 //The content of the restored file cannot be compared directly, because t_sqlattach uses the same test databases |
|
790 //and modifies them. The original database content was stored without executing t_sqlattach. |
|
791 //Hence a simple test is made: open the restored database, check if the database content can be accessed. |
|
792 |
|
793 RSqlDatabase db; |
|
794 rc = db.Open(KTestDbFileName1); |
|
795 TEST2(rc, KErrNone); |
|
796 //The database contains this table: "TABLE C(A1 INTEGER, B2 BLOB)". |
|
797 rc = db.Exec(_L("INSERT INTO C VALUES(100, 200)")); |
|
798 TEST2(rc, 1); |
|
799 RSqlStatement stmt; |
|
800 rc = stmt.Prepare(db, _L("SELECT * FROM C")); |
|
801 TEST2(rc, KErrNone); |
|
802 while((rc = stmt.Next()) == KSqlAtRow) |
|
803 { |
|
804 } |
|
805 stmt.Close(); |
|
806 TEST2(rc, KSqlAtEnd); |
|
807 db.Close(); |
|
808 |
|
809 rc = db.Open(KTestDbFileName2); |
|
810 TEST2(rc, KErrNone); |
|
811 //The database contains this table: "TABLE A1(F1 INTEGER , F2 INTEGER, B1 BLOB)" |
|
812 rc = db.Exec(_L("INSERT INTO A1 VALUES(100, 200, NULL)")); |
|
813 TEST2(rc, 1); |
|
814 rc = stmt.Prepare(db, _L("SELECT * FROM A1")); |
|
815 TEST2(rc, KErrNone); |
|
816 while((rc = stmt.Next()) == KSqlAtRow) |
|
817 { |
|
818 } |
|
819 stmt.Close(); |
|
820 TEST2(rc, KSqlAtEnd); |
|
821 db.Close(); |
|
822 |
|
823 (void)TheTestHarness->Fs().Delete(KBackupFile2); |
|
824 } |
|
825 |
|
826 void DoMain() |
|
827 { |
|
828 TestEnvCreate(); |
|
829 |
|
830 TheTest.Start(_L("Store db content to memory buffer")); |
|
831 StoreDbContentToBuf(TheTestHarness->Fs()); |
|
832 |
|
833 FunctionalTest(); |
|
834 |
|
835 OomTest(); |
|
836 |
|
837 FunctionalTest2(); |
|
838 |
|
839 LegacyFileFormatTest(); |
|
840 |
|
841 TestEnvDestroy(); |
|
842 } |
|
843 |
|
844 TInt E32Main() |
|
845 { |
|
846 TheTest.Title(); |
|
847 |
|
848 CTrapCleanup* tc = CTrapCleanup::New(); |
|
849 TEST(tc != NULL); |
|
850 |
|
851 __UHEAP_MARK; |
|
852 |
|
853 DoMain(); |
|
854 |
|
855 __UHEAP_MARKEND; |
|
856 |
|
857 TheTest.End(); |
|
858 TheTest.Close(); |
|
859 |
|
860 delete tc; |
|
861 |
|
862 User::Heap().Check(); |
|
863 return KErrNone; |
|
864 } |