From 592988d307e8d305ca163c4e58da0fb350054194 Mon Sep 17 00:00:00 2001 From: Daisuke Miyakawa Date: Thu, 12 Nov 2009 11:19:06 +0900 Subject: [PATCH] Add unit tests for Japanization and fix several bugs. Internal issue number: 2195990 --- .../java/android/pim/vcard/ContactStruct.java | 84 ++++++++++------ .../java/android/pim/vcard/VCardComposer.java | 82 +++++++++++----- core/java/android/pim/vcard/VCardConfig.java | 39 ++++---- core/java/android/pim/vcard/VCardUtils.java | 70 +++++++------ .../res/raw/v21_invalid_comment_line.vcf | 10 ++ .../vcard/PropertyNodesVerifier.java | 12 +++ .../unit_tests/vcard/VCardExporterTests.java | 36 +++---- .../unit_tests/vcard/VCardImporterTests.java | 20 +++- .../vcard/VCardJapanizationTests.java | 98 +++++++++++++++++++ .../unit_tests/vcard/VCardTestsBase.java | 20 ++-- 10 files changed, 334 insertions(+), 137 deletions(-) create mode 100644 tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java index f01659e86edaf..530d5ad3c8d52 100644 --- a/core/java/android/pim/vcard/ContactStruct.java +++ b/core/java/android/pim/vcard/ContactStruct.java @@ -20,8 +20,10 @@ import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.OperationApplicationException; import android.database.Cursor; +import android.net.Uri; import android.os.RemoteException; import android.provider.ContactsContract; +import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; @@ -675,16 +677,53 @@ public class ContactStruct { */ @SuppressWarnings("fallthrough") private void handlePhoneticNameFromSound(List elems) { - // Family, Given, Middle. (1-3) - // This is not from specification but mere assumption. Some Japanese phones use this order. + if (!(TextUtils.isEmpty(mPhoneticFamilyName) && + TextUtils.isEmpty(mPhoneticMiddleName) && + TextUtils.isEmpty(mPhoneticGivenName))) { + // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found. + // Ignore "SOUND;X-IRMC-N". + return; + } + int size; if (elems == null || (size = elems.size()) < 1) { return; } + + // Assume that the order is "Family, Given, Middle". + // This is not from specification but mere assumption. Some Japanese phones use this order. if (size > 3) { size = 3; } + if (elems.get(0).length() > 0) { + boolean onlyFirstElemIsNonEmpty = true; + for (int i = 1; i < size; i++) { + if (elems.get(i).length() > 0) { + onlyFirstElemIsNonEmpty = false; + break; + } + } + if (onlyFirstElemIsNonEmpty) { + final String[] namesArray = elems.get(0).split(" "); + final int nameArrayLength = namesArray.length; + if (nameArrayLength == 3) { + // Assume the string is "Family Middle Given". + mPhoneticFamilyName = namesArray[0]; + mPhoneticMiddleName = namesArray[1]; + mPhoneticGivenName = namesArray[2]; + } else if (nameArrayLength == 2) { + // Assume the string is "Family Given" based on the Japanese mobile + // phones' preference. + mPhoneticFamilyName = namesArray[0]; + mPhoneticGivenName = namesArray[1]; + } else { + mPhoneticFullName = elems.get(0); + } + return; + } + } + switch (size) { // fallthrough case 3: @@ -976,36 +1015,8 @@ public class ContactStruct { if (!TextUtils.isEmpty(mFullName)) { mDisplayName = mFullName; } else if (!(TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mGivenName))) { - StringBuilder builder = new StringBuilder(); - List nameList; - switch (VCardConfig.getNameOrderType(mVCardType)) { - case VCardConfig.NAME_ORDER_JAPANESE: - if (VCardUtils.containsOnlyPrintableAscii(mFamilyName) && - VCardUtils.containsOnlyPrintableAscii(mGivenName)) { - nameList = Arrays.asList(mPrefix, mGivenName, mMiddleName, mFamilyName, mSuffix); - } else { - nameList = Arrays.asList(mPrefix, mFamilyName, mMiddleName, mGivenName, mSuffix); - } - break; - case VCardConfig.NAME_ORDER_EUROPE: - nameList = Arrays.asList(mPrefix, mMiddleName, mGivenName, mFamilyName, mSuffix); - break; - default: - nameList = Arrays.asList(mPrefix, mGivenName, mMiddleName, mFamilyName, mSuffix); - break; - } - boolean first = true; - for (String namePart : nameList) { - if (!TextUtils.isEmpty(namePart)) { - if (first) { - first = false; - } else { - builder.append(' '); - } - builder.append(namePart); - } - } - mDisplayName = builder.toString(); + mDisplayName = VCardUtils.constructNameFromElements(mVCardType, + mFamilyName, mMiddleName, mGivenName, mPrefix, mSuffix); } else if (!(TextUtils.isEmpty(mPhoneticFamilyName) && TextUtils.isEmpty(mPhoneticGivenName))) { mDisplayName = VCardUtils.constructNameFromElements(mVCardType, @@ -1282,6 +1293,15 @@ public class ContactStruct { } } + public static ContactStruct buildFromResolver(ContentResolver resolver) { + return buildFromResolver(resolver, Contacts.CONTENT_URI); + } + + public static ContactStruct buildFromResolver(ContentResolver resolver, Uri uri) { + + return null; + } + private boolean nameFieldsAreEmpty() { return (TextUtils.isEmpty(mFamilyName) && TextUtils.isEmpty(mMiddleName) diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index 980dd05d7bd06..b7ad7df720ad7 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -682,10 +682,18 @@ public class VCardComposer { final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME); final String prefix = contentValues.getAsString(StructuredName.PREFIX); final String suffix = contentValues.getAsString(StructuredName.SUFFIX); + final String phoneticFamilyName = + contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME); + final String phoneticMiddleName = + contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME); + final String phoneticGivenName = + contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME); final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME); return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) && TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) && - TextUtils.isEmpty(suffix) && TextUtils.isEmpty(displayName)); + TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) && + TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) && + TextUtils.isEmpty(displayName)); } private void appendStructuredNamesInternal(final StringBuilder builder, @@ -865,17 +873,18 @@ public class VCardComposer { builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_END_OF_LINE); - if (mIsV30) { - builder.append(Constants.PROPERTY_FN); - // TODO: Not allowed formally... - if (shouldAppendCharsetParameter(displayName)) { - builder.append(VCARD_PARAM_SEPARATOR); - builder.append(mVCardCharsetParameter); - } - builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedDisplayName); - builder.append(VCARD_END_OF_LINE); + builder.append(Constants.PROPERTY_FN); + + // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it + // when it would be useful for external importers, assuming no external + // importer allows this vioration. + if (shouldAppendCharsetParameter(displayName)) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(mVCardCharsetParameter); } + builder.append(VCARD_DATA_SEPARATOR); + builder.append(encodedDisplayName); + builder.append(VCARD_END_OF_LINE); } else if (mIsV30) { // vCard 3.0 specification requires these fields. appendVCardLine(builder, Constants.PROPERTY_N, ""); @@ -913,15 +922,12 @@ public class VCardComposer { .constructNameFromElements(mVCardType, phoneticFamilyName, phoneticMiddleName, phoneticGivenName); builder.append(Constants.PROPERTY_SORT_STRING); - - // Do not need to care about QP, since vCard 3.0 does not allow it. - final String encodedSortString = escapeCharacters(sortString); - if (shouldAppendCharsetParameter(encodedSortString)) { + if (shouldAppendCharsetParameter(sortString)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedSortString); + builder.append(escapeCharacters(sortString)); builder.append(VCARD_END_OF_LINE); } else if (mIsJapaneseMobilePhone) { // Note: There is no appropriate property for expressing @@ -964,11 +970,31 @@ public class VCardComposer { builder.append(mVCardCharsetParameter); } builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedPhoneticFamilyName); + // DoCoMo's specification requires vCard composer to use just the first + // column. + { + boolean first = true; + if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) { + builder.append(encodedPhoneticFamilyName); + first = false; + } + if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) { + if (first) { + first = false; + } else { + builder.append(' '); + } + builder.append(encodedPhoneticMiddleName); + } + if (!TextUtils.isEmpty(encodedPhoneticGivenName)) { + if (!first) { + builder.append(' '); + } + builder.append(encodedPhoneticGivenName); + } + } builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedPhoneticGivenName); builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedPhoneticMiddleName); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_END_OF_LINE); @@ -988,7 +1014,8 @@ public class VCardComposer { if (mUsesDefactProperty) { if (!TextUtils.isEmpty(phoneticGivenName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); final String encodedPhoneticGivenName; if (reallyUseQuotedPrintable) { encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); @@ -996,7 +1023,7 @@ public class VCardComposer { encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); } builder.append(Constants.PROPERTY_X_PHONETIC_FIRST_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticGivenName)) { + if (shouldAppendCharsetParameter(phoneticGivenName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -1010,7 +1037,8 @@ public class VCardComposer { } if (!TextUtils.isEmpty(phoneticMiddleName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); final String encodedPhoneticMiddleName; if (reallyUseQuotedPrintable) { encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); @@ -1018,7 +1046,7 @@ public class VCardComposer { encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); } builder.append(Constants.PROPERTY_X_PHONETIC_MIDDLE_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticMiddleName)) { + if (shouldAppendCharsetParameter(phoneticMiddleName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -1032,7 +1060,8 @@ public class VCardComposer { } if (!TextUtils.isEmpty(phoneticFamilyName)) { final boolean reallyUseQuotedPrintable = - !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName); + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); final String encodedPhoneticFamilyName; if (reallyUseQuotedPrintable) { encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); @@ -1040,7 +1069,7 @@ public class VCardComposer { encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); } builder.append(Constants.PROPERTY_X_PHONETIC_LAST_NAME); - if (shouldAppendCharsetParameter(encodedPhoneticFamilyName)) { + if (shouldAppendCharsetParameter(phoneticFamilyName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -2255,8 +2284,7 @@ public class VCardComposer { * to know this text is NOT UTF-8 but Shift_Jis. */ private boolean shouldAppendCharsetParameter(final String propertyValue) { - return (!VCardUtils.containsOnlyPrintableAscii(propertyValue) && - (!mIsV30 || !mUsesUtf8)); + return (!(mIsV30 && mUsesUtf8) && !VCardUtils.containsOnlyPrintableAscii(propertyValue)); } private boolean shouldAppendCharsetParameters(final List propertyValueList) { diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index 545c09ba5c963..fff4c82dbea8d 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -60,7 +60,8 @@ public class VCardConfig { // 0x10 is reserved for safety private static final int FLAG_CHARSET_UTF8 = 0; - private static final int FLAG_CHARSET_SHIFT_JIS = 0x20; + private static final int FLAG_CHARSET_SHIFT_JIS = 0x100; + private static final int FLAG_CHARSET_MASK = 0xF00; /** * The flag indicating the vCard composer will add some "X-" properties used only in Android @@ -349,8 +350,8 @@ public class VCardConfig { sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO); } - public static int getVCardTypeFromString(String vcardTypeString) { - String loweredKey = vcardTypeString.toLowerCase(); + public static int getVCardTypeFromString(final String vcardTypeString) { + final String loweredKey = vcardTypeString.toLowerCase(); if (sVCardTypeMap.containsKey(loweredKey)) { return sVCardTypeMap.get(loweredKey); } else { @@ -360,31 +361,31 @@ public class VCardConfig { } } - public static boolean isV30(int vcardType) { + public static boolean isV30(final int vcardType) { return ((vcardType & FLAG_V30) != 0); } - public static boolean usesQuotedPrintable(int vcardType) { + public static boolean usesQuotedPrintable(final int vcardType) { return !isV30(vcardType); } - public static boolean usesUtf8(int vcardType) { - return ((vcardType & FLAG_CHARSET_UTF8) != 0); + public static boolean usesUtf8(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_UTF8); } - public static boolean usesShiftJis(int vcardType) { - return ((vcardType & FLAG_CHARSET_SHIFT_JIS) != 0); + public static boolean usesShiftJis(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_SHIFT_JIS); } - - public static int getNameOrderType(int vcardType) { + + public static int getNameOrderType(final int vcardType) { return vcardType & NAME_ORDER_MASK; } - public static boolean usesAndroidSpecificProperty(int vcardType) { + public static boolean usesAndroidSpecificProperty(final int vcardType) { return ((vcardType & FLAG_USE_ANDROID_PROPERTY) != 0); } - public static boolean usesDefactProperty(int vcardType) { + public static boolean usesDefactProperty(final int vcardType) { return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0); } @@ -392,12 +393,12 @@ public class VCardConfig { return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0; } - public static boolean refrainsQPToPrimaryProperties(int vcardType) { + public static boolean refrainsQPToPrimaryProperties(final int vcardType) { return (!usesQuotedPrintable(vcardType) || ((vcardType & FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES) != 0)); } - public static boolean appendTypeParamName(int vcardType) { + public static boolean appendTypeParamName(final int vcardType) { return (isV30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0)); } @@ -405,19 +406,19 @@ public class VCardConfig { * @return true if the device is Japanese and some Japanese convension is * applied to creating "formatted" something like FORMATTED_ADDRESS. */ - public static boolean isJapaneseDevice(int vcardType) { + public static boolean isJapaneseDevice(final int vcardType) { return sJapaneseMobileTypeSet.contains(vcardType); } - public static boolean needsToConvertPhoneticString(int vcardType) { + public static boolean needsToConvertPhoneticString(final int vcardType) { return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0); } - public static boolean onlyOneNoteFieldIsAvailable(int vcardType) { + public static boolean onlyOneNoteFieldIsAvailable(final int vcardType) { return vcardType == VCARD_TYPE_DOCOMO; } - public static boolean isDoCoMo(int vcardType) { + public static boolean isDoCoMo(final int vcardType) { return ((vcardType & FLAG_DOCOMO) != 0); } diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java index 9e5dbb5f87889..00679bd82cd8b 100644 --- a/core/java/android/pim/vcard/VCardUtils.java +++ b/core/java/android/pim/vcard/VCardUtils.java @@ -23,6 +23,7 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; +import android.util.Log; import java.util.ArrayList; import java.util.Collection; @@ -181,26 +182,36 @@ public class VCardUtils { sPhoneTypesSetUnknownToContacts.contains(phoneType)); } - public static String[] sortNameElements(int vcardType, - String familyName, String middleName, String givenName) { - String[] list = new String[3]; - switch (VCardConfig.getNameOrderType(vcardType)) { - case VCardConfig.NAME_ORDER_JAPANESE: - // TODO: Should handle Ascii case? - list[0] = familyName; - list[1] = middleName; - list[2] = givenName; - break; - case VCardConfig.NAME_ORDER_EUROPE: - list[0] = middleName; - list[1] = givenName; - list[2] = familyName; - break; - default: - list[0] = givenName; - list[1] = middleName; - list[2] = familyName; - break; + public static String[] sortNameElements(final int vcardType, + final String familyName, final String middleName, final String givenName) { + final String[] list = new String[3]; + final int nameOrderType = VCardConfig.getNameOrderType(vcardType); + switch (nameOrderType) { + case VCardConfig.NAME_ORDER_JAPANESE: { + if (containsOnlyPrintableAscii(familyName) && + containsOnlyPrintableAscii(givenName)) { + list[0] = givenName; + list[1] = middleName; + list[2] = familyName; + } else { + list[0] = familyName; + list[1] = middleName; + list[2] = givenName; + } + break; + } + case VCardConfig.NAME_ORDER_EUROPE: { + list[0] = middleName; + list[1] = givenName; + list[2] = familyName; + break; + } + default: { + list[0] = givenName; + list[1] = middleName; + list[2] = familyName; + break; + } } return list; } @@ -302,24 +313,23 @@ public class VCardUtils { return dataArray; } - public static String constructNameFromElements(int nameOrderType, - String familyName, String middleName, String givenName) { - return constructNameFromElements(nameOrderType, familyName, middleName, givenName, + public static String constructNameFromElements(final int vcardType, + final String familyName, final String middleName, final String givenName) { + return constructNameFromElements(vcardType, familyName, middleName, givenName, null, null); } - public static String constructNameFromElements(int nameOrderType, - String familyName, String middleName, String givenName, - String prefix, String suffix) { - StringBuilder builder = new StringBuilder(); - String[] nameList = sortNameElements(nameOrderType, - familyName, middleName, givenName); + public static String constructNameFromElements(final int vcardType, + final String familyName, final String middleName, final String givenName, + final String prefix, final String suffix) { + final StringBuilder builder = new StringBuilder(); + final String[] nameList = sortNameElements(vcardType, familyName, middleName, givenName); boolean first = true; if (!TextUtils.isEmpty(prefix)) { first = false; builder.append(prefix); } - for (String namePart : nameList) { + for (final String namePart : nameList) { if (!TextUtils.isEmpty(namePart)) { if (first) { first = false; diff --git a/tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf b/tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf new file mode 100644 index 0000000000000..f910710af6d3b --- /dev/null +++ b/tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf @@ -0,0 +1,10 @@ +BEGIN:vCard +VERSION:2.1 +UID:357 +N:;Conference Call +FN:Conference Call +# This line must be ignored. +NOTE;ENCODING=QUOTED-PRINTABLE:This is an (sharp ->= +#<- sharp) example. This message must NOT be ignored. +# This line must be ignored too. +END:vCard diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java index a9775fadf8331..1d4589347a786 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java @@ -162,6 +162,12 @@ class PropertyNodesVerifierElem { paramMap_TYPE, null); } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, + ContentValues paramMap, TypeSet paramMap_TYPE) { + return addNodeWithOrder(propName, propValue, null, null, + paramMap, paramMap_TYPE, null); + } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, List propValueList, TypeSet paramMap_TYPE) { return addNodeWithOrder(propName, propValue, propValueList, null, null, @@ -223,6 +229,12 @@ class PropertyNodesVerifierElem { paramMap_TYPE, null); } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, + ContentValues paramMap, TypeSet paramMap_TYPE) { + return addNodeWithoutOrder(propName, propValue, null, null, + paramMap, paramMap_TYPE, null); + } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, List propValueList, byte[] propValue_bytes, ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) { diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java index 6dabd01cf825e..c8289dc1dd6ce 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java @@ -268,7 +268,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Nickname.NAME, "Nicky"); VCardVerifier verifier = new VCardVerifier(resolver, V30); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithOrder("NICKNAME", "Nicky"); verifier.verify(); @@ -282,7 +282,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Phone.TYPE, Phone.TYPE_HOME); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME")); verifier.verify(); @@ -353,7 +353,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Phone.TYPE, Phone.TYPE_MMS); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("TEL", "10", new TypeSet("HOME")) .addNodeWithoutOrder("TEL", "20", new TypeSet("WORK")) .addNodeWithoutOrder("TEL", "30", new TypeSet("HOME", "FAX")) @@ -403,7 +403,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Phone.TYPE, Phone.TYPE_FAX_WORK); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("TEL", "4", new TypeSet("WORK", "FAX")) .addNodeWithoutOrder("TEL", "3", new TypeSet("HOME", "FAX", "PREF")) .addNodeWithoutOrder("TEL", "2", new TypeSet("WORK", "PREF")) @@ -426,7 +426,7 @@ public class VCardExporterTests extends VCardTestsBase { VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("EMAIL", "sample@example.com"); verifier.verify(); @@ -459,7 +459,7 @@ public class VCardExporterTests extends VCardTestsBase { VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME")) .addNodeWithoutOrder("EMAIL", "type_work@example.com", new TypeSet("WORK")) .addNodeWithoutOrder("EMAIL", "type_mobile@example.com", new TypeSet("CELL")) @@ -490,7 +490,7 @@ public class VCardExporterTests extends VCardTestsBase { VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("EMAIL", "type_notype@example.com", new TypeSet("PREF")) .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF")); @@ -520,7 +520,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(StructuredPostal.POSTCODE, "100") .put(StructuredPostal.COUNTRY, "Country"); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("ADR", "Pobox;Neighborhood;Street;City;Region;100;Country", Arrays.asList("Pobox", "Neighborhood", "Street", "City", "Region", "100", "Country"), new TypeSet("HOME")); @@ -544,7 +544,7 @@ public class VCardExporterTests extends VCardTestsBase { "Formatted address CA 123-334 United Statue"); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;", Arrays.asList("", "Formatted address CA 123-334 United Statue", "", "", "", "", ""), new TypeSet("HOME")); @@ -574,7 +574,7 @@ public class VCardExporterTests extends VCardTestsBase { "Formatted address CA 123-334 United Statue"); // Should be ignored VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("ADR", "Pobox;;;;;;Country", Arrays.asList("Pobox", "", "", "", "", "", "Country"), new TypeSet("HOME")); @@ -615,7 +615,7 @@ public class VCardExporterTests extends VCardTestsBase { VCardVerifier verifier = new VCardVerifier(resolver, version); // Currently we do not use group but depend on the order. - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithOrder("ORG", "CompanyX;DepartmentY", Arrays.asList("CompanyX", "DepartmentY")) .addNodeWithOrder("TITLE", "TitleZ") @@ -677,7 +677,7 @@ public class VCardExporterTests extends VCardTestsBase { // No determined way to express unknown type... VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("X-JABBER", "jabber") .addNodeWithoutOrder("X-ICQ", "icq") .addNodeWithoutOrder("X-GOOGLE-TALK", "google talk") @@ -714,7 +714,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Im.IS_PRIMARY, 1); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("X-AIM", "aim1") .addNodeWithoutOrder("X-AIM", "aim2", new TypeSet("HOME", "PREF")); @@ -743,7 +743,7 @@ public class VCardExporterTests extends VCardTestsBase { // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it. VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("URL", "ftp://ftp.example.android.com/index.html") .addNodeWithoutOrder("URL", "http://website.example.android.com/index.html"); verifier.verify(); @@ -779,7 +779,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Event.START_DATE, "2009-05-19"); VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("BDAY", "2008-10-22"); verifier.verify(); @@ -804,7 +804,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Note.IS_PRIMARY, 1); // Just ignored. VCardVerifier verifier = new VCardVerifier(resolver, version); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithOrder("NOTE", "note1") .addNodeWithOrder("NOTE", "note2"); @@ -881,7 +881,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Nickname.NAME, "Nicky"); VCardVerifier verifier = new VCardVerifier(resolver, V21); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithOrder("X-ANDROID-CUSTOM", Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;"); verifier.addImportVerifier() @@ -897,7 +897,7 @@ public class VCardExporterTests extends VCardTestsBase { .put(Phone.NUMBER, "111-222-3333 (Miami)\n444-5555-666 (Tokyo);" + "777-888-9999 (Chicago);111-222-3333 (Miami)"); VCardVerifier verifier = new VCardVerifier(resolver, V21); - verifier.addPropertyNodesVerifierWithEmptyName() + verifier.addPropertyNodesVerifierElemWithEmptyName() .addNodeWithoutOrder("TEL", "111-222-3333", new TypeSet("HOME")) .addNodeWithoutOrder("TEL", "444-555-5666", new TypeSet("HOME")) .addNodeWithoutOrder("TEL", "777-888-9999", new TypeSet("HOME")); diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java index b1fccaadb0da0..36cc96633c4bf 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java @@ -784,7 +784,7 @@ public class VCardImporterTests extends VCardTestsBase { .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9") // While vCard parser does not split "SOUND" property values, // ContactStruct care it. - .put(StructuredName.PHONETIC_FAMILY_NAME, + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E"); elem.addExpected(Phone.CONTENT_ITEM_TYPE) @@ -937,7 +937,7 @@ public class VCardImporterTests extends VCardTestsBase { elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033") .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033") - .put(StructuredName.PHONETIC_FAMILY_NAME, + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033"); elem.addExpected(Phone.CONTENT_ITEM_TYPE) .put(Phone.TYPE, Phone.TYPE_CUSTOM) @@ -959,7 +959,7 @@ public class VCardImporterTests extends VCardTestsBase { elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034") .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034") - .put(StructuredName.PHONETIC_FAMILY_NAME, + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034"); elem.addExpected(Phone.CONTENT_ITEM_TYPE) .put(Phone.TYPE, Phone.TYPE_CUSTOM) @@ -981,7 +981,7 @@ public class VCardImporterTests extends VCardTestsBase { elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035") .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035") - .put(StructuredName.PHONETIC_FAMILY_NAME, + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035"); elem.addExpected(Phone.CONTENT_ITEM_TYPE) .put(Phone.TYPE, Phone.TYPE_CUSTOM) @@ -1031,6 +1031,18 @@ public class VCardImporterTests extends VCardTestsBase { new VCardParser_V21(VCardParser.PARSER_MODE_SCAN)); } + public void testTolerateInvalidCommentLikeLineV21() throws IOException, VCardException { + ImportVerifier verifier = new ImportVerifier(); + ImportVerifierElem elem = verifier.addImportVerifierElem(); + elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.GIVEN_NAME, "Conference Call") + .put(StructuredName.DISPLAY_NAME, "Conference Call"); + elem.addExpected(Note.CONTENT_ITEM_TYPE) + .put(Note.NOTE, "This is an (sharp ->#<- sharp) example. " + + "This message must NOT be ignored."); + verifier.verify(R.raw.v21_invalid_comment_line, V21); + } + public void testPagerV30_Parse() throws IOException, VCardException { PropertyNodesVerifier verifier = new PropertyNodesVerifier(this); verifier.addPropertyNodesVerifierElem() diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java index 4b65008f1bb23..70e49661a8c3b 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java @@ -106,4 +106,102 @@ public class VCardJapanizationTests extends VCardTestsBase { .addNodeWithoutOrder("X-DCM-HMN-MODE", ""); verifier.verify(); } + + private void testPhoneticNameCommon(int vcardType) { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") + .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); + + final ContentValues contentValues = + (VCardConfig.usesShiftJis(vcardType) ? + (VCardConfig.isV30(vcardType) ? mContentValuesForSJis : + mContentValuesForQPAndSJis) : + (VCardConfig.isV30(vcardType) ? null : mContentValuesForQPAndUtf8)); + VCardVerifier verifier = new VCardVerifier(resolver, vcardType); + PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElemWithEmptyName(); + elem.addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "\u3084\u307E\u3060", + contentValues) + .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", + "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0", + contentValues) + .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "\u305F\u308D\u3046", + contentValues); + if (VCardConfig.isV30(vcardType)) { + elem.addNodeWithoutOrder("SORT-STRING", + "\u3084\u307E\u3060 \u30DF\u30C9\u30EB\u30CD\u30FC\u30E0 \u305F\u308D\u3046", + contentValues); + } + ContentValuesBuilder builder = verifier.addImportVerifier() + .addExpected(StructuredName.CONTENT_ITEM_TYPE); + builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") + .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046") + .put(StructuredName.DISPLAY_NAME, + "\u3084\u307E\u3060 \u30DF\u30C9\u30EB\u30CD\u30FC\u30E0 " + + "\u305F\u308D\u3046"); + verifier.verify(); + } + + public void testPhoneticNameForJapaneseV21Utf8() { + testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE_UTF8); + } + + public void testPhoneticNameForJapaneseV21Sjis() { + testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS); + } + + public void testPhoneticNameForJapaneseV30Utf8() { + testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V30_JAPANESE_UTF8); + } + + public void testPhoneticNameForJapaneseV30SJis() { + testPhoneticNameCommon(VCardConfig.VCARD_TYPE_V30_JAPANESE_SJIS); + } + + public void testPhoneticNameForMobileV21_1() { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") + .put(StructuredName.PHONETIC_MIDDLE_NAME, "\u30DF\u30C9\u30EB\u30CD\u30FC\u30E0") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); + + VCardVerifier verifier = new VCardVerifier(resolver, + VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE); + verifier.addPropertyNodesVerifierElem() + .addNodeWithoutOrder("SOUND", + "\uFF94\uFF8F\uFF80\uFF9E \uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91 " + + "\uFF80\uFF9B\uFF73;;;;", + mContentValuesForSJis, new TypeSet("X-IRMC-N")); + ContentValuesBuilder builder = verifier.addImportVerifier() + .addExpected(StructuredName.CONTENT_ITEM_TYPE); + builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF94\uFF8F\uFF80\uFF9E") + .put(StructuredName.PHONETIC_MIDDLE_NAME, + "\uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF80\uFF9B\uFF73") + .put(StructuredName.DISPLAY_NAME, + "\uFF94\uFF8F\uFF80\uFF9E \uFF90\uFF84\uFF9E\uFF99\uFF88\uFF70\uFF91 " + + "\uFF80\uFF9B\uFF73"); + verifier.verify(); + } + + public void testPhoneticNameForMobileV21_2() { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.PHONETIC_FAMILY_NAME, "\u3084\u307E\u3060") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); + + VCardVerifier verifier = new VCardVerifier(resolver, + VCardConfig.VCARD_TYPE_V21_JAPANESE_MOBILE); + verifier.addPropertyNodesVerifierElem() + .addNodeWithoutOrder("SOUND", "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73;;;;", + mContentValuesForSJis, new TypeSet("X-IRMC-N")); + ContentValuesBuilder builder = verifier.addImportVerifier() + .addExpected(StructuredName.CONTENT_ITEM_TYPE); + builder.put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF94\uFF8F\uFF80\uFF9E") + .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF80\uFF9B\uFF73") + .put(StructuredName.DISPLAY_NAME, "\uFF94\uFF8F\uFF80\uFF9E \uFF80\uFF9B\uFF73"); + verifier.verify(); + } } \ No newline at end of file diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java index 6176f5cf797f1..af8b718a727dc 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java @@ -349,10 +349,14 @@ class CustomMockContext extends MockContext { } } if (!checked) { - final String failMsg = - "Unexpected ContentValues for MimeType " + mimeType - + ": " + actualContentValues; - fail(failMsg); + final StringBuilder builder = new StringBuilder(); + builder.append("Unexpected: "); + builder.append(convertToEasilyReadableString(actualContentValues)); + builder.append("\nExpected: "); + for (ContentValues expectedContentValues : contentValuesCollection) { + builder.append(convertToEasilyReadableString(expectedContentValues)); + } + fail(builder.toString()); } } else { fail("Unexpected Uri has come: " + uri); @@ -823,7 +827,7 @@ class CustomMockContext extends MockContext { return elem; } - public PropertyNodesVerifierElem addPropertyNodesVerifierWithEmptyName() { + public PropertyNodesVerifierElem addPropertyNodesVerifierElemWithEmptyName() { PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem(); if (mIsV30) { elem.addNodeWithOrder("N", "").addNodeWithOrder("FN", ""); @@ -847,14 +851,16 @@ class CustomMockContext extends MockContext { } private void verifyOneVCard(final String vcard) { + // Log.d("@@@", vcard); final VCardBuilder builder; if (mImportVerifier != null) { final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier; - final VCardDataBuilder vcardDataBuilder = new VCardDataBuilder(); + final VCardDataBuilder vcardDataBuilder = + new VCardDataBuilder(mVCardType); vcardDataBuilder.addEntryHandler(mImportVerifier); if (mPropertyNodesVerifier != null) { builder = new VCardBuilderCollection(Arrays.asList( - vcardDataBuilder, mPropertyNodesVerifier)); + mPropertyNodesVerifier, vcardDataBuilder)); } else { builder = vnodeBuilder; }