summaryrefslogtreecommitdiffstats
path: root/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java')
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java959
1 files changed, 959 insertions, 0 deletions
diff --git a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java
new file mode 100644
index 0000000..004a197
--- /dev/null
+++ b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.pim.vcard;
+
+import android.content.ContentValues;
+import android.pim.vcard.VCardConfig;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Event;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Nickname;
+import android.provider.ContactsContract.CommonDataKinds.Note;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.Relation;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
+
+import android.pim.vcard.PropertyNodesVerifierElem.TypeSet;
+
+import java.util.Arrays;
+
+/**
+ * Tests for the code related to vCard exporter, inculding vCard composer.
+ * This test class depends on vCard importer code, so if tests for vCard importer fail,
+ * the result of this class will not be reliable.
+ */
+public class VCardExporterTests extends VCardTestsBase {
+ private static final byte[] sPhotoByteArray =
+ VCardImporterTests.sPhotoByteArrayForComplicatedCase;
+
+ public void testSimpleV21() {
+ mVerifier.initForExportTest(V21);
+ mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "Ando")
+ .put(StructuredName.GIVEN_NAME, "Roid");
+ mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNode("FN", "Roid Ando")
+ .addExpectedNode("N", "Ando;Roid;;;",
+ Arrays.asList("Ando", "Roid", "", "", ""));
+ }
+
+ private void testStructuredNameBasic(int vcardType) {
+ final boolean isV30 = VCardConfig.isV30(vcardType);
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+ .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+ .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+ .put(StructuredName.PREFIX, "AppropriatePrefix")
+ .put(StructuredName.SUFFIX, "AppropriateSuffix")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
+
+ PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNodeWithOrder("N",
+ "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+ + "AppropriatePrefix;AppropriateSuffix",
+ Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+ "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+ .addExpectedNodeWithOrder("FN",
+ "AppropriatePrefix AppropriateGivenName "
+ + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+ .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+ .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+ .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+ if (isV30) {
+ elem.addExpectedNode("SORT-STRING",
+ "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
+ + "AppropriatePhoneticFamily");
+ }
+ }
+
+ public void testStructuredNameBasicV21() {
+ testStructuredNameBasic(V21);
+ }
+
+ public void testStructuredNameBasicV30() {
+ testStructuredNameBasic(V30);
+ }
+
+ /**
+ * Test that only "primary" StructuredName is emitted, so that our vCard file
+ * will not confuse the external importer, assuming there may be some importer
+ * which presume that there's only one property toward each of "N", "FN", etc.
+ * Note that more than one "N", "FN", etc. properties are acceptable in vCard spec.
+ */
+ private void testStructuredNameUsePrimaryCommon(int vcardType) {
+ final boolean isV30 = (vcardType == V30);
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
+ .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
+ .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
+ .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
+ .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+
+ // With "IS_PRIMARY=1". This is what we should use.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+ .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+ .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+ .put(StructuredName.PREFIX, "AppropriatePrefix")
+ .put(StructuredName.SUFFIX, "AppropriateSuffix")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle")
+ .put(StructuredName.IS_PRIMARY, 1);
+
+ // With "IS_PRIMARY=1", but we should ignore this time, since this is second, not first.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
+ .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
+ .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
+ .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
+ .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2")
+ .put(StructuredName.IS_PRIMARY, 1);
+
+ PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNodeWithOrder("N",
+ "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+ + "AppropriatePrefix;AppropriateSuffix",
+ Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+ "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+ .addExpectedNodeWithOrder("FN",
+ "AppropriatePrefix AppropriateGivenName "
+ + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+ .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+ .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+ .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+ if (isV30) {
+ elem.addExpectedNode("SORT-STRING",
+ "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
+ + "AppropriatePhoneticFamily");
+ }
+ }
+
+ public void testStructuredNameUsePrimaryV21() {
+ testStructuredNameUsePrimaryCommon(V21);
+ }
+
+ public void testStructuredNameUsePrimaryV30() {
+ testStructuredNameUsePrimaryCommon(V30);
+ }
+
+ /**
+ * Tests that only "super primary" StructuredName is emitted.
+ * See also the comment in {@link #testStructuredNameUsePrimaryCommon(int)}.
+ */
+ private void testStructuredNameUseSuperPrimaryCommon(int vcardType) {
+ final boolean isV30 = (vcardType == V30);
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
+ .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
+ .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
+ .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
+ .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+
+ // With "IS_PRIMARY=1", but we should ignore this time.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
+ .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
+ .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
+ .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
+ .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2")
+ .put(StructuredName.IS_PRIMARY, 1);
+
+ // With "IS_SUPER_PRIMARY=1". This is what we should use.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+ .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+ .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+ .put(StructuredName.PREFIX, "AppropriatePrefix")
+ .put(StructuredName.SUFFIX, "AppropriateSuffix")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle")
+ .put(StructuredName.IS_SUPER_PRIMARY, 1);
+
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3")
+ .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3")
+ .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3")
+ .put(StructuredName.PREFIX, "DoNotEmitPrefix3")
+ .put(StructuredName.SUFFIX, "DoNotEmitSuffix3")
+ .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3")
+ .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3")
+ .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3")
+ .put(StructuredName.IS_PRIMARY, 1);
+
+ PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNodeWithOrder("N",
+ "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+ + "AppropriatePrefix;AppropriateSuffix",
+ Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+ "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+ .addExpectedNodeWithOrder("FN",
+ "AppropriatePrefix AppropriateGivenName "
+ + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+ .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+ .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+ .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+ if (isV30) {
+ elem.addExpectedNode("SORT-STRING",
+ "AppropriatePhoneticGiven AppropriatePhoneticMiddle"
+ + " AppropriatePhoneticFamily");
+ }
+ }
+
+ public void testStructuredNameUseSuperPrimaryV21() {
+ testStructuredNameUseSuperPrimaryCommon(V21);
+ }
+
+ public void testStructuredNameUseSuperPrimaryV30() {
+ testStructuredNameUseSuperPrimaryCommon(V30);
+ }
+
+ public void testNickNameV30() {
+ mVerifier.initForExportTest(V30);
+ mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
+ .put(Nickname.NAME, "Nicky");
+
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNodeWithOrder("NICKNAME", "Nicky");
+ }
+
+ private void testPhoneBasicCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "1")
+ .put(Phone.TYPE, Phone.TYPE_HOME);
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("TEL", "1", new TypeSet("HOME"));
+ }
+
+ public void testPhoneBasicV21() {
+ testPhoneBasicCommon(V21);
+ }
+
+ public void testPhoneBasicV30() {
+ testPhoneBasicCommon(V30);
+ }
+
+ /**
+ * Tests that vCard composer emits corresponding type param which we expect.
+ */
+ private void testPhoneVariousTypeSupport(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "10")
+ .put(Phone.TYPE, Phone.TYPE_HOME);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "20")
+ .put(Phone.TYPE, Phone.TYPE_WORK);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "30")
+ .put(Phone.TYPE, Phone.TYPE_FAX_HOME);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "40")
+ .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "50")
+ .put(Phone.TYPE, Phone.TYPE_MOBILE);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "60")
+ .put(Phone.TYPE, Phone.TYPE_PAGER);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "70")
+ .put(Phone.TYPE, Phone.TYPE_OTHER);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "80")
+ .put(Phone.TYPE, Phone.TYPE_CAR);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "90")
+ .put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "100")
+ .put(Phone.TYPE, Phone.TYPE_ISDN);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "110")
+ .put(Phone.TYPE, Phone.TYPE_MAIN);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "120")
+ .put(Phone.TYPE, Phone.TYPE_OTHER_FAX);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "130")
+ .put(Phone.TYPE, Phone.TYPE_TELEX);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "140")
+ .put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "150")
+ .put(Phone.TYPE, Phone.TYPE_WORK_PAGER);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "160")
+ .put(Phone.TYPE, Phone.TYPE_MMS);
+
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("TEL", "10", new TypeSet("HOME"))
+ .addExpectedNode("TEL", "20", new TypeSet("WORK"))
+ .addExpectedNode("TEL", "30", new TypeSet("HOME", "FAX"))
+ .addExpectedNode("TEL", "40", new TypeSet("WORK", "FAX"))
+ .addExpectedNode("TEL", "50", new TypeSet("CELL"))
+ .addExpectedNode("TEL", "60", new TypeSet("PAGER"))
+ .addExpectedNode("TEL", "70", new TypeSet("VOICE"))
+ .addExpectedNode("TEL", "80", new TypeSet("CAR"))
+ .addExpectedNode("TEL", "90", new TypeSet("WORK", "PREF"))
+ .addExpectedNode("TEL", "100", new TypeSet("ISDN"))
+ .addExpectedNode("TEL", "110", new TypeSet("PREF"))
+ .addExpectedNode("TEL", "120", new TypeSet("FAX"))
+ .addExpectedNode("TEL", "130", new TypeSet("TLX"))
+ .addExpectedNode("TEL", "140", new TypeSet("WORK", "CELL"))
+ .addExpectedNode("TEL", "150", new TypeSet("WORK", "PAGER"))
+ .addExpectedNode("TEL", "160", new TypeSet("MSG"));
+ }
+
+ public void testPhoneVariousTypeSupportV21() {
+ testPhoneVariousTypeSupport(V21);
+ }
+
+ public void testPhoneVariousTypeSupportV30() {
+ testPhoneVariousTypeSupport(V30);
+ }
+
+ /**
+ * Tests that "PREF"s are emitted appropriately.
+ */
+ private void testPhonePrefHandlingCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "1")
+ .put(Phone.TYPE, Phone.TYPE_HOME);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "2")
+ .put(Phone.TYPE, Phone.TYPE_WORK)
+ .put(Phone.IS_PRIMARY, 1);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "3")
+ .put(Phone.TYPE, Phone.TYPE_FAX_HOME)
+ .put(Phone.IS_PRIMARY, 1);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "4")
+ .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
+
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("TEL", "4", new TypeSet("WORK", "FAX"))
+ .addExpectedNode("TEL", "3", new TypeSet("HOME", "FAX", "PREF"))
+ .addExpectedNode("TEL", "2", new TypeSet("WORK", "PREF"))
+ .addExpectedNode("TEL", "1", new TypeSet("HOME"));
+ }
+
+ public void testPhonePrefHandlingV21() {
+ testPhonePrefHandlingCommon(V21);
+ }
+
+ public void testPhonePrefHandlingV30() {
+ testPhonePrefHandlingCommon(V30);
+ }
+
+ private void testMiscPhoneTypeHandling(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "1")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "Modem");
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "2")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "MSG");
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "3")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "BBS");
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "4")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "VIDEO");
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "5")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM);
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "6")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "_AUTO_CELL"); // The old indicator for the type mobile.
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "7")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "\u643A\u5E2F"); // Mobile phone in Japanese Kanji
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.NUMBER, "8")
+ .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+ .put(Phone.LABEL, "invalid");
+ PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName();
+ elem.addExpectedNode("TEL", "1", new TypeSet("MODEM"))
+ .addExpectedNode("TEL", "2", new TypeSet("MSG"))
+ .addExpectedNode("TEL", "3", new TypeSet("BBS"))
+ .addExpectedNode("TEL", "4", new TypeSet("VIDEO"))
+ .addExpectedNode("TEL", "5", new TypeSet("VOICE"))
+ .addExpectedNode("TEL", "6", new TypeSet("CELL"))
+ .addExpectedNode("TEL", "7", new TypeSet("CELL"))
+ .addExpectedNode("TEL", "8", new TypeSet("X-invalid"));
+ }
+
+ public void testPhoneTypeHandlingV21() {
+ testMiscPhoneTypeHandling(V21);
+ }
+
+ public void testPhoneTypeHandlingV30() {
+ testMiscPhoneTypeHandling(V30);
+ }
+
+ private void testEmailBasicCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "sample@example.com");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("EMAIL", "sample@example.com");
+ }
+
+ public void testEmailBasicV21() {
+ testEmailBasicCommon(V21);
+ }
+
+ public void testEmailBasicV30() {
+ testEmailBasicCommon(V30);
+ }
+
+ private void testEmailVariousTypeSupportCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_home@example.com")
+ .put(Email.TYPE, Email.TYPE_HOME);
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_work@example.com")
+ .put(Email.TYPE, Email.TYPE_WORK);
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_mobile@example.com")
+ .put(Email.TYPE, Email.TYPE_MOBILE);
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_other@example.com")
+ .put(Email.TYPE, Email.TYPE_OTHER);
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME"))
+ .addExpectedNode("EMAIL", "type_work@example.com", new TypeSet("WORK"))
+ .addExpectedNode("EMAIL", "type_mobile@example.com", new TypeSet("CELL"))
+ .addExpectedNode("EMAIL", "type_other@example.com");
+ }
+
+ public void testEmailVariousTypeSupportV21() {
+ testEmailVariousTypeSupportCommon(V21);
+ }
+
+ public void testEmailVariousTypeSupportV30() {
+ testEmailVariousTypeSupportCommon(V30);
+ }
+
+ private void testEmailPrefHandlingCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_home@example.com")
+ .put(Email.TYPE, Email.TYPE_HOME)
+ .put(Email.IS_PRIMARY, 1);
+ entry.addContentValues(Email.CONTENT_ITEM_TYPE)
+ .put(Email.DATA, "type_notype@example.com")
+ .put(Email.IS_PRIMARY, 1);
+
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("EMAIL", "type_notype@example.com", new TypeSet("PREF"))
+ .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF"));
+ }
+
+ public void testEmailPrefHandlingV21() {
+ testEmailPrefHandlingCommon(V21);
+ }
+
+ public void testEmailPrefHandlingV30() {
+ testEmailPrefHandlingCommon(V30);
+ }
+
+ private void testPostalAddressCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
+ .put(StructuredPostal.POBOX, "Pobox")
+ .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood")
+ .put(StructuredPostal.STREET, "Street")
+ .put(StructuredPostal.CITY, "City")
+ .put(StructuredPostal.REGION, "Region")
+ .put(StructuredPostal.POSTCODE, "100")
+ .put(StructuredPostal.COUNTRY, "Country")
+ .put(StructuredPostal.FORMATTED_ADDRESS, "Formatted Address")
+ .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK);
+ // adr-value = 0*6(text-value ";") text-value
+ // ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
+ // ; Country Name
+ //
+ // The NEIGHBORHOOD field is appended after the CITY field.
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("ADR",
+ Arrays.asList("Pobox", "", "Street", "City Neighborhood",
+ "Region", "100", "Country"), new TypeSet("WORK"));
+ }
+
+ public void testPostalAddressV21() {
+ testPostalAddressCommon(V21);
+ }
+
+ public void testPostalAddressV30() {
+ testPostalAddressCommon(V30);
+ }
+
+ private void testPostalAddressNonNeighborhood(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
+ .put(StructuredPostal.CITY, "City");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("ADR",
+ Arrays.asList("", "", "", "City", "", "", ""), new TypeSet("HOME"));
+ }
+
+ public void testPostalAddressNonNeighborhoodV21() {
+ testPostalAddressNonNeighborhood(V21);
+ }
+
+ public void testPostalAddressNonNeighborhoodV30() {
+ testPostalAddressNonNeighborhood(V30);
+ }
+
+ private void testPostalAddressNonCity(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
+ .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("ADR",
+ Arrays.asList("", "", "", "Neighborhood", "", "", ""), new TypeSet("HOME"));
+ }
+
+ public void testPostalAddressNonCityV21() {
+ testPostalAddressNonCity(V21);
+ }
+
+ public void testPostalAddressNonCityV30() {
+ testPostalAddressNonCity(V30);
+ }
+
+ private void testPostalOnlyWithFormattedAddressCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
+ .put(StructuredPostal.REGION, "") // Must be ignored.
+ .put(StructuredPostal.FORMATTED_ADDRESS,
+ "Formatted address CA 123-334 United Statue");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
+ Arrays.asList("", "Formatted address CA 123-334 United Statue",
+ "", "", "", "", ""), new TypeSet("HOME"));
+ }
+
+ public void testPostalOnlyWithFormattedAddressV21() {
+ testPostalOnlyWithFormattedAddressCommon(V21);
+ }
+
+ public void testPostalOnlyWithFormattedAddressV30() {
+ testPostalOnlyWithFormattedAddressCommon(V30);
+ }
+
+ /**
+ * Tests that the vCard composer honors formatted data when it is available
+ * even when it is partial.
+ */
+ private void testPostalWithBothStructuredAndFormattedCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
+ .put(StructuredPostal.POBOX, "Pobox")
+ .put(StructuredPostal.COUNTRY, "Country")
+ .put(StructuredPostal.FORMATTED_ADDRESS,
+ "Formatted address CA 123-334 United Statue"); // Should be ignored
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("ADR", "Pobox;;;;;;Country",
+ Arrays.asList("Pobox", "", "", "", "", "", "Country"),
+ new TypeSet("HOME"));
+ }
+
+ public void testPostalWithBothStructuredAndFormattedV21() {
+ testPostalWithBothStructuredAndFormattedCommon(V21);
+ }
+
+ public void testPostalWithBothStructuredAndFormattedV30() {
+ testPostalWithBothStructuredAndFormattedCommon(V30);
+ }
+
+ private void testOrganizationCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
+ .put(Organization.COMPANY, "CompanyX")
+ .put(Organization.DEPARTMENT, "DepartmentY")
+ .put(Organization.TITLE, "TitleZ")
+ .put(Organization.JOB_DESCRIPTION, "Description Rambda") // Ignored.
+ .put(Organization.OFFICE_LOCATION, "Mountain View") // Ignored.
+ .put(Organization.PHONETIC_NAME, "PhoneticName!") // Ignored
+ .put(Organization.SYMBOL, "(^o^)/~~"); // Ignore him (her).
+ entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
+ .putNull(Organization.COMPANY)
+ .put(Organization.DEPARTMENT, "DepartmentXX")
+ .putNull(Organization.TITLE);
+ entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
+ .put(Organization.COMPANY, "CompanyXYZ")
+ .putNull(Organization.DEPARTMENT)
+ .put(Organization.TITLE, "TitleXYZYX");
+ // Currently we do not use group but depend on the order.
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNodeWithOrder("ORG", "CompanyX;DepartmentY",
+ Arrays.asList("CompanyX", "DepartmentY"))
+ .addExpectedNodeWithOrder("TITLE", "TitleZ")
+ .addExpectedNodeWithOrder("ORG", "DepartmentXX")
+ .addExpectedNodeWithOrder("ORG", "CompanyXYZ")
+ .addExpectedNodeWithOrder("TITLE", "TitleXYZYX");
+ }
+
+ public void testOrganizationV21() {
+ testOrganizationCommon(V21);
+ }
+
+ public void testOrganizationV30() {
+ testOrganizationCommon(V30);
+ }
+
+ private void testImVariousTypeSupportCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+ .put(Im.DATA, "aim");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_MSN)
+ .put(Im.DATA, "msn");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_YAHOO)
+ .put(Im.DATA, "yahoo");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_SKYPE)
+ .put(Im.DATA, "skype");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_QQ)
+ .put(Im.DATA, "qq");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK)
+ .put(Im.DATA, "google talk");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_ICQ)
+ .put(Im.DATA, "icq");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_JABBER)
+ .put(Im.DATA, "jabber");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING)
+ .put(Im.DATA, "netmeeting");
+
+ // No determined way to express unknown type...
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("X-JABBER", "jabber")
+ .addExpectedNode("X-ICQ", "icq")
+ .addExpectedNode("X-GOOGLE-TALK", "google talk")
+ .addExpectedNode("X-QQ", "qq")
+ .addExpectedNode("X-SKYPE-USERNAME", "skype")
+ .addExpectedNode("X-YAHOO", "yahoo")
+ .addExpectedNode("X-MSN", "msn")
+ .addExpectedNode("X-NETMEETING", "netmeeting")
+ .addExpectedNode("X-AIM", "aim");
+ }
+
+ public void testImBasiV21() {
+ testImVariousTypeSupportCommon(V21);
+ }
+
+ public void testImBasicV30() {
+ testImVariousTypeSupportCommon(V30);
+ }
+
+ private void testImPrefHandlingCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+ .put(Im.DATA, "aim1");
+ entry.addContentValues(Im.CONTENT_ITEM_TYPE)
+ .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+ .put(Im.DATA, "aim2")
+ .put(Im.TYPE, Im.TYPE_HOME)
+ .put(Im.IS_PRIMARY, 1);
+
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("X-AIM", "aim1")
+ .addExpectedNode("X-AIM", "aim2", new TypeSet("HOME", "PREF"));
+ }
+
+ public void testImPrefHandlingV21() {
+ testImPrefHandlingCommon(V21);
+ }
+
+ public void testImPrefHandlingV30() {
+ testImPrefHandlingCommon(V30);
+ }
+
+ private void testWebsiteCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Website.CONTENT_ITEM_TYPE)
+ .put(Website.URL, "http://website.example.android.com/index.html")
+ .put(Website.TYPE, Website.TYPE_BLOG);
+ entry.addContentValues(Website.CONTENT_ITEM_TYPE)
+ .put(Website.URL, "ftp://ftp.example.android.com/index.html")
+ .put(Website.TYPE, Website.TYPE_FTP);
+
+ // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it.
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("URL", "ftp://ftp.example.android.com/index.html")
+ .addExpectedNode("URL", "http://website.example.android.com/index.html");
+ }
+
+ public void testWebsiteV21() {
+ testWebsiteCommon(V21);
+ }
+
+ public void testWebsiteV30() {
+ testWebsiteCommon(V30);
+ }
+
+ private String getAndroidPropValue(final String mimeType, String value, Integer type) {
+ return getAndroidPropValue(mimeType, value, type, null);
+ }
+
+ private String getAndroidPropValue(final String mimeType, String value,
+ Integer type, String label) {
+ return (mimeType + ";" + value + ";"
+ + (type != null ? type : "") + ";"
+ + (label != null ? label : "") + ";;;;;;;;;;;;");
+ }
+
+ private void testEventCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Event.CONTENT_ITEM_TYPE)
+ .put(Event.TYPE, Event.TYPE_ANNIVERSARY)
+ .put(Event.START_DATE, "1982-06-16");
+ entry.addContentValues(Event.CONTENT_ITEM_TYPE)
+ .put(Event.TYPE, Event.TYPE_BIRTHDAY)
+ .put(Event.START_DATE, "2008-10-22");
+ entry.addContentValues(Event.CONTENT_ITEM_TYPE)
+ .put(Event.TYPE, Event.TYPE_OTHER)
+ .put(Event.START_DATE, "2018-03-12");
+ entry.addContentValues(Event.CONTENT_ITEM_TYPE)
+ .put(Event.TYPE, Event.TYPE_CUSTOM)
+ .put(Event.LABEL, "The last day")
+ .put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed.");
+ entry.addContentValues(Event.CONTENT_ITEM_TYPE)
+ .put(Event.TYPE, Event.TYPE_BIRTHDAY)
+ .put(Event.START_DATE, "2009-05-19"); // Should be ignored.
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("BDAY", "2008-10-22")
+ .addExpectedNode("X-ANDROID-CUSTOM",
+ getAndroidPropValue(
+ Event.CONTENT_ITEM_TYPE, "1982-06-16", Event.TYPE_ANNIVERSARY))
+ .addExpectedNode("X-ANDROID-CUSTOM",
+ getAndroidPropValue(
+ Event.CONTENT_ITEM_TYPE, "2018-03-12", Event.TYPE_OTHER))
+ .addExpectedNode("X-ANDROID-CUSTOM",
+ getAndroidPropValue(
+ Event.CONTENT_ITEM_TYPE,
+ "When the Tower of Hanoi with 64 rings is completed.",
+ Event.TYPE_CUSTOM, "The last day"));
+ }
+
+ public void testEventV21() {
+ testEventCommon(V21);
+ }
+
+ public void testEventV30() {
+ testEventCommon(V30);
+ }
+
+ private void testNoteCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Note.CONTENT_ITEM_TYPE)
+ .put(Note.NOTE, "note1");
+ entry.addContentValues(Note.CONTENT_ITEM_TYPE)
+ .put(Note.NOTE, "note2")
+ .put(Note.IS_PRIMARY, 1); // Just ignored.
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNodeWithOrder("NOTE", "note1")
+ .addExpectedNodeWithOrder("NOTE", "note2");
+ }
+
+ public void testNoteV21() {
+ testNoteCommon(V21);
+ }
+
+ public void testNoteV30() {
+ testNoteCommon(V30);
+ }
+
+ private void testPhotoCommon(int vcardType) {
+ final boolean isV30 = vcardType == V30;
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "PhotoTest");
+ entry.addContentValues(Photo.CONTENT_ITEM_TYPE)
+ .put(Photo.PHOTO, sPhotoByteArray);
+
+ ContentValues contentValuesForPhoto = new ContentValues();
+ contentValuesForPhoto.put("ENCODING", (isV30 ? "b" : "BASE64"));
+ mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNode("FN", "PhotoTest")
+ .addExpectedNode("N", "PhotoTest;;;;",
+ Arrays.asList("PhotoTest", "", "", "", ""))
+ .addExpectedNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
+ contentValuesForPhoto, new TypeSet("JPEG"), null);
+ }
+
+ public void testPhotoV21() {
+ testPhotoCommon(V21);
+ }
+
+ public void testPhotoV30() {
+ testPhotoCommon(V30);
+ }
+
+ private void testRelationCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ mVerifier.addInputEntry().addContentValues(Relation.CONTENT_ITEM_TYPE)
+ .put(Relation.TYPE, Relation.TYPE_MOTHER)
+ .put(Relation.NAME, "Ms. Mother");
+ mVerifier.addContentValuesVerifierElem().addExpected(Relation.CONTENT_ITEM_TYPE)
+ .put(Relation.TYPE, Relation.TYPE_MOTHER)
+ .put(Relation.NAME, "Ms. Mother");
+ }
+
+ public void testRelationV21() {
+ testRelationCommon(V21);
+ }
+
+ public void testRelationV30() {
+ testRelationCommon(V30);
+ }
+
+ public void testV30HandleEscape() {
+ mVerifier.initForExportTest(V30);
+ mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "\\")
+ .put(StructuredName.GIVEN_NAME, ";")
+ .put(StructuredName.MIDDLE_NAME, ",")
+ .put(StructuredName.PREFIX, "\n")
+ .put(StructuredName.DISPLAY_NAME, "[<{Unescaped:Asciis}>]");
+ // Verifies the vCard String correctly escapes each character which must be escaped.
+ mVerifier.addLineVerifierElem()
+ .addExpected("N:\\\\;\\;;\\,;\\n;")
+ .addExpected("FN:[<{Unescaped:Asciis}>]");
+ mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNode("FN", "[<{Unescaped:Asciis}>]")
+ .addExpectedNode("N", Arrays.asList("\\", ";", ",", "\n", ""));
+ }
+
+ /**
+ * There's no "NICKNAME" property in vCard 2.1, while there is in vCard 3.0.
+ * We use Android-specific "X-ANDROID-CUSTOM" property.
+ * This test verifies the functionality.
+ */
+ public void testNickNameV21() {
+ mVerifier.initForExportTest(V21);
+ mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
+ .put(Nickname.NAME, "Nicky");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("X-ANDROID-CUSTOM",
+ Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;");
+ mVerifier.addContentValuesVerifierElem().addExpected(Nickname.CONTENT_ITEM_TYPE)
+ .put(Nickname.NAME, "Nicky");
+ }
+
+ public void testTolerateBrokenPhoneNumberEntryV21() {
+ mVerifier.initForExportTest(V21);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
+ .put(Phone.TYPE, Phone.TYPE_HOME)
+ .put(Phone.NUMBER, "111-222-3333 (Miami)\n444-5555-666 (Tokyo);"
+ + "777-888-9999 (Chicago);111-222-3333 (Miami)");
+ mVerifier.addPropertyNodesVerifierElemWithEmptyName()
+ .addExpectedNode("TEL", "111-222-3333", new TypeSet("HOME"))
+ .addExpectedNode("TEL", "444-555-5666", new TypeSet("HOME"))
+ .addExpectedNode("TEL", "777-888-9999", new TypeSet("HOME"));
+ }
+
+ private void testPickUpNonEmptyContentValuesCommon(int vcardType) {
+ mVerifier.initForExportTest(vcardType);
+ ContactEntry entry = mVerifier.addInputEntry();
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.IS_PRIMARY, 1); // Empty name. Should be ignored.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "family1"); // Not primary. Should be ignored.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.IS_PRIMARY, 1)
+ .put(StructuredName.FAMILY_NAME, "family2"); // This entry is what we want.
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.IS_PRIMARY, 1)
+ .put(StructuredName.FAMILY_NAME, "family3");
+ entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
+ .put(StructuredName.FAMILY_NAME, "family4");
+ mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNode("N", Arrays.asList("family2", "", "", "", ""))
+ .addExpectedNode("FN", "family2");
+ }
+
+ public void testPickUpNonEmptyContentValuesV21() {
+ testPickUpNonEmptyContentValuesCommon(V21);
+ }
+
+ public void testPickUpNonEmptyContentValuesV30() {
+ testPickUpNonEmptyContentValuesCommon(V30);
+ }
+}