|
1 // Copyright (c) 2008-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 // Summary: |
|
15 // A regression test to check changes to the CContactDatabase::SortL() API |
|
16 // that provide backward compatibility with <=v9.2 for some 3rd party apps |
|
17 // that misuse the API. |
|
18 // Full description: |
|
19 // In cntmodel <=v9.2, sorting on the database was done with the now deprecated |
|
20 // method: |
|
21 // CContactDatabase::SortL(CArrayFix<TSortPref>* aSortOrder) |
|
22 // As is implied by the pass-by-pointer semantics, this has always taken |
|
23 // ownership of aSortOrder. In the past, aSortOrder was held as a data member |
|
24 // of CContactDatabase and so was held for the lifetime of the database object. |
|
25 // Some 3rd party apps called SortL(), mistakenly thinking that ownership |
|
26 // of aSortOrder had not been passed. Consequently, they used aSortOrder after |
|
27 // the call. They were able to get away with this because aSortOrder had not |
|
28 // been deleted yet at that point. |
|
29 // In cntmodel >=v9.3, the way sort preferences are stored changed and so |
|
30 // aSortOrder was deleted at the end of SortL() as it was no longer needed. |
|
31 // The impact of this change was that aSortOrder was no longer available for |
|
32 // use after a call to SortL() and so the 3rd party apps panicked. |
|
33 // The fix for INC119319 provides a work-around that re-introduces the |
|
34 // CContactDatabase member variable to hold aSortOrder for the lifetime of the |
|
35 // database object, as in pre-v9.3 versions. This extended lifetime allows the |
|
36 // 3rd party apps to continue to use aSortOrder as they had done before. |
|
37 // Actions: |
|
38 // -- Create a new database; |
|
39 // -- Create and insert 2 contact items into the database; |
|
40 // -- Call SortL() to sort the contact items; |
|
41 // -- Test whether aSortOrder can still be used, failing if not; |
|
42 // -- Clean up the database. |
|
43 // Associated defect: |
|
44 // INC119319 Break in CContactDatabase::SortL |
|
45 // [Not actually a defect but a work-around was provided for compatibility.] |
|
46 // Written by: |
|
47 // James Clarke |
|
48 // |
|
49 // |
|
50 |
|
51 #include <e32test.h> |
|
52 #include <cntdb.h> |
|
53 #include <cntitem.h> |
|
54 #include <cntfield.h> |
|
55 #include <cntfldst.h> |
|
56 |
|
57 _LIT(KDbName, "C:T_DB_SortL_test.cdb"); |
|
58 _LIT(KTestName, "T_DB_SortL_test"); |
|
59 RTest test(KTestName); |
|
60 |
|
61 /** |
|
62 |
|
63 @SYMTestCaseID PIM-T-DB-SORTL-TEST-0001 |
|
64 |
|
65 */ |
|
66 |
|
67 LOCAL_C void DoTestsL() |
|
68 { |
|
69 test.Start(_L("@SYMTESTCaseID:PIM-T-DB-SORTL-TEST-0001 T_DB_SortL_test")); |
|
70 |
|
71 |
|
72 // create default, empty database |
|
73 CContactDatabase* db = CContactDatabase::ReplaceL(KDbName); |
|
74 CleanupStack::PushL(db); |
|
75 |
|
76 // create contact 1 and add it to the db |
|
77 CContactCard* contact1 = CContactCard::NewLC(); |
|
78 CContactItemField* fname1 = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldGivenName); |
|
79 _LIT(KFname1, "Test"); |
|
80 fname1->TextStorage()->SetTextL(KFname1() ); |
|
81 contact1->AddFieldL(*fname1); |
|
82 CleanupStack::Pop(fname1); |
|
83 CContactItemField* lname1 = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName); |
|
84 _LIT(KLname1, "Name"); |
|
85 lname1->TextStorage()->SetTextL(KLname1() ); |
|
86 contact1->AddFieldL(*lname1); |
|
87 CleanupStack::Pop(lname1); |
|
88 db->AddNewContactL(*contact1); |
|
89 |
|
90 // create contact 2 and add it to the db |
|
91 CContactCard* contact2 = CContactCard::NewLC(); |
|
92 CContactItemField* fname2 = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldGivenName); |
|
93 _LIT(KFname2, "Example"); |
|
94 fname2->TextStorage()->SetTextL(KFname2() ); |
|
95 contact2->AddFieldL(*fname2); |
|
96 CleanupStack::Pop(fname2); |
|
97 CContactItemField* lname2 = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName); |
|
98 _LIT(KLname2, "AExamp"); |
|
99 lname2->TextStorage()->SetTextL(KLname2() ); |
|
100 contact2->AddFieldL(*lname2); |
|
101 CleanupStack::Pop(lname2); |
|
102 db->AddNewContactL(*contact2); |
|
103 |
|
104 // fetch and print contact IDs. Expected order: 1, 2 |
|
105 const CContactIdArray* items = db->SortedItemsL(); // doesn't take ownership |
|
106 _LIT(KFormattedIdList1, "Contact IDs *before* sorting: %d, %d\n"); |
|
107 test.Printf(KFormattedIdList1, (*items)[0], (*items)[1]); |
|
108 TInt item1BeforeSort = (*items)[0]; |
|
109 TInt item2BeforeSort = (*items)[1]; |
|
110 |
|
111 // create sort order array |
|
112 CArrayFix<CContactDatabase::TSortPref>* sortOrder = new (ELeave) CArrayFixFlat<CContactDatabase::TSortPref>(2); |
|
113 CleanupStack::PushL(sortOrder); |
|
114 sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldFamilyName) ); |
|
115 sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldGivenName) ); |
|
116 |
|
117 // sort db and measure differences in heap allocations as a proxy for |
|
118 // whether sortOrder has been deleted by SortL() or not. |
|
119 TInt totalAllocSize(0); |
|
120 TInt heapCellsDifference = User::AllocSize(totalAllocSize); |
|
121 db->SortL(sortOrder); |
|
122 heapCellsDifference -= User::AllocSize(totalAllocSize); |
|
123 CleanupStack::Pop(sortOrder); |
|
124 |
|
125 // fetch and print contact IDs. Expected order: 2, 1 |
|
126 items = db->SortedItemsL(); // doesn't take ownership |
|
127 _LIT(KFormattedIdList2, "Contact IDs *after* sorting: %d, %d\n"); |
|
128 test.Printf(KFormattedIdList2, (*items)[0], (*items)[1]); |
|
129 TInt item1AfterSort = (*items)[0]; |
|
130 TInt item2AfterSort = (*items)[1]; |
|
131 |
|
132 //check the sort order to make sure |
|
133 test(item1BeforeSort == item2AfterSort); |
|
134 test(item2BeforeSort == item1AfterSort); |
|
135 |
|
136 // check to see if sortOrder is still usable |
|
137 if (heapCellsDifference == 0) |
|
138 { |
|
139 // attempt to re-use sortOrder -- should be allowed after workaround |
|
140 CContactDatabase::TSortPref sortPref( (*sortOrder)[0]); |
|
141 _LIT(KSortOrderInfo, "The first sort order preference's field type is: %d.\n"); |
|
142 test.Printf(KSortOrderInfo, sortPref.iFieldType); |
|
143 _LIT(KYesSame, "Yes, have successfully re-used sortOrder.\n"); |
|
144 test.Printf(KYesSame); |
|
145 } |
|
146 else |
|
147 { |
|
148 // looks like sortOrder has been deleted so don't try to use it |
|
149 _LIT(KNoDifferent, "No, have not reused sortOrder as it has probably been deleted.\n"); |
|
150 test.Printf(KNoDifferent); |
|
151 } |
|
152 |
|
153 // cleanup |
|
154 CleanupStack::PopAndDestroy(3, db); // and contact1, contact2 |
|
155 CContactDatabase::DeleteDatabaseL(KDbName); |
|
156 |
|
157 test.End(); |
|
158 test.Close(); |
|
159 } |
|
160 |
|
161 GLDEF_C TInt E32Main() |
|
162 { |
|
163 // Init |
|
164 __UHEAP_MARK; |
|
165 CTrapCleanup* cleanupStack = CTrapCleanup::New(); |
|
166 if (!cleanupStack) |
|
167 { |
|
168 return KErrNoMemory; |
|
169 } |
|
170 |
|
171 CActiveScheduler* activeScheduler = new CActiveScheduler; |
|
172 if (!activeScheduler) |
|
173 { |
|
174 return KErrNoMemory; |
|
175 } |
|
176 CActiveScheduler::Install(activeScheduler); |
|
177 |
|
178 // Run the tests |
|
179 TRAPD(err, DoTestsL()); |
|
180 if (err) |
|
181 { |
|
182 TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KDbName) ); |
|
183 test(EFalse); |
|
184 } |
|
185 |
|
186 // Cleanup |
|
187 delete activeScheduler; |
|
188 delete cleanupStack; |
|
189 __UHEAP_MARKEND; |
|
190 return err; |
|
191 } |