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