1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.vcard.tests; 17 18 import com.android.vcard.VCardConfig; 19 import com.android.vcard.VCardConstants; 20 import com.android.vcard.VCardEntry; 21 import com.android.vcard.VCardEntry.AndroidCustomData; 22 import com.android.vcard.VCardEntry.AnniversaryData; 23 import com.android.vcard.VCardEntry.BirthdayData; 24 import com.android.vcard.VCardEntry.EmailData; 25 import com.android.vcard.VCardEntry.EntryElement; 26 import com.android.vcard.VCardEntry.EntryLabel; 27 import com.android.vcard.VCardEntry.ImData; 28 import com.android.vcard.VCardEntry.NameData; 29 import com.android.vcard.VCardEntry.NicknameData; 30 import com.android.vcard.VCardEntry.NoteData; 31 import com.android.vcard.VCardEntry.OrganizationData; 32 import com.android.vcard.VCardEntry.PhoneData; 33 import com.android.vcard.VCardEntry.PhotoData; 34 import com.android.vcard.VCardEntry.PostalData; 35 import com.android.vcard.VCardEntry.SipData; 36 import com.android.vcard.VCardEntryConstructor; 37 import com.android.vcard.VCardEntryHandler; 38 import com.android.vcard.VCardInterpreter; 39 import com.android.vcard.VCardProperty; 40 41 import android.accounts.Account; 42 import android.content.ContentProviderOperation; 43 import android.content.ContentResolver; 44 import android.provider.ContactsContract.CommonDataKinds.Email; 45 import android.provider.ContactsContract.CommonDataKinds.Im; 46 import android.provider.ContactsContract.CommonDataKinds.Organization; 47 import android.provider.ContactsContract.CommonDataKinds.Phone; 48 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 49 import android.provider.ContactsContract.CommonDataKinds.SipAddress; 50 import android.test.AndroidTestCase; 51 52 import java.util.ArrayList; 53 import java.util.Arrays; 54 import java.util.HashMap; 55 import java.util.List; 56 import java.util.Map; 57 58 public class VCardEntryTests extends AndroidTestCase { 59 private class MockVCardEntryHandler implements VCardEntryHandler { 60 private List<VCardEntry> mEntries = new ArrayList<VCardEntry>(); 61 private boolean mOnStartCalled; 62 private boolean mOnEndCalled; 63 64 @Override onStart()65 public void onStart() { 66 assertFalse(mOnStartCalled); 67 mOnStartCalled = true; 68 } 69 70 @Override onEntryCreated(VCardEntry entry)71 public void onEntryCreated(VCardEntry entry) { 72 assertTrue(mOnStartCalled); 73 assertFalse(mOnEndCalled); 74 mEntries.add(entry); 75 } 76 77 @Override onEnd()78 public void onEnd() { 79 assertTrue(mOnStartCalled); 80 assertFalse(mOnEndCalled); 81 mOnEndCalled = true; 82 } 83 getEntries()84 public List<VCardEntry> getEntries() { 85 return mEntries; 86 } 87 } 88 89 /** 90 * Tests VCardEntry and related clasess can handle nested classes given 91 * {@link VCardInterpreter} is called appropriately. 92 * 93 * This test manually calls VCardInterpreter's callback mechanism and checks 94 * {@link VCardEntryConstructor} constructs {@link VCardEntry} per given calls. 95 * 96 * Intended vCard is as follows: 97 * <code> 98 * BEGIN:VCARD 99 * N:test1 100 * BEGIN:VCARD 101 * N:test2 102 * END:VCARD 103 * TEL:1 104 * END:VCARD 105 * </code> 106 */ testNestHandling()107 public void testNestHandling() { 108 VCardEntryConstructor entryConstructor = new VCardEntryConstructor(); 109 MockVCardEntryHandler entryHandler = new MockVCardEntryHandler(); 110 entryConstructor.addEntryHandler(entryHandler); 111 112 entryConstructor.onVCardStarted(); 113 entryConstructor.onEntryStarted(); 114 VCardProperty property = new VCardProperty(); 115 property.setName(VCardConstants.PROPERTY_N); 116 property.setValues("test1"); 117 entryConstructor.onPropertyCreated(property); 118 119 entryConstructor.onEntryStarted(); // begin nest 120 property = new VCardProperty(); 121 property.setName(VCardConstants.PROPERTY_N); 122 property.setValues("test2"); 123 entryConstructor.onPropertyCreated(property); 124 entryConstructor.onEntryEnded(); // end nest 125 126 property = new VCardProperty(); 127 property.setName(VCardConstants.PROPERTY_TEL); 128 property.setValues("1"); 129 entryConstructor.onPropertyCreated(property); 130 entryConstructor.onEntryEnded(); 131 entryConstructor.onVCardEnded(); 132 133 List<VCardEntry> entries = entryHandler.getEntries(); 134 assertEquals(2, entries.size()); 135 VCardEntry parent = entries.get(1); 136 VCardEntry child = entries.get(0); 137 assertEquals("test1", parent.getDisplayName()); 138 assertEquals("test2", child.getDisplayName()); 139 List<VCardEntry.PhoneData> phoneList = parent.getPhoneList(); 140 assertNotNull(phoneList); 141 assertEquals(1, phoneList.size()); 142 assertEquals("1", phoneList.get(0).getNumber()); 143 } 144 145 private class MockEntryElementIterator implements VCardEntry.EntryElementIterator { 146 private boolean mStartCalled; 147 private boolean mEndCalled; 148 private EntryLabel mLabel; 149 private final Map<EntryLabel, EntryElement> mExpectedElements = 150 new HashMap<EntryLabel, EntryElement>(); 151 addExpectedElement(EntryElement elem)152 public void addExpectedElement(EntryElement elem) { 153 mExpectedElements.put(elem.getEntryLabel(), elem); 154 } 155 156 @Override onIterationStarted()157 public void onIterationStarted() { 158 assertFalse(mStartCalled); 159 assertFalse(mEndCalled); 160 assertNull(mLabel); 161 mStartCalled = true; 162 } 163 164 @Override onIterationEnded()165 public void onIterationEnded() { 166 assertTrue(mStartCalled); 167 assertFalse(mEndCalled); 168 assertNull(mLabel); 169 assertTrue("Expected Elements remaining: " + 170 Arrays.toString(mExpectedElements.values().toArray()), 171 mExpectedElements.isEmpty()); 172 } 173 174 @Override onElementGroupStarted(EntryLabel label)175 public void onElementGroupStarted(EntryLabel label) { 176 assertTrue(mStartCalled); 177 assertFalse(mEndCalled); 178 assertNull(mLabel); 179 mLabel = label; 180 } 181 182 @Override onElementGroupEnded()183 public void onElementGroupEnded() { 184 assertTrue(mStartCalled); 185 assertFalse(mEndCalled); 186 assertNotNull(mLabel); 187 mLabel = null; 188 } 189 190 @Override onElement(EntryElement elem)191 public boolean onElement(EntryElement elem) { 192 EntryElement expectedElem = mExpectedElements.remove(elem.getEntryLabel()); 193 assertNotNull("Unexpected elem: " + elem.toString(), expectedElem); 194 assertEquals(expectedElem, elem); 195 return true; 196 } 197 } 198 199 /** 200 * Tests every element in VCardEntry is iterated by 201 * {@link VCardEntry#iterateAllData(com.android.vcard.VCardEntry.EntryElementIterator)}. 202 */ testEntryElementIterator()203 public void testEntryElementIterator() { 204 VCardEntry entry = new VCardEntry(); 205 MockEntryElementIterator iterator = new MockEntryElementIterator(); 206 207 VCardProperty property = new VCardProperty(); 208 property.setName("N"); 209 property.setValues("family", "given", "middle", "prefix", "suffix"); 210 entry.addProperty(property); 211 NameData nameData = new NameData(); 212 nameData.setFamily("family"); 213 nameData.setGiven("given"); 214 nameData.setMiddle("middle"); 215 nameData.setPrefix("prefix"); 216 nameData.setSuffix("suffix"); 217 iterator.addExpectedElement(nameData); 218 219 property = new VCardProperty(); 220 property.setName("TEL"); 221 property.setParameter("TYPE", "HOME"); 222 property.setValues("1"); 223 entry.addProperty(property); 224 PhoneData phoneData = new PhoneData("1", Phone.TYPE_HOME, null, false); 225 iterator.addExpectedElement(phoneData); 226 227 property = new VCardProperty(); 228 property.setName("EMAIL"); 229 property.setParameter("TYPE", "WORK"); 230 property.setValues("email"); 231 entry.addProperty(property); 232 EmailData emailData = new EmailData("email", Email.TYPE_WORK, null, false); 233 iterator.addExpectedElement(emailData); 234 235 property = new VCardProperty(); 236 property.setName("ADR"); 237 property.setParameter("TYPE", "HOME"); 238 property.setValues(null, null, "street"); 239 entry.addProperty(property); 240 PostalData postalData = new PostalData(null, null, "street", null, null, null, 241 null, StructuredPostal.TYPE_HOME, null, false, 242 VCardConfig.VCARD_TYPE_DEFAULT); 243 iterator.addExpectedElement(postalData); 244 245 property = new VCardProperty(); 246 property.setName("ORG"); 247 property.setValues("organization", "depertment"); 248 entry.addProperty(property); 249 OrganizationData organizationData = new OrganizationData( 250 "organization", "depertment", null, null, Organization.TYPE_WORK, false); 251 iterator.addExpectedElement(organizationData); 252 253 property = new VCardProperty(); 254 property.setName("X-GOOGLE-TALK"); 255 property.setParameter("TYPE", "WORK"); 256 property.setValues("googletalk"); 257 entry.addProperty(property); 258 ImData imData = new ImData( 259 Im.PROTOCOL_GOOGLE_TALK, null, "googletalk", Im.TYPE_WORK, false); 260 iterator.addExpectedElement(imData); 261 262 property = new VCardProperty(); 263 property.setName("PHOTO"); 264 property.setParameter("TYPE", "PNG"); 265 byte[] photoBytes = new byte[] {1}; 266 property.setByteValue(photoBytes); 267 entry.addProperty(property); 268 PhotoData photoData = new PhotoData("PNG", photoBytes, false); 269 iterator.addExpectedElement(photoData); 270 271 property = new VCardProperty(); 272 property.setName("X-SIP"); 273 property.setValues("sipdata"); 274 entry.addProperty(property); 275 SipData sipData = new SipData("sip:sipdata", SipAddress.TYPE_OTHER, null, false); 276 iterator.addExpectedElement(sipData); 277 278 property = new VCardProperty(); 279 property.setName("NICKNAME"); 280 property.setValues("nickname"); 281 entry.addProperty(property); 282 NicknameData nicknameData = new NicknameData("nickname"); 283 iterator.addExpectedElement(nicknameData); 284 285 property = new VCardProperty(); 286 property.setName("NOTE"); 287 property.setValues("note"); 288 entry.addProperty(property); 289 NoteData noteData = new NoteData("note"); 290 iterator.addExpectedElement(noteData); 291 292 property = new VCardProperty(); 293 property.setName("BDAY"); 294 property.setValues("birthday"); 295 entry.addProperty(property); 296 BirthdayData birthdayData = new BirthdayData("birthday"); 297 iterator.addExpectedElement(birthdayData); 298 299 property = new VCardProperty(); 300 property.setName("ANNIVERSARY"); 301 property.setValues("anniversary"); 302 entry.addProperty(property); 303 AnniversaryData anniversaryData = new AnniversaryData("anniversary"); 304 iterator.addExpectedElement(anniversaryData); 305 306 property = new VCardProperty(); 307 property.setName("X-ANDROID-CUSTOM"); 308 property.setValues("mime;value"); 309 entry.addProperty(property); 310 AndroidCustomData androidCustom = new AndroidCustomData("mime", Arrays.asList("value")); 311 iterator.addExpectedElement(androidCustom); 312 313 entry.iterateAllData(iterator); 314 } 315 testToString()316 public void testToString() { 317 VCardEntry entry = new VCardEntry(); 318 VCardProperty property = new VCardProperty(); 319 property.setName("N"); 320 property.setValues("Family", "Given", "Middle", "Prefix", "Suffix"); 321 entry.addProperty(property); 322 entry.consolidateFields(); 323 324 String result = entry.toString(); 325 assertNotNull(result); 326 327 assertTrue(result.contains(String.valueOf(entry.hashCode()))); 328 assertTrue(result.contains(VCardEntry.EntryLabel.NAME.toString())); 329 assertTrue(result.contains("Family")); 330 assertTrue(result.contains("Given")); 331 assertTrue(result.contains("Middle")); 332 assertTrue(result.contains("Prefix")); 333 assertTrue(result.contains("Suffix")); 334 } 335 336 /** 337 * Tests that VCardEntry emits correct insert operation for name field. 338 */ testConstructInsertOperationsInsertName()339 public void testConstructInsertOperationsInsertName() { 340 VCardEntry entry = new VCardEntry(); 341 VCardProperty property = new VCardProperty(); 342 property.setName("N"); 343 property.setValues("Family", "Given", "Middle", "Prefix", "Suffix"); 344 entry.addProperty(property); 345 entry.consolidateFields(); 346 347 NameData nameData = entry.getNameData(); 348 assertEquals("Family", nameData.getFamily()); 349 assertEquals("Given", nameData.getGiven()); 350 assertEquals("Middle", nameData.getMiddle()); 351 assertEquals("Prefix", nameData.getPrefix()); 352 assertEquals("Suffix", nameData.getSuffix()); 353 354 ContentResolver resolver = getContext().getContentResolver(); 355 ArrayList<ContentProviderOperation> operationList = 356 new ArrayList<ContentProviderOperation>(); 357 entry.constructInsertOperations(resolver, operationList); 358 359 // Need too many details for testing these. Just check basics. 360 // TODO: introduce nice-to-test mechanism here. 361 assertEquals(2, operationList.size()); 362 assertEquals(ContentProviderOperation.TYPE_INSERT, operationList.get(0).getType()); 363 assertEquals(ContentProviderOperation.TYPE_INSERT, operationList.get(1).getType()); 364 } 365 366 /** 367 * Tests that VCardEntry refrains from emitting unnecessary insert operation. 368 */ testConstructInsertOperationsEmptyData()369 public void testConstructInsertOperationsEmptyData() { 370 VCardEntry entry = new VCardEntry(); 371 ContentResolver resolver = getContext().getContentResolver(); 372 ArrayList<ContentProviderOperation> operationList = 373 new ArrayList<ContentProviderOperation>(); 374 entry.constructInsertOperations(resolver, operationList); 375 assertEquals(0, operationList.size()); 376 } 377 378 /** 379 * Tests that VCardEntry can add an account via the constructor 380 */ testConstructor_withAccount_canGetAccount()381 public void testConstructor_withAccount_canGetAccount() { 382 Account account = new Account("test-type", "test-name"); 383 VCardEntry entry = new VCardEntry(VCardConfig.VCARD_TYPE_V21_GENERIC, account); 384 assertEquals(entry.getAccount(), account); 385 } 386 387 /** 388 * Tests that VCardEntry can add a null account via the constructor 389 */ testConstructor_withNullAccount_canGetNullAccount()390 public void testConstructor_withNullAccount_canGetNullAccount() { 391 VCardEntry entry = new VCardEntry(VCardConfig.VCARD_TYPE_V21_GENERIC, null); 392 assertEquals(entry.getAccount(), null); 393 } 394 395 /** 396 * Tests that VCardEntry can add an account via the setter, updating a null account to a value 397 */ testSetAccount_fromNullToValue_canGetAccount()398 public void testSetAccount_fromNullToValue_canGetAccount() { 399 Account account = new Account("test-type", "test-name"); 400 VCardEntry entry = new VCardEntry(); 401 assertEquals(entry.getAccount(), null); 402 entry.setAccount(account); 403 assertEquals(entry.getAccount(), account); 404 } 405 406 /** 407 * Tests that VCardEntry can add an account via the setter, changing one account to another 408 */ testSetAccount_fromToNewValue_canGetAccount()409 public void testSetAccount_fromToNewValue_canGetAccount() { 410 Account account1 = new Account("test-type-1", "test-name-1"); 411 VCardEntry entry = new VCardEntry(VCardConfig.VCARD_TYPE_V21_GENERIC, account1); 412 assertEquals(entry.getAccount(), account1); 413 414 Account account2 = new Account("test-type-2", "test-name-2"); 415 entry.setAccount(account2); 416 assertEquals(entry.getAccount(), account2); 417 } 418 419 /** 420 * Tests that VCardEntry can add an account via the setter, changing one account to another 421 */ testSetAccount_setValueTwice_canGetAccount()422 public void testSetAccount_setValueTwice_canGetAccount() { 423 VCardEntry entry = new VCardEntry(); 424 assertEquals(entry.getAccount(), null); 425 426 Account account1 = new Account("test-type-1", "test-name-1"); 427 entry.setAccount(account1); 428 assertEquals(entry.getAccount(), account1); 429 430 Account account2 = new Account("test-type-2", "test-name-2"); 431 entry.setAccount(account2); 432 assertEquals(entry.getAccount(), account2); 433 } 434 435 // TODO: add bunch of test for constructInsertOperations.. 436 } 437