|
1 // Copyright (c) 2007-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 <e32debug.h> |
|
17 #include <e32test.h> |
|
18 #include <f32file.h> |
|
19 #include "sqlite3.h" |
|
20 #include <stdlib.h> |
|
21 #include "SqliteSymbian.h" |
|
22 #include "SqlAssert.h" |
|
23 |
|
24 /////////////////////////////////////////////////////////////////////////////////////// |
|
25 |
|
26 RTest TheTest(_L("t_SqlGetFirstStmt test")); |
|
27 RFs TheFs; |
|
28 sqlite3* TheSqliteDb; |
|
29 |
|
30 _LIT(KTestDir, "c:\\test\\"); |
|
31 _LIT(KTestDatabase, "c:\\test\\DEF104744.db"); |
|
32 _LIT8(KTestDatabaseZ, "c:\\test\\DEF104744.db\x0"); |
|
33 |
|
34 /////////////////////////////////////////////////////////////////////////////////////// |
|
35 |
|
36 //Deletes all created test files. |
|
37 void DestroyTestEnv() |
|
38 { |
|
39 if(TheSqliteDb) |
|
40 { |
|
41 sqlite3_close(TheSqliteDb); |
|
42 TheSqliteDb = NULL; |
|
43 } |
|
44 (void)TheFs.Delete(KTestDatabase); |
|
45 TheFs.Close(); |
|
46 } |
|
47 |
|
48 /////////////////////////////////////////////////////////////////////////////////////// |
|
49 /////////////////////////////////////////////////////////////////////////////////////// |
|
50 //Test macros and functions |
|
51 void Check1(TInt aValue, TInt aLine) |
|
52 { |
|
53 if(!aValue) |
|
54 { |
|
55 DestroyTestEnv(); |
|
56 RDebug::Print(_L("*** Line %d\r\n"), aLine); |
|
57 TheTest(EFalse, aLine); |
|
58 } |
|
59 } |
|
60 void Check2(TInt aValue, TInt aExpected, TInt aLine) |
|
61 { |
|
62 if(aValue != aExpected) |
|
63 { |
|
64 DestroyTestEnv(); |
|
65 RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue); |
|
66 TheTest(EFalse, aLine); |
|
67 } |
|
68 } |
|
69 #define TEST(arg) ::Check1((arg), __LINE__) |
|
70 #define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__) |
|
71 |
|
72 /////////////////////////////////////////////////////////////////////////////////////// |
|
73 /////////////////////////////////////////////////////////////////////////////////////// |
|
74 |
|
75 extern TPtrC GetFirstSqlStmt(TPtr& aString); |
|
76 |
|
77 #define PTR_ARG(buf) const_cast <TUint16*> (buf.Ptr()), buf.Length(), buf.Length() |
|
78 |
|
79 /** |
|
80 @SYMTestCaseID SYSLIB-SQL-CT-1628 |
|
81 @SYMTestCaseDesc GetFirstSqlStmt() test |
|
82 Tests the GetFirstSqlStmt() behaviour with a set of various SQL statements. |
|
83 @SYMTestPriority High |
|
84 @SYMTestActions GetFirstSqlStmt() test |
|
85 @SYMTestExpectedResults Test must not fail |
|
86 @SYMREQ REQ5792 |
|
87 REQ5793 |
|
88 */ |
|
89 void TestGetFirstSqlStmt() |
|
90 { |
|
91 TPtrC res; |
|
92 |
|
93 TBuf<1> b2; b2.Append(TChar(0)); |
|
94 TPtr p2(PTR_ARG(b2)); |
|
95 res.Set(GetFirstSqlStmt(p2)); |
|
96 //Expected result: res = "\x0", p2 is NULL |
|
97 TEST(res == b2); |
|
98 TEST(!p2.Ptr()); |
|
99 |
|
100 TBuf<2> b3; b3.Append(TChar(' ')); b3.Append(TChar(0)); |
|
101 TPtr p3(PTR_ARG(b3)); |
|
102 res.Set(GetFirstSqlStmt(p3)); |
|
103 //Expected result: res = " \x0", p3 is NULL |
|
104 TEST(res == b3); |
|
105 TEST(!p3.Ptr()); |
|
106 |
|
107 TBuf<7> b4(_L(";; ; ")); b4.Append(TChar(0)); |
|
108 TPtr p4(PTR_ARG(b4)); |
|
109 res.Set(GetFirstSqlStmt(p4)); |
|
110 //Expected result: res = "\x0", p4 = "; ; \x0" |
|
111 TEST(res.Length() == 1 && (TInt)res[0] == 0); |
|
112 TInt accLen = res.Length(); |
|
113 TEST(p4 == b4.Right(b4.Length() - accLen)); |
|
114 |
|
115 res.Set(GetFirstSqlStmt(p4)); |
|
116 //Expected result: res = "\x0", p4 = " ; \x0" |
|
117 TEST(res.Length() == 1 && (TInt)res[0] == 0); |
|
118 accLen += res.Length(); |
|
119 TEST(p4 == b4.Right(b4.Length() - accLen)); |
|
120 |
|
121 res.Set(GetFirstSqlStmt(p4)); |
|
122 //Expected result: res = " \x0", p4 = " \x0" |
|
123 TEST((TInt)res[0] == (TInt)TChar(' ') && (TInt)res[1] == 0); |
|
124 accLen += res.Length(); |
|
125 TEST(p4 == b4.Right(b4.Length() - accLen)); |
|
126 |
|
127 res.Set(GetFirstSqlStmt(p4)); |
|
128 //Expected result: res = " \x0", p4 is NULL |
|
129 TEST((TInt)res[0] == (TInt)TChar(' ') && (TInt)res[1] == (TInt)TChar(' ') && (TInt)res[2] == 0); |
|
130 TEST(!p4.Ptr()); |
|
131 |
|
132 TBuf<20> b5(_L("SELECT * FROM A")); b5.Append(TChar(0)); |
|
133 TPtr p5(PTR_ARG(b5)); |
|
134 res.Set(GetFirstSqlStmt(p5)); |
|
135 //Expected result: res = "SELECT * FROM A\x0", p5 is NULL |
|
136 TEST(res == b5); |
|
137 TEST(!p5.Ptr()); |
|
138 |
|
139 TBuf<20> b6(_L("SELECT * FROM A;")); b6.Append(TChar(0)); |
|
140 TPtr p6(PTR_ARG(b6)); |
|
141 res.Set(GetFirstSqlStmt(p6)); |
|
142 //Expected result: res = "SELECT * FROM A\x0", p6 = "\x0" |
|
143 TEST(res == b6.Left(b6.Length() - 1)); |
|
144 TEST(p6.Length() == 1 && p6[0] == 0); |
|
145 |
|
146 TBuf<40> b7(_L("/** Comment */ SELECT * FROM A;")); b7.Append(TChar(0)); |
|
147 TPtr p7(PTR_ARG(b7)); |
|
148 res.Set(GetFirstSqlStmt(p7)); |
|
149 //Expected result: res = "/** Comment */ SELECT * FROM A\x0", p7 = "\x0" |
|
150 TEST(res == b7.Left(b7.Length() - 1)); |
|
151 TEST(p7.Length() == 1 && p7[0] == 0); |
|
152 |
|
153 TBuf<40> b8(_L(" SELECT * FROM --Comment \r\n A;")); b8.Append(TChar(0)); |
|
154 TPtr p8(PTR_ARG(b8)); |
|
155 res.Set(GetFirstSqlStmt(p8)); |
|
156 //Expected result: res = " SELECT * FROM --Comment \r\n A\x0", p8 = "\x0" |
|
157 TEST(res == b8.Left(b8.Length() - 1)); |
|
158 TEST(p8.Length() == 1 && p8[0] == 0); |
|
159 |
|
160 TBuf<40> b9(_L("SELECT * FROM A; SELECT * FROM B")); b9.Append(TChar(0)); |
|
161 TPtr p9(PTR_ARG(b9)); |
|
162 res.Set(GetFirstSqlStmt(p9)); |
|
163 //Expected result: res = "SELECT * FROM A\x0", p9 = " SELECT * FROM B\x0" |
|
164 TEST(res.Left(res.Length() - 1) == b9.Left(res.Length() - 1) && (TInt)res[res.Length() - 1] == 0); |
|
165 accLen = res.Length(); |
|
166 TEST(p9 == b9.Right(b9.Length() - accLen)); |
|
167 |
|
168 res.Set(GetFirstSqlStmt(p9)); |
|
169 //Expected result: res = " SELECT * FROM B\x0", p9 is NULL |
|
170 TEST(res == b9.Right(b9.Length() - accLen)); |
|
171 TEST(!p9.Ptr()); |
|
172 |
|
173 //Defect INC113060 |
|
174 TBuf<255> b10(_L("UPDATE Playlist SET Name=';',Time='2007-09-20 12:31:33' WHERE UniqueId=640397473")); |
|
175 TPtr p10(PTR_ARG(b10)); |
|
176 res.Set(GetFirstSqlStmt(p10)); |
|
177 //Expected results: res= original string |
|
178 TEST(res.Compare(b10)==0); |
|
179 TEST(!p10.Ptr()); |
|
180 |
|
181 TBuf<255> firstStmt(_L("SELECT * FROM PlayList"));firstStmt.Append(TChar(0)); |
|
182 TBuf<255> b11(_L("SELECT * FROM PlayList;UPDATE Playlist SET Name=';',Time='2007-09-20 12:31:33' WHERE UniqueId=640397473")); |
|
183 TPtr p11(PTR_ARG(b11)); |
|
184 res.Set(GetFirstSqlStmt(p11)); |
|
185 TEST(res.Compare(firstStmt)==0); |
|
186 TEST(p11.Compare(b10)==0); |
|
187 } |
|
188 |
|
189 /** |
|
190 @SYMTestCaseID SYSLIB-SQL-UT-3433 |
|
191 @SYMTestCaseDesc Test for DEF104744 - RSqlStatement::Next() SQL Server crashes on ORDER BY clause. |
|
192 The test creates a database with a table with 30 integer columns, then inserts 100 |
|
193 records. After that, sets the soft heap limit to be very low - 10K |
|
194 (to get sqlite3_release_memory() called by SQLITE ), creates a statement object |
|
195 and attempts to retrieve the inserted records in descending order. |
|
196 @SYMTestPriority High |
|
197 @SYMTestActions Test for DEF104744 - RSqlStatement::Next() SQL Server crashes on ORDER BY clause. |
|
198 @SYMTestExpectedResults Test must not fail |
|
199 @SYMDEF DEF104744 |
|
200 */ |
|
201 void DEF104744() |
|
202 { |
|
203 (void)TheFs.Delete(KTestDatabase); |
|
204 TheSqliteDb = NULL; |
|
205 TInt err = sqlite3_open((const char*)KTestDatabaseZ().Ptr(), &TheSqliteDb); |
|
206 TEST2(err, SQLITE_OK); |
|
207 |
|
208 _LIT8(KCreateTblSqlZ, "CREATE TABLE A1(F1 INTEGER,F2 INTEGER,F3 INTEGER,F4 INTEGER,F5 INTEGER,F6 INTEGER,F7 INTEGER,F8 INTEGER,F9 INTEGER,F10 INTEGER,F11 INTEGER,F12 INTEGER,F13 INTEGER,F14 INTEGER,F15 INTEGER,F16 INTEGER,F17 INTEGER,F18 INTEGER,F19 INTEGER,F20 INTEGER,F21 INTEGER,F22 INTEGER,F23 INTEGER,F24 INTEGER,F25 INTEGER,F26 INTEGER,F27 INTEGER,F28 INTEGER,F29 INTEGER,F30 INTEGER)\x0"); |
|
209 err = sqlite3_exec(TheSqliteDb, (const char*)KCreateTblSqlZ().Ptr(), 0, 0, 0); |
|
210 TEST2(err, SQLITE_OK); |
|
211 |
|
212 //Insert a 100 records |
|
213 const TInt KTestRecCnt = 100; |
|
214 _LIT8(KInsertSqlZ, "INSERT INTO A1(F1,F2 ,F3 ,F4 ,F5 ,F6 ,F7 ,F8 ,F9 ,F10,F11,F12,F13,F14,F15,F16,F17,F18,F19,F20,F21,F22,F23,F24,F25,F26,F27,F28,F29,F30) VALUES(:Prm1,:Prm2,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296,4294967296)\x0"); |
|
215 sqlite3_stmt* stmt1 = NULL; |
|
216 err = sqlite3_prepare_v2(TheSqliteDb, (const char*)(KInsertSqlZ().Ptr()), -1, &stmt1, NULL); |
|
217 TEST2(err, SQLITE_OK); |
|
218 |
|
219 _LIT8(KBeginSqlZ, "BEGIN\x0"); |
|
220 err = sqlite3_exec(TheSqliteDb, (const char*)KBeginSqlZ().Ptr(), 0, 0, 0); |
|
221 TEST2(err, SQLITE_OK); |
|
222 |
|
223 for(TInt i=0;i<KTestRecCnt;++i) |
|
224 { |
|
225 err = sqlite3_bind_int(stmt1, 1, i); |
|
226 TEST2(err, SQLITE_OK); |
|
227 err = sqlite3_bind_int(stmt1, 2, i + 1); |
|
228 TEST2(err, SQLITE_OK); |
|
229 err = sqlite3_step(stmt1); |
|
230 TEST2(err, SQLITE_DONE); |
|
231 err = sqlite3_reset(stmt1); |
|
232 TEST2(err, SQLITE_OK); |
|
233 TInt cnt = sqlite3_changes(TheSqliteDb); |
|
234 TEST2(cnt, 1); |
|
235 } |
|
236 |
|
237 _LIT8(KCommitSqlZ, "COMMIT\x0"); |
|
238 err = sqlite3_exec(TheSqliteDb, (const char*)KCommitSqlZ().Ptr(), 0, 0, 0); |
|
239 TEST2(err, SQLITE_OK); |
|
240 sqlite3_finalize(stmt1); |
|
241 |
|
242 sqlite3_soft_heap_limit(10 * 1024);//Setting very low soft heap limit - 10K |
|
243 |
|
244 // Get the inserted record data in descending order. |
|
245 sqlite3_stmt* stmt2 = NULL; |
|
246 _LIT8(KSelectSqlZ,"SELECT * FROM A1 ORDER BY F1 DESC"); |
|
247 err = sqlite3_prepare_v2(TheSqliteDb, (const char*)(KSelectSqlZ().Ptr()), -1, &stmt2, NULL); |
|
248 TEST2(err, SQLITE_OK); |
|
249 err = sqlite3_step(stmt2); |
|
250 TEST2(err, SQLITE_ROW); |
|
251 sqlite3_finalize(stmt2); |
|
252 |
|
253 sqlite3_close(TheSqliteDb); |
|
254 TheSqliteDb = NULL; |
|
255 (void)TheFs.Delete(KTestDatabase); |
|
256 } |
|
257 |
|
258 enum TStmtType {EStmt8, EStmt16}; |
|
259 |
|
260 //This function attempts to execute sqlite3_prepare_v2() or sqlite3_prepare16_v2() in an "out of memory loop". |
|
261 //If the prepare call fails, the statement handle is expected to be NULL. |
|
262 void StmtHandleTest(TStmtType aStmtType) |
|
263 { |
|
264 TEST(TheSqliteDb != NULL); |
|
265 for(TInt failingAllocationNo=1;;++failingAllocationNo) |
|
266 { |
|
267 __UHEAP_SETFAIL(RHeap::EFailNext, failingAllocationNo); |
|
268 sqlite3_stmt* stmt = NULL; |
|
269 TInt err = SQLITE_NOMEM; |
|
270 if(aStmtType == EStmt8) |
|
271 { |
|
272 _LIT8(KSelectSqlZ,"SELECT * FROM A\x0"); |
|
273 err = sqlite3_prepare_v2(TheSqliteDb, (const char*)(KSelectSqlZ().Ptr()), -1, &stmt, NULL); |
|
274 } |
|
275 else |
|
276 { |
|
277 _LIT(KSelectSqlZ,"SELECT * FROM A\x0"); |
|
278 err = sqlite3_prepare16_v2(TheSqliteDb, (const char*)(KSelectSqlZ().Ptr()), -1, &stmt, NULL); |
|
279 } |
|
280 __UHEAP_SETFAIL(RHeap::ENone, 0); |
|
281 if(err != SQLITE_OK) |
|
282 {//The statement handle should be NULL if err is not SQLITE_OK |
|
283 TEST(!stmt); |
|
284 } |
|
285 else |
|
286 { |
|
287 TEST(stmt != NULL); |
|
288 sqlite3_finalize(stmt); |
|
289 break; |
|
290 } |
|
291 } |
|
292 } |
|
293 |
|
294 /** |
|
295 @SYMTestCaseID SYSLIB-SQL-UT-3466 |
|
296 @SYMTestCaseDesc Test for DEF105444 SQL, sqlite3_prepare_v2() demonstrates non-atomic behaviour (handle leak). |
|
297 The test creates a database with a table and inserts one record. |
|
298 After that the test attempts to prepare a SELECT statement handle inside an "ouut of memory" |
|
299 loop. If the prepare operation fails, the statement handle should be NULL. |
|
300 @SYMTestPriority High |
|
301 @SYMTestActions DEF105444 SQL, sqlite3_prepare_v2() demonstrates non-atomic behaviour (handle leak) |
|
302 @SYMTestExpectedResults Test must not fail |
|
303 @SYMDEF DEF105444 |
|
304 */ |
|
305 void DEF105444() |
|
306 { |
|
307 (void)TheFs.Delete(KTestDatabase); |
|
308 TheSqliteDb = NULL; |
|
309 TInt err = sqlite3_open((const char*)KTestDatabaseZ().Ptr(), &TheSqliteDb); |
|
310 TEST2(err, SQLITE_OK); |
|
311 |
|
312 _LIT8(KCreateTblSqlZ, "CREATE TABLE A(Id INTEGER)\x0"); |
|
313 err = sqlite3_exec(TheSqliteDb, (const char*)KCreateTblSqlZ().Ptr(), 0, 0, 0); |
|
314 TEST2(err, SQLITE_OK); |
|
315 |
|
316 _LIT8(KInsertSqlZ, "INSERT INTO A(Id) VALUES(1)\x0"); |
|
317 err = sqlite3_exec(TheSqliteDb, (const char*)KInsertSqlZ().Ptr(), 0, 0, 0); |
|
318 TEST2(err, SQLITE_OK); |
|
319 |
|
320 StmtHandleTest(EStmt8); |
|
321 StmtHandleTest(EStmt16); |
|
322 |
|
323 sqlite3_close(TheSqliteDb); |
|
324 TheSqliteDb = NULL; |
|
325 (void)TheFs.Delete(KTestDatabase); |
|
326 } |
|
327 |
|
328 void UtilFileNameTest() |
|
329 { |
|
330 #ifdef _ASSERTIONS |
|
331 _LIT(KFileName, "bbb.db"); |
|
332 |
|
333 _LIT(KFileName1, "c:\\aaa\\bbb.db\x0"); |
|
334 TPtrC p1 = Util::Filename(KFileName1().Ptr()); |
|
335 TEST(p1 == KFileName); |
|
336 |
|
337 _LIT(KFileName2, "c:/aaa/bbb.db\x0"); |
|
338 TPtrC p2 = Util::Filename(KFileName2().Ptr()); |
|
339 TEST(p2 == KFileName); |
|
340 |
|
341 _LIT(KFileName3, "bbb.db\x0"); |
|
342 TPtrC p3 = Util::Filename(KFileName3().Ptr()); |
|
343 TEST(p3 == KFileName); |
|
344 #else |
|
345 TheTest.Printf(_L(" === This test case works only if the test is built with the _ASSERTIONS macro defined!\r\n")); |
|
346 #endif |
|
347 } |
|
348 |
|
349 void DoTests() |
|
350 { |
|
351 TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1628 GetFirstSqlStmt() test ")); |
|
352 TestGetFirstSqlStmt(); |
|
353 |
|
354 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3433 DEF104744 SQL Server crashes on ORDER BY clause ")); |
|
355 DEF104744(); |
|
356 |
|
357 TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3466 DEF105444 SQL, sqlite3_prepare_v2() demonstrates non-atomic behaviour (handle leak) ")); |
|
358 DEF105444(); |
|
359 |
|
360 TheTest.Next(_L(" Util::Filename() test")); |
|
361 UtilFileNameTest(); |
|
362 } |
|
363 |
|
364 //Creates file session instance and the test directory |
|
365 void CreateTestEnv() |
|
366 { |
|
367 TInt err = TheFs.Connect(); |
|
368 TheTest(err == KErrNone); |
|
369 |
|
370 err = TheFs.MkDir(KTestDir); |
|
371 TEST(err == KErrNone || err == KErrAlreadyExists); |
|
372 } |
|
373 |
|
374 TInt E32Main() |
|
375 { |
|
376 TheSqliteDb = NULL; |
|
377 |
|
378 TheTest.Title(); |
|
379 |
|
380 CTrapCleanup* tc = CTrapCleanup::New(); |
|
381 |
|
382 __UHEAP_MARK; |
|
383 |
|
384 CreateTestEnv(); |
|
385 TInt err = sqlite3SymbianLibInit(); |
|
386 TEST2(err, KErrNone); |
|
387 DoTests(); |
|
388 sqlite3SymbianLibFinalize(); |
|
389 DestroyTestEnv(); |
|
390 |
|
391 CloseSTDLIB(); |
|
392 |
|
393 __UHEAP_MARKEND; |
|
394 |
|
395 TheTest.End(); |
|
396 TheTest.Close(); |
|
397 |
|
398 delete tc; |
|
399 |
|
400 User::Heap().Check(); |
|
401 return KErrNone; |
|
402 } |