|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "ut_cntcache.h" |
|
19 #include "cntcache.h" |
|
20 #include "cntcache_p.h" |
|
21 |
|
22 void TestCntCache::initTestCase() |
|
23 { |
|
24 mContactManager = new QContactManager("symbian"); |
|
25 |
|
26 // start with a clean database |
|
27 cleanDatabase(); |
|
28 |
|
29 // TODO: This test needs to be run with the default provider, so when there is a mechanism |
|
30 // to variate the info provider, use that mechanism here to select the default provider. |
|
31 |
|
32 // create contacts; twins with same image at indexes 0,5 and 2,3 (good for increasing branch coverage) |
|
33 mContacts[0] = createContact("Joe", "Doe", "1234567", "c:/data/images/image1.png"); |
|
34 mContacts[1] = createContact("Marja", "Meikalainen", "7654321", ""); |
|
35 mContacts[2] = createContact("Sven", "Dufva", "12121212", "c:/data/images/image2.png"); |
|
36 mContacts[3] = createContact("Twin", "Dufva", "12121212", "c:/data/images/image2.png"); |
|
37 mContacts[4] = createContact("", "", "123123", ""); |
|
38 mContacts[5] = createContact("Twin", "Doe", "1234568", "c:/data/images/image1.png"); |
|
39 } |
|
40 |
|
41 void TestCntCache::cleanupTestCase() |
|
42 { |
|
43 // end with a clean database |
|
44 cleanDatabase(); |
|
45 |
|
46 delete mContactManager; |
|
47 mContactManager = NULL; |
|
48 } |
|
49 |
|
50 /* |
|
51 Test case: Constructing and deleting the cache. |
|
52 */ |
|
53 void TestCntCache::construction() |
|
54 { |
|
55 // test creation |
|
56 QPointer<CntCache> cache = CntCache::instance(); |
|
57 QVERIFY(cache != NULL); |
|
58 QPointer<CntCacheThread> worker = cache->mWorker; |
|
59 QVERIFY(worker != NULL); |
|
60 |
|
61 // test singleton property |
|
62 QVERIFY(cache == CntCache::instance()); |
|
63 |
|
64 // test data members |
|
65 QVERIFY(cache->mContactManager != NULL); |
|
66 QVERIFY(worker->mContactManager != NULL); |
|
67 QVERIFY(worker->mThumbnailManager != NULL); |
|
68 QVERIFY(!worker->mStarted); |
|
69 QVERIFY(!worker->mJobLoopRunning); |
|
70 QVERIFY(!worker->mPostponeJobs); |
|
71 QVERIFY(worker->mDataProviders.count() >= 1); |
|
72 |
|
73 // test deletion |
|
74 cache->onShutdown(); |
|
75 QVERIFY(cache == NULL); |
|
76 QVERIFY(worker == NULL); |
|
77 } |
|
78 |
|
79 /* |
|
80 Test case: Fetch contact info. |
|
81 |
|
82 Fetches all six contacts in two batches of four and two contacts. The contacts are |
|
83 divided up so that one pair of twins is in the same batch and the other pair of twins |
|
84 has one twin in each batch. This maximizes branch coverage. |
|
85 */ |
|
86 void TestCntCache::fetchContactInfo() |
|
87 { |
|
88 CntContactInfo info[CntTestContacts]; // info for each of the contacts |
|
89 |
|
90 // create cache and attach a signal spy to it |
|
91 CntCache* cache = CntCache::instance(); |
|
92 QSignalSpy spy(cache, SIGNAL(contactInfoUpdated(QContactLocalId))); |
|
93 |
|
94 // create list of ids |
|
95 QList<QContactLocalId> idList; |
|
96 for (int i = 0; i < CntTestContacts; ++i) { |
|
97 idList << mContacts[i].localId(); |
|
98 } |
|
99 |
|
100 // fetch three of the contacts in rapid succession, one of them twice |
|
101 info[1] = cache->fetchContactInfo(1, idList); |
|
102 info[0] = cache->fetchContactInfo(0, idList); |
|
103 info[4] = cache->fetchContactInfo(4, idList); |
|
104 info[0] = cache->fetchContactInfo(0, idList); |
|
105 info[5] = cache->fetchContactInfo(5, idList); |
|
106 |
|
107 // check that names are ok |
|
108 QVERIFY(info[1].name() == mContacts[1].displayLabel()); |
|
109 QVERIFY(info[0].name() == mContacts[0].displayLabel()); |
|
110 QVERIFY(info[4].name() == mContacts[4].displayLabel()); |
|
111 QVERIFY(info[5].name() == mContacts[5].displayLabel()); |
|
112 |
|
113 // wait for possible signals to arrive (in the future, all info could be returned immediately) |
|
114 QTest::qWait(4000); |
|
115 spy.clear(); |
|
116 |
|
117 // fetch all contacts -- they should be cached now by the read-ahead mechanism |
|
118 for (int i = 0; i < CntTestContacts; ++i) { |
|
119 info[i] = cache->fetchContactInfo(i, idList); |
|
120 } |
|
121 |
|
122 // confirm that no further signals from cache (i.e. they were all really cached) |
|
123 QTest::qWait(2000); |
|
124 QVERIFY(spy.count() == 0); |
|
125 |
|
126 // confirm that returned data equals created data |
|
127 for (int i = 0; i < CntTestContacts; ++i) { |
|
128 QVERIFY(info[i].name() == mContacts[i].displayLabel()); |
|
129 QVERIFY(info[i].text() == mContacts[i].detail<QContactPhoneNumber>().number()); |
|
130 } |
|
131 |
|
132 // confirm that info cache contains correct data |
|
133 int cacheItemCount = 0; |
|
134 foreach (CntInfoCacheItem* item, cache->mInfoCache) { |
|
135 // find corresponding contact |
|
136 for (int i = 0; i < CntTestContacts; ++i) { |
|
137 if (mContacts[i].localId() == item->contactId) { |
|
138 QVERIFY(item->name == mContacts[i].displayLabel()); |
|
139 QVERIFY(item->text == mContacts[i].detail<QContactPhoneNumber>().number()); |
|
140 QVERIFY(item->icons[0].replace('\\', '/') == mContacts[i].detail<QContactAvatar>().imageUrl().toString().replace('\\', '/')); |
|
141 ++cacheItemCount; |
|
142 } |
|
143 } |
|
144 } |
|
145 QVERIFY(cacheItemCount == CntTestContacts); |
|
146 |
|
147 // confirm that icon cache contains correct data |
|
148 cacheItemCount = 0; |
|
149 foreach (CntIconCacheItem* item, cache->mIconCache) { |
|
150 // find corresponding contact |
|
151 for (int i = 0; i < CntTestContacts; ++i) { |
|
152 if (mContacts[i].detail<QContactAvatar>().imageUrl().toString().replace('\\','/') == item->iconName.replace('\\','/')) { |
|
153 QVERIFY(item->isFetched); |
|
154 QVERIFY(!item->icon.isNull()); |
|
155 ++cacheItemCount; |
|
156 } |
|
157 } |
|
158 } |
|
159 QVERIFY(cacheItemCount == 2*2); // two images, both used by two contacts |
|
160 |
|
161 delete cache; |
|
162 } |
|
163 |
|
164 /* |
|
165 Test case: Clear cache. |
|
166 */ |
|
167 void TestCntCache::clearCache() |
|
168 { |
|
169 CntCache* cache = CntCache::instance(); |
|
170 |
|
171 QList<QContactLocalId> idList; |
|
172 for (int i = 0; i < CntTestContacts; ++i) { |
|
173 idList << mContacts[i].localId(); |
|
174 } |
|
175 |
|
176 cache->fetchContactInfo(1, idList); |
|
177 cache->fetchContactInfo(3, idList); |
|
178 |
|
179 QVERIFY(cache->mInfoCache.count() == 2); |
|
180 QTest::qWait(3000); |
|
181 QVERIFY(cache->mIconCache.count() == 2); |
|
182 |
|
183 cache->clearCache(); |
|
184 QVERIFY(cache->mInfoCache.count() == 0); // icon cache needn't be cleared |
|
185 |
|
186 delete cache; |
|
187 } |
|
188 |
|
189 /* TODO: Test cases for overflowing info and icon requests (>30) -- IDs need not be real, just confirm |
|
190 that cancellation notifications eventually arrive */ |
|
191 |
|
192 /* |
|
193 Helper function for cleaning the database. |
|
194 */ |
|
195 void TestCntCache::cleanDatabase() |
|
196 { |
|
197 QList<QContactLocalId> ids = mContactManager->contactIds(); |
|
198 QMap<int, QContactManager::Error> errorMapInit; |
|
199 mContactManager->removeContacts(ids, &errorMapInit); |
|
200 mContactManager->removeContact(mContactManager->selfContactId()); |
|
201 } |
|
202 |
|
203 /* |
|
204 Helper function for creating contacts. |
|
205 */ |
|
206 QContact TestCntCache::createContact(QString firstName, QString lastName, QString phoneNumber, QString imageName) |
|
207 { |
|
208 QContact contact; |
|
209 |
|
210 if (!firstName.isEmpty() && !lastName.isEmpty()) { |
|
211 QContactName name; |
|
212 name.setFirstName(firstName); |
|
213 name.setLastName(lastName); |
|
214 contact.saveDetail(&name); |
|
215 } |
|
216 |
|
217 if (!phoneNumber.isEmpty()) { |
|
218 QContactPhoneNumber number; |
|
219 number.setNumber(phoneNumber); |
|
220 number.setContexts(QContactDetail::ContextHome); |
|
221 number.setSubTypes(QContactPhoneNumber::SubTypeMobile); |
|
222 contact.saveDetail(&number); |
|
223 } |
|
224 |
|
225 if (!imageName.isEmpty()) { |
|
226 QContactAvatar avatar; |
|
227 avatar.setImageUrl(imageName); |
|
228 contact.saveDetail(&avatar); |
|
229 } |
|
230 |
|
231 mContactManager->saveContact(&contact); |
|
232 |
|
233 return contact; |
|
234 } |