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.content.ContentProviderOperation; 42 import android.content.ContentResolver; 43 import android.provider.ContactsContract.CommonDataKinds.Email; 44 import android.provider.ContactsContract.CommonDataKinds.Im; 45 import android.provider.ContactsContract.CommonDataKinds.Organization; 46 import android.provider.ContactsContract.CommonDataKinds.Phone; 47 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 48 import android.provider.ContactsContract.CommonDataKinds.SipAddress; 49 import android.test.AndroidTestCase; 50 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.HashMap; 54 import java.util.List; 55 import java.util.Map; 56 57 public class VCardEntryTests extends AndroidTestCase { 58 private class MockVCardEntryHandler implements VCardEntryHandler { 59 private List<VCardEntry> mEntries = new ArrayList<VCardEntry>(); 60 private boolean mOnStartCalled; 61 private boolean mOnEndCalled; 62 63 @Override 64 public void onStart() { 65 assertFalse(mOnStartCalled); 66 mOnStartCalled = true; 67 } 68 69 @Override 70 public void onEntryCreated(VCardEntry entry) { 71 assertTrue(mOnStartCalled); 72 assertFalse(mOnEndCalled); 73 mEntries.add(entry); 74 } 75 76 @Override 77 public void onEnd() { 78 assertTrue(mOnStartCalled); 79 assertFalse(mOnEndCalled); 80 mOnEndCalled = true; 81 } 82 83 public List<VCardEntry> getEntries() { 84 return mEntries; 85 } 86 } 87 88 /** 89 * Tests VCardEntry and related clasess can handle nested classes given 90 * {@link VCardInterpreter} is called appropriately. 91 * 92 * This test manually calls VCardInterpreter's callback mechanism and checks 93 * {@link VCardEntryConstructor} constructs {@link VCardEntry} per given calls. 94 * 95 * Intended vCard is as follows: 96 * <code> 97 * BEGIN:VCARD 98 * N:test1 99 * BEGIN:VCARD 100 * N:test2 101 * END:VCARD 102 * TEL:1 103 * END:VCARD 104 * </code> 105 */ 106 public void testNestHandling() { 107 VCardEntryConstructor entryConstructor = new VCardEntryConstructor(); 108 MockVCardEntryHandler entryHandler = new MockVCardEntryHandler(); 109 entryConstructor.addEntryHandler(entryHandler); 110 111 entryConstructor.onVCardStarted(); 112 entryConstructor.onEntryStarted(); 113 VCardProperty property = new VCardProperty(); 114 property.setName(VCardConstants.PROPERTY_N); 115 property.setValues("test1"); 116 entryConstructor.onPropertyCreated(property); 117 118 entryConstructor.onEntryStarted(); // begin nest 119 property = new VCardProperty(); 120 property.setName(VCardConstants.PROPERTY_N); 121 property.setValues("test2"); 122 entryConstructor.onPropertyCreated(property); 123 entryConstructor.onEntryEnded(); // end nest 124 125 property = new VCardProperty(); 126 property.setName(VCardConstants.PROPERTY_TEL); 127 property.setValues("1"); 128 entryConstructor.onPropertyCreated(property); 129 entryConstructor.onEntryEnded(); 130 entryConstructor.onVCardEnded(); 131 132 List<VCardEntry> entries = entryHandler.getEntries(); 133 assertEquals(2, entries.size()); 134 VCardEntry parent = entries.get(1); 135 VCardEntry child = entries.get(0); 136 assertEquals("test1", parent.getDisplayName()); 137 assertEquals("test2", child.getDisplayName()); 138 List<VCardEntry.PhoneData> phoneList = parent.getPhoneList(); 139 assertNotNull(phoneList); 140 assertEquals(1, phoneList.size()); 141 assertEquals("1", phoneList.get(0).getNumber()); 142 } 143 144 private class MockEntryElementIterator implements VCardEntry.EntryElementIterator { 145 private boolean mStartCalled; 146 private boolean mEndCalled; 147 private EntryLabel mLabel; 148 private final Map<EntryLabel, EntryElement> mExpectedElements = 149 new HashMap<EntryLabel, EntryElement>(); 150 151 public void addExpectedElement(EntryElement elem) { 152 mExpectedElements.put(elem.getEntryLabel(), elem); 153 } 154 155 @Override 156 public void onIterationStarted() { 157 assertFalse(mStartCalled); 158 assertFalse(mEndCalled); 159 assertNull(mLabel); 160 mStartCalled = true; 161 } 162 163 @Override 164 public void onIterationEnded() { 165 assertTrue(mStartCalled); 166 assertFalse(mEndCalled); 167 assertNull(mLabel); 168 assertTrue("Expected Elements remaining: " + 169 Arrays.toString(mExpectedElements.values().toArray()), 170 mExpectedElements.isEmpty()); 171 } 172 173 @Override 174 public void onElementGroupStarted(EntryLabel label) { 175 assertTrue(mStartCalled); 176 assertFalse(mEndCalled); 177 assertNull(mLabel); 178 mLabel = label; 179 } 180 181 @Override 182 public void onElementGroupEnded() { 183 assertTrue(mStartCalled); 184 assertFalse(mEndCalled); 185 assertNotNull(mLabel); 186 mLabel = null; 187 } 188 189 @Override 190 public boolean onElement(EntryElement elem) { 191 EntryElement expectedElem = mExpectedElements.remove(elem.getEntryLabel()); 192 assertNotNull("Unexpected elem: " + elem.toString(), expectedElem); 193 assertEquals(expectedElem, elem); 194 return true; 195 } 196 } 197 198 /** 199 * Tests every element in VCardEntry is iterated by 200 * {@link VCardEntry#iterateAllData(com.android.vcard.VCardEntry.EntryElementIterator)}. 201 */ 202 public void testEntryElementIterator() { 203 VCardEntry entry = new VCardEntry(); 204 MockEntryElementIterator iterator = new MockEntryElementIterator(); 205 206 VCardProperty property = new VCardProperty(); 207 property.setName("N"); 208 property.setValues("family", "given", "middle", "prefix", "suffix"); 209 entry.addProperty(property); 210 NameData nameData = new NameData(); 211 nameData.setFamily("family"); 212 nameData.setGiven("given"); 213 nameData.setMiddle("middle"); 214 nameData.setPrefix("prefix"); 215 nameData.setSuffix("suffix"); 216 iterator.addExpectedElement(nameData); 217 218 property = new VCardProperty(); 219 property.setName("TEL"); 220 property.setParameter("TYPE", "HOME"); 221 property.setValues("1"); 222 entry.addProperty(property); 223 PhoneData phoneData = new PhoneData("1", Phone.TYPE_HOME, null, false); 224 iterator.addExpectedElement(phoneData); 225 226 property = new VCardProperty(); 227 property.setName("EMAIL"); 228 property.setParameter("TYPE", "WORK"); 229 property.setValues("email"); 230 entry.addProperty(property); 231 EmailData emailData = new EmailData("email", Email.TYPE_WORK, null, false); 232 iterator.addExpectedElement(emailData); 233 234 property = new VCardProperty(); 235 property.setName("ADR"); 236 property.setParameter("TYPE", "HOME"); 237 property.setValues(null, null, "street"); 238 entry.addProperty(property); 239 PostalData postalData = new PostalData(null, null, "street", null, null, null, 240 null, StructuredPostal.TYPE_HOME, null, false, 241 VCardConfig.VCARD_TYPE_DEFAULT); 242 iterator.addExpectedElement(postalData); 243 244 property = new VCardProperty(); 245 property.setName("ORG"); 246 property.setValues("organization", "depertment"); 247 entry.addProperty(property); 248 OrganizationData organizationData = new OrganizationData( 249 "organization", "depertment", null, null, Organization.TYPE_WORK, false); 250 iterator.addExpectedElement(organizationData); 251 252 property = new VCardProperty(); 253 property.setName("X-GOOGLE-TALK"); 254 property.setParameter("TYPE", "WORK"); 255 property.setValues("googletalk"); 256 entry.addProperty(property); 257 ImData imData = new ImData( 258 Im.PROTOCOL_GOOGLE_TALK, null, "googletalk", Im.TYPE_WORK, false); 259 iterator.addExpectedElement(imData); 260 261 property = new VCardProperty(); 262 property.setName("PHOTO"); 263 property.setParameter("TYPE", "PNG"); 264 byte[] photoBytes = new byte[] {1}; 265 property.setByteValue(photoBytes); 266 entry.addProperty(property); 267 PhotoData photoData = new PhotoData("PNG", photoBytes, false); 268 iterator.addExpectedElement(photoData); 269 270 property = new VCardProperty(); 271 property.setName("X-SIP"); 272 property.setValues("sipdata"); 273 entry.addProperty(property); 274 SipData sipData = new SipData("sip:sipdata", SipAddress.TYPE_OTHER, null, false); 275 iterator.addExpectedElement(sipData); 276 277 property = new VCardProperty(); 278 property.setName("NICKNAME"); 279 property.setValues("nickname"); 280 entry.addProperty(property); 281 NicknameData nicknameData = new NicknameData("nickname"); 282 iterator.addExpectedElement(nicknameData); 283 284 property = new VCardProperty(); 285 property.setName("NOTE"); 286 property.setValues("note"); 287 entry.addProperty(property); 288 NoteData noteData = new NoteData("note"); 289 iterator.addExpectedElement(noteData); 290 291 property = new VCardProperty(); 292 property.setName("BDAY"); 293 property.setValues("birthday"); 294 entry.addProperty(property); 295 BirthdayData birthdayData = new BirthdayData("birthday"); 296 iterator.addExpectedElement(birthdayData); 297 298 property = new VCardProperty(); 299 property.setName("ANNIVERSARY"); 300 property.setValues("anniversary"); 301 entry.addProperty(property); 302 AnniversaryData anniversaryData = new AnniversaryData("anniversary"); 303 iterator.addExpectedElement(anniversaryData); 304 305 property = new VCardProperty(); 306 property.setName("X-ANDROID-CUSTOM"); 307 property.setValues("mime;value"); 308 entry.addProperty(property); 309 AndroidCustomData androidCustom = new AndroidCustomData("mime", Arrays.asList("value")); 310 iterator.addExpectedElement(androidCustom); 311 312 entry.iterateAllData(iterator); 313 } 314 315 public void testToString() { 316 VCardEntry entry = new VCardEntry(); 317 VCardProperty property = new VCardProperty(); 318 property.setName("N"); 319 property.setValues("Family", "Given", "Middle", "Prefix", "Suffix"); 320 entry.addProperty(property); 321 entry.consolidateFields(); 322 323 String result = entry.toString(); 324 assertNotNull(result); 325 326 assertTrue(result.contains(String.valueOf(entry.hashCode()))); 327 assertTrue(result.contains(VCardEntry.EntryLabel.NAME.toString())); 328 assertTrue(result.contains("Family")); 329 assertTrue(result.contains("Given")); 330 assertTrue(result.contains("Middle")); 331 assertTrue(result.contains("Prefix")); 332 assertTrue(result.contains("Suffix")); 333 } 334 335 /** 336 * Tests that VCardEntry emits correct insert operation for name field. 337 */ 338 public void testConstructInsertOperationsInsertName() { 339 VCardEntry entry = new VCardEntry(); 340 VCardProperty property = new VCardProperty(); 341 property.setName("N"); 342 property.setValues("Family", "Given", "Middle", "Prefix", "Suffix"); 343 entry.addProperty(property); 344 entry.consolidateFields(); 345 346 NameData nameData = entry.getNameData(); 347 assertEquals("Family", nameData.getFamily()); 348 assertEquals("Given", nameData.getGiven()); 349 assertEquals("Middle", nameData.getMiddle()); 350 assertEquals("Prefix", nameData.getPrefix()); 351 assertEquals("Suffix", nameData.getSuffix()); 352 353 ContentResolver resolver = getContext().getContentResolver(); 354 ArrayList<ContentProviderOperation> operationList = 355 new ArrayList<ContentProviderOperation>(); 356 entry.constructInsertOperations(resolver, operationList); 357 358 // Need too many details for testing these. Just check basics. 359 // TODO: introduce nice-to-test mechanism here. 360 assertEquals(2, operationList.size()); 361 assertEquals(ContentProviderOperation.TYPE_INSERT, operationList.get(0).getType()); 362 assertEquals(ContentProviderOperation.TYPE_INSERT, operationList.get(1).getType()); 363 } 364 365 /** 366 * Tests that VCardEntry refrains from emitting unnecessary insert operation. 367 */ 368 public void testConstructInsertOperationsEmptyData() { 369 VCardEntry entry = new VCardEntry(); 370 ContentResolver resolver = getContext().getContentResolver(); 371 ArrayList<ContentProviderOperation> operationList = 372 new ArrayList<ContentProviderOperation>(); 373 entry.constructInsertOperations(resolver, operationList); 374 assertEquals(0, operationList.size()); 375 } 376 377 // TODO: add bunch of test for constructInsertOperations.. 378 }