|
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 |
|
20 /////////////////////////////////////////////////////////////////////////////////////// |
|
21 |
|
22 RTest TheTest(_L("t_sqlmulti test")); |
|
23 |
|
24 _LIT(KTestDir, "c:\\test\\"); |
|
25 _LIT(KTestDbName1, "c:\\test\\t_sqlmulti.db"); |
|
26 |
|
27 /////////////////////////////////////////////////////////////////////////////////////// |
|
28 |
|
29 void DeleteTestFiles() |
|
30 { |
|
31 RSqlDatabase::Delete(KTestDbName1); |
|
32 } |
|
33 |
|
34 /////////////////////////////////////////////////////////////////////////////////////// |
|
35 /////////////////////////////////////////////////////////////////////////////////////// |
|
36 //Test macros and functions |
|
37 void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse) |
|
38 { |
|
39 if(!aValue) |
|
40 { |
|
41 DeleteTestFiles(); |
|
42 if(aPrintThreadName) |
|
43 { |
|
44 RThread th; |
|
45 TName name = th.Name(); |
|
46 RDebug::Print(_L("*** Thread %S, Line %d\r\n"), &name, aLine); |
|
47 } |
|
48 else |
|
49 { |
|
50 RDebug::Print(_L("*** Line %d\r\n"), aLine); |
|
51 } |
|
52 TheTest(EFalse, aLine); |
|
53 } |
|
54 } |
|
55 void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse) |
|
56 { |
|
57 if(aValue != aExpected) |
|
58 { |
|
59 DeleteTestFiles(); |
|
60 if(aPrintThreadName) |
|
61 { |
|
62 RThread th; |
|
63 TName name = th.Name(); |
|
64 RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue); |
|
65 } |
|
66 else |
|
67 { |
|
68 RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue); |
|
69 } |
|
70 TheTest(EFalse, aLine); |
|
71 } |
|
72 } |
|
73 #define TEST(arg) ::Check1((arg), __LINE__) |
|
74 #define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__) |
|
75 #define TTEST(arg) ::Check1((arg), __LINE__, ETrue) |
|
76 #define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue) |
|
77 |
|
78 /////////////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
80 void CreateTestDir() |
|
81 { |
|
82 RFs fs; |
|
83 TInt err = fs.Connect(); |
|
84 TEST2(err, KErrNone); |
|
85 |
|
86 err = fs.MkDir(KTestDir); |
|
87 TEST(err == KErrNone || err == KErrAlreadyExists); |
|
88 |
|
89 fs.Close(); |
|
90 } |
|
91 |
|
92 /////////////////////////////////////////////////////////////////////////////////////// |
|
93 |
|
94 /** |
|
95 @SYMTestCaseID SYSLIB-SQL-CT-1612 |
|
96 @SYMTestCaseDesc Two connections to the same database in the same thread. Create a test database |
|
97 and insert some records from both connections. Verify that all records were inserted |
|
98 successfully. |
|
99 @SYMTestPriority High |
|
100 @SYMTestActions Testing SQL engine behaviour when having mutiple connections to the same database |
|
101 in the same thread. |
|
102 @SYMTestExpectedResults Test must not fail |
|
103 @SYMREQ REQ5792 |
|
104 REQ5793 |
|
105 */ |
|
106 void TestMultiConnSameThread() |
|
107 { |
|
108 //Connection 1 |
|
109 RSqlDatabase db1; |
|
110 TInt err = db1.Create(KTestDbName1); |
|
111 TEST2(err, KErrNone); |
|
112 |
|
113 //Create test database |
|
114 RDebug::Print(_L("###Create test database\r\n")); |
|
115 _LIT8(KCreateSql, "CREATE TABLE A(Id INTEGER PRIMARY KEY AUTOINCREMENT, Data INTEGER)"); |
|
116 err = db1.Exec(KCreateSql); |
|
117 TEST(err >= 0); |
|
118 |
|
119 //Connection 2 |
|
120 RSqlDatabase db2; |
|
121 err = db2.Open(KTestDbName1); |
|
122 TEST2(err, KErrNone); |
|
123 |
|
124 //Insert some records using both connections |
|
125 RDebug::Print(_L("###Insert some records\r\n")); |
|
126 const TInt KRecNum = 100; |
|
127 _LIT8(KInsertSql, "INSERT INTO A(Data) VALUES("); |
|
128 for(TInt i=0;i<KRecNum;++i) |
|
129 { |
|
130 TBuf8<100> sql(KInsertSql); |
|
131 sql.AppendNum((TInt64)i + 1); |
|
132 sql.Append(_L(");")); |
|
133 err = (i%2) ? db1.Exec(sql) : db2.Exec(sql); |
|
134 if(err < 0) |
|
135 { |
|
136 TPtrC msg = (i%2) ? db1.LastErrorMessage() : db2.LastErrorMessage(); |
|
137 RDebug::Print(_L("##Db Error msg: \"%S\"\n\r"), &msg); |
|
138 } |
|
139 TEST2(err, 1); |
|
140 } |
|
141 |
|
142 //Check the database content |
|
143 RDebug::Print(_L("###Check the database content\r\n")); |
|
144 _LIT8(KSelectSql, "SELECT * FROM A"); |
|
145 RSqlStatement stmt; |
|
146 err = stmt.Prepare(db1, KSelectSql); |
|
147 TEST2(err, KErrNone); |
|
148 |
|
149 for(TInt j=0;j<KRecNum;++j) |
|
150 { |
|
151 err = stmt.Next(); |
|
152 TEST2(err, KSqlAtRow); |
|
153 TEST(stmt.AtRow()); |
|
154 TInt id = stmt.ColumnInt(0); |
|
155 TInt data = stmt.ColumnInt(1); |
|
156 TEST(id == data); |
|
157 } |
|
158 |
|
159 stmt.Close(); |
|
160 |
|
161 //Cleanup |
|
162 db2.Close(); |
|
163 db1.Close(); |
|
164 RDebug::Print(_L("###Delete the test database\r\n")); |
|
165 (void)RSqlDatabase::Delete(KTestDbName1); |
|
166 } |
|
167 |
|
168 /////////////////////////////////////////////////////////////////////////////////////// |
|
169 |
|
170 struct TThreadData |
|
171 { |
|
172 TInt iTransType; |
|
173 RSqlDatabase::TIsolationLevel iIsolationLevel; |
|
174 TInt iLowRecNo; |
|
175 TInt iHighRecNo; |
|
176 }; |
|
177 |
|
178 TInt ThreadFunc(void* aData) |
|
179 { |
|
180 __UHEAP_MARK; |
|
181 |
|
182 CTrapCleanup* tc = CTrapCleanup::New(); |
|
183 TTEST(tc != NULL); |
|
184 |
|
185 TThreadData* data = static_cast<TThreadData*> (aData); |
|
186 TTEST(data != NULL); |
|
187 |
|
188 RSqlDatabase db; |
|
189 TInt err = db.Open(KTestDbName1); |
|
190 TTEST2(err, KErrNone); |
|
191 |
|
192 err = db.SetIsolationLevel(data->iIsolationLevel); |
|
193 TTEST2(err, KErrNone); |
|
194 |
|
195 if(data->iTransType == 1) |
|
196 { |
|
197 _LIT8(KBeginTrans, "BEGIN"); |
|
198 err = db.Exec(KBeginTrans); |
|
199 TTEST(err >= 0); |
|
200 } |
|
201 |
|
202 _LIT8(KInsertSql, "INSERT INTO A(Id) VALUES("); |
|
203 for(TInt id=data->iLowRecNo;id<=data->iHighRecNo;++id) |
|
204 { |
|
205 TBuf8<128> sql(KInsertSql); |
|
206 sql.AppendNum((TInt64)id); |
|
207 sql.Append(_L(")")); |
|
208 err = KSqlErrBusy; |
|
209 const TInt KAttempts = 20; |
|
210 for(TInt i=0;i<KAttempts&&err==KSqlErrBusy;++i) |
|
211 { |
|
212 err = db.Exec(sql); |
|
213 if(err == KSqlErrBusy) |
|
214 { |
|
215 RThread th; |
|
216 TName name = th.Name(); |
|
217 RDebug::Print(_L("!!!Database locked, Thread: %S, Attempt %d, column value %d\r\n"), &name, i + 1, id); |
|
218 User::After(1000000); |
|
219 } |
|
220 } |
|
221 TTEST2(err, 1); |
|
222 } |
|
223 |
|
224 if(data->iTransType == 1) |
|
225 { |
|
226 _LIT8(KCommitTrans, "COMMIT"); |
|
227 err = db.Exec(KCommitTrans); |
|
228 TTEST(err >= 0); |
|
229 } |
|
230 |
|
231 db.Close(); |
|
232 delete tc; |
|
233 |
|
234 __UHEAP_MARKEND; |
|
235 |
|
236 return KErrNone; |
|
237 } |
|
238 |
|
239 /** |
|
240 @SYMTestCaseID SYSLIB-SQL-CT-1613 |
|
241 @SYMTestCaseDesc Multiple connections to the same database from different threads. |
|
242 Each thread inserts set of record to the same table. Verify that all expected records |
|
243 and their column values meet the expectations. |
|
244 @SYMTestPriority High |
|
245 @SYMTestActions Testing SQL engine behaviour when having mutiple connections to the same database |
|
246 from different threads. |
|
247 @SYMTestExpectedResults Test must not fail |
|
248 @SYMREQ REQ5792 |
|
249 REQ5793 |
|
250 */ |
|
251 void TestMultiConnDiffThread() |
|
252 { |
|
253 //Create a test database |
|
254 RDebug::Print(_L("+++:MainThread: Create test database\r\n")); |
|
255 RSqlDatabase db; |
|
256 TInt err = db.Create(KTestDbName1); |
|
257 TEST2(err, KErrNone); |
|
258 |
|
259 //Create a test table |
|
260 RDebug::Print(_L("+++:MainThread: Create a table in the test database\r\n")); |
|
261 _LIT8(KCreateSql, "CREATE TABLE A(Id INTEGER PRIMARY KEY)"); |
|
262 err = db.Exec(KCreateSql); |
|
263 TEST(err >= 0); |
|
264 |
|
265 const TInt KThreadCnt = 4; |
|
266 const TInt KRange = 100; |
|
267 |
|
268 const TInt KIsolationLevelCnt = 2; |
|
269 TPtrC KIsolationLevelName[KIsolationLevelCnt] = {_L("Read Uncommitted"), _L("Serializable")}; |
|
270 const RSqlDatabase::TIsolationLevel KIsolationLevels[KIsolationLevelCnt] = { |
|
271 RSqlDatabase::EReadUncommitted, RSqlDatabase::ESerializable}; |
|
272 |
|
273 const TInt KTransTypeCnt = 2; |
|
274 |
|
275 //Do the tests: |
|
276 // - doing each per thread database operation in a single transaction; |
|
277 // - doing all per thread database operations in a single transaction; |
|
278 for(TInt transType=0;transType<KTransTypeCnt;++transType) |
|
279 { |
|
280 //For both supported isolation levels: read uncommitted and serializable |
|
281 for(TInt isolLevel=0;isolLevel<KIsolationLevelCnt;++isolLevel) |
|
282 { |
|
283 TInt low = 1; |
|
284 TInt high = KRange; |
|
285 |
|
286 RDebug::Print(_L("+++:MainThread: Test: thread count %d, records %d, trans type %d, isolation level: %S\r\n"), |
|
287 KThreadCnt, KRange, transType, &KIsolationLevelName[isolLevel]); |
|
288 |
|
289 RThread thread[KThreadCnt]; |
|
290 TRequestStatus status[KThreadCnt]; |
|
291 TThreadData data[KThreadCnt]; |
|
292 |
|
293 //Create the test threads and run them. Each thread establishes a connection with the test database |
|
294 //and attempts to write set of records in the test table. |
|
295 TInt j; |
|
296 for(j=0;j<KThreadCnt;++j,low=high+1,high+=KRange) |
|
297 { |
|
298 data[j].iTransType = transType; |
|
299 data[j].iIsolationLevel = KIsolationLevels[isolLevel]; |
|
300 data[j].iLowRecNo = low; |
|
301 data[j].iHighRecNo = high; |
|
302 |
|
303 _LIT(KThreadName,"Thr-"); |
|
304 TBuf<32> threadName(KThreadName); |
|
305 threadName.AppendNum((TInt64)j + 1); |
|
306 |
|
307 TEST2(thread[j].Create(threadName, &ThreadFunc, 0x2000, 0x1000, 0x10000, (void*)&data[j], EOwnerThread), KErrNone); |
|
308 thread[j].Logon(status[j]); |
|
309 TEST2(status[j].Int(), KRequestPending); |
|
310 thread[j].Resume(); |
|
311 } |
|
312 |
|
313 User::After(2000000); |
|
314 //Wait until threads finish the database operations and close them. |
|
315 for(j=0;j<KThreadCnt;++j) |
|
316 { |
|
317 User::WaitForRequest(status[j]); |
|
318 TEST(thread[j].ExitType() != EExitPanic); |
|
319 thread[j].Close(); |
|
320 } |
|
321 |
|
322 //Check that all records which are esupposed to be in the database, are there. |
|
323 RDebug::Print(_L("+++:MainThread: Check that all records have been written\r\n")); |
|
324 _LIT8(KSelectSql1, "SELECT COUNT(*) FROM A;"); |
|
325 RSqlStatement stmt; |
|
326 err = stmt.Prepare(db, KSelectSql1); |
|
327 TEST2(err, KErrNone); |
|
328 err = stmt.Next(); |
|
329 TEST2(err, KSqlAtRow); |
|
330 TInt cnt = stmt.ColumnInt(0); |
|
331 TEST2(cnt, KThreadCnt * KRange); |
|
332 stmt.Close(); |
|
333 |
|
334 //Check that all records have expected column values. |
|
335 RDebug::Print(_L("+++:MainThread: Check that all records have expected column values\r\n")); |
|
336 _LIT8(KSelectSql2, "SELECT * FROM A;"); |
|
337 err = stmt.Prepare(db, KSelectSql2); |
|
338 TEST2(err, KErrNone); |
|
339 for(TInt k=0;k<(KThreadCnt*KRange);++k) |
|
340 { |
|
341 err = stmt.Next(); |
|
342 TEST2(err, KSqlAtRow); |
|
343 TInt val = stmt.ColumnInt(0); |
|
344 TEST(val > 0 && val <= (KThreadCnt * KRange)); |
|
345 } |
|
346 stmt.Close(); |
|
347 |
|
348 //Prepare for the next test run - delete all records. |
|
349 RDebug::Print(_L("+++:MainThread: Delete all records\r\n")); |
|
350 _LIT8(KDeleteSql, "DELETE FROM A"); |
|
351 err = db.Exec(KDeleteSql); |
|
352 TEST(err >= 0); |
|
353 }//end of "for(TInt isolLevel=0;isolLevel<KIsolationLevelCnt;++isolLevel)" |
|
354 }//end of "for(TInt transType=0;transType<KTransTypeCnt;++transType)" |
|
355 |
|
356 db.Close(); |
|
357 RDebug::Print(_L("+++:MainThread: Delete the test database\r\n")); |
|
358 (void)RSqlDatabase::Delete(KTestDbName1); |
|
359 } |
|
360 |
|
361 /////////////////////////////////////////////////////////////////////////////////////// |
|
362 |
|
363 static RCriticalSection UpdateThreadCrS; |
|
364 static RCriticalSection MainThreadCrS; |
|
365 const TInt KInitialValue = 10; |
|
366 const TInt KUpdatedValue = 20; |
|
367 |
|
368 TInt UpdateThreadFunc(void*) |
|
369 { |
|
370 __UHEAP_MARK; |
|
371 |
|
372 CTrapCleanup* tc = CTrapCleanup::New(); |
|
373 TTEST(tc != NULL); |
|
374 |
|
375 RSqlDatabase db; |
|
376 TInt err = db.Open(KTestDbName1); |
|
377 TTEST2(err, KErrNone); |
|
378 |
|
379 RDebug::Print(_L("---:UpdThread: Set the isolation level to \"Read uncommitted\"\r\n")); |
|
380 err = db.SetIsolationLevel(RSqlDatabase::EReadUncommitted); |
|
381 TTEST2(err, KErrNone); |
|
382 |
|
383 RDebug::Print(_L("---:UpdThread: Begin a write transaction\r\n")); |
|
384 _LIT8(KBeginTransSql, "BEGIN IMMEDIATE TRANSACTION"); |
|
385 err = db.Exec(KBeginTransSql); |
|
386 TTEST(err >= 0); |
|
387 |
|
388 RDebug::Print(_L("---:UpdThread: Update the record\r\n")); |
|
389 _LIT8(KUpdateSql, "UPDATE A SET Id = "); |
|
390 TBuf8<64> sql(KUpdateSql); |
|
391 sql.AppendNum((TInt64)KUpdatedValue); |
|
392 err = db.Exec(sql); |
|
393 TTEST(err >= 0); |
|
394 |
|
395 RDebug::Print(_L("---:UpdThread: Notify the main thread about the update\r\n")); |
|
396 MainThreadCrS.Signal(); |
|
397 |
|
398 RDebug::Print(_L("---:UpdThread: Wait for permisson to continue...\r\n")); |
|
399 UpdateThreadCrS.Wait(); |
|
400 |
|
401 RDebug::Print(_L("---:UpdThread: Rollback the update\r\n")); |
|
402 _LIT8(KRollBackTransSql, "ROLLBACK TRANSACTION"); |
|
403 err = db.Exec(KRollBackTransSql); |
|
404 TTEST(err >= 0); |
|
405 |
|
406 RDebug::Print(_L("---:UpdThread: Notify the main thread about the rollback\r\n")); |
|
407 MainThreadCrS.Signal(); |
|
408 |
|
409 db.Close(); |
|
410 delete tc; |
|
411 |
|
412 __UHEAP_MARKEND; |
|
413 |
|
414 return KErrNone; |
|
415 } |
|
416 |
|
417 /** |
|
418 @SYMTestCaseID SYSLIB-SQL-CT-1614 |
|
419 @SYMTestCaseDesc Verifying that when having 2 database connections in different threads, both set |
|
420 the isolation level to "Read Uncommitted", the reading thread can make "dirty read" |
|
421 operations (can read the updated but not committed yet record values made by the |
|
422 writing thread). |
|
423 @SYMTestPriority High |
|
424 @SYMTestActions Testing "Read Uncommitted" database isolation level. |
|
425 @SYMTestExpectedResults Test must not fail |
|
426 @SYMREQ REQ5792 |
|
427 REQ5793 |
|
428 */ |
|
429 void TestIsolationLevel() |
|
430 { |
|
431 RDebug::Print(_L("+++:MainThread: Create critical sections\r\n")); |
|
432 TEST2(UpdateThreadCrS.CreateLocal(), KErrNone); |
|
433 UpdateThreadCrS.Wait(); |
|
434 TEST2(MainThreadCrS.CreateLocal(), KErrNone); |
|
435 MainThreadCrS.Wait(); |
|
436 |
|
437 RDebug::Print(_L("+++:MainThread: Create test database\r\n")); |
|
438 RSqlDatabase db; |
|
439 TInt err = db.Create(KTestDbName1); |
|
440 TEST2(err, KErrNone); |
|
441 |
|
442 RDebug::Print(_L("+++:MainThread: Set the isolation level to \"Read uncommitted\"\r\n")); |
|
443 err = db.SetIsolationLevel(RSqlDatabase::EReadUncommitted); |
|
444 TEST2(err, KErrNone); |
|
445 |
|
446 RDebug::Print(_L("+++:MainThread: Create a table in the test database\r\n")); |
|
447 _LIT8(KCreateSql, "CREATE TABLE A(Id INTEGER)"); |
|
448 err = db.Exec(KCreateSql); |
|
449 TEST(err >= 0); |
|
450 |
|
451 RDebug::Print(_L("+++:MainThread: Insert one record in the table\r\n")); |
|
452 _LIT8(KInsertSql, "INSERT INTO A(Id) VALUES("); |
|
453 TBuf8<64> sql(KInsertSql); |
|
454 sql.AppendNum((TInt64)KInitialValue); |
|
455 sql.Append(_L(")")); |
|
456 err = db.Exec(sql); |
|
457 TEST2(err, 1); |
|
458 |
|
459 RDebug::Print(_L("+++:MainThread: Create the \"update\" thread\r\n")); |
|
460 _LIT(KThreadName, "UpdTh"); |
|
461 RThread thread; |
|
462 TEST2(thread.Create(KThreadName, &UpdateThreadFunc, 0x2000, 0x1000, 0x10000, NULL, EOwnerThread), KErrNone); |
|
463 TRequestStatus status; |
|
464 thread.Logon(status); |
|
465 TEST2(status.Int(), KRequestPending); |
|
466 thread.Resume(); |
|
467 |
|
468 RDebug::Print(_L("+++:MainThread: Wait for record update completion...\r\n")); |
|
469 MainThreadCrS.Wait(); |
|
470 |
|
471 RDebug::Print(_L("+++:MainThread: Read the record and check the data...\r\n")); |
|
472 _LIT8(KSelectSql, "SELECT * FROM A"); |
|
473 RSqlStatement stmt; |
|
474 err = stmt.Prepare(db, KSelectSql); |
|
475 TEST2(err, KErrNone); |
|
476 err = stmt.Next(); |
|
477 TEST2(err, KSqlAtRow); |
|
478 TInt val = stmt.ColumnInt(0); |
|
479 TEST(val == KUpdatedValue); |
|
480 stmt.Close(); |
|
481 |
|
482 RDebug::Print(_L("+++:MainThread: Notify the update thread that it can rollback\r\n")); |
|
483 UpdateThreadCrS.Signal(); |
|
484 |
|
485 RDebug::Print(_L("+++:MainThread: Wait for rollback completion...\r\n")); |
|
486 MainThreadCrS.Wait(); |
|
487 |
|
488 RDebug::Print(_L("+++:MainThread: Read the record and check the data...\r\n")); |
|
489 err = stmt.Prepare(db, KSelectSql); |
|
490 TEST2(err, KErrNone); |
|
491 err = stmt.Next(); |
|
492 TEST2(err, KSqlAtRow); |
|
493 val = stmt.ColumnInt(0); |
|
494 TEST2(val, KInitialValue); |
|
495 stmt.Close(); |
|
496 |
|
497 User::WaitForRequest(status); |
|
498 thread.Close(); |
|
499 |
|
500 db.Close(); |
|
501 RDebug::Print(_L("+++:MainThread: Delete the test database\r\n")); |
|
502 (void)RSqlDatabase::Delete(KTestDbName1); |
|
503 |
|
504 RDebug::Print(_L("+++:MainThread: Close critical sections\r\n")); |
|
505 MainThreadCrS.Close(); |
|
506 UpdateThreadCrS.Close(); |
|
507 } |
|
508 |
|
509 /////////////////////////////////////////////////////////////////////////////////////// |
|
510 |
|
511 void DoTestsL() |
|
512 { |
|
513 TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1612 Multiple connections, the same thread ")); |
|
514 TestMultiConnSameThread(); |
|
515 |
|
516 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1613 Multiple connections, different threads ")); |
|
517 TestMultiConnDiffThread(); |
|
518 |
|
519 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1614 Isolation level ")); |
|
520 TestIsolationLevel(); |
|
521 } |
|
522 |
|
523 TInt E32Main() |
|
524 { |
|
525 TheTest.Title(); |
|
526 |
|
527 CTrapCleanup* tc = CTrapCleanup::New(); |
|
528 |
|
529 __UHEAP_MARK; |
|
530 |
|
531 CreateTestDir(); |
|
532 DeleteTestFiles(); |
|
533 TRAPD(err, DoTestsL()); |
|
534 DeleteTestFiles(); |
|
535 TEST2(err, KErrNone); |
|
536 |
|
537 __UHEAP_MARKEND; |
|
538 |
|
539 TheTest.End(); |
|
540 TheTest.Close(); |
|
541 |
|
542 delete tc; |
|
543 |
|
544 User::Heap().Check(); |
|
545 return KErrNone; |
|
546 } |