OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / tests / coretests / src / android / pim / vcard / VCardExporterTests.java
1 /*
2  * Copyright (C) 2009 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
17 package android.pim.vcard;
18
19 import android.content.ContentValues;
20 import android.pim.vcard.test_utils.ContactEntry;
21 import android.pim.vcard.test_utils.PropertyNodesVerifierElem;
22 import android.pim.vcard.test_utils.PropertyNodesVerifierElem.TypeSet;
23 import android.pim.vcard.test_utils.VCardTestsBase;
24 import android.provider.ContactsContract.CommonDataKinds.Email;
25 import android.provider.ContactsContract.CommonDataKinds.Event;
26 import android.provider.ContactsContract.CommonDataKinds.Im;
27 import android.provider.ContactsContract.CommonDataKinds.Nickname;
28 import android.provider.ContactsContract.CommonDataKinds.Note;
29 import android.provider.ContactsContract.CommonDataKinds.Organization;
30 import android.provider.ContactsContract.CommonDataKinds.Phone;
31 import android.provider.ContactsContract.CommonDataKinds.Photo;
32 import android.provider.ContactsContract.CommonDataKinds.Relation;
33 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
34 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
35 import android.provider.ContactsContract.CommonDataKinds.Website;
36
37 import java.util.Arrays;
38
39 /**
40  * Tests for the code related to vCard exporter, inculding vCard composer.
41  * This test class depends on vCard importer code, so if tests for vCard importer fail,
42  * the result of this class will not be reliable.
43  */
44 public class VCardExporterTests extends VCardTestsBase {
45     private static final byte[] sPhotoByteArray =
46         VCardImporterTests.sPhotoByteArrayForComplicatedCase;
47
48     public void testSimpleV21() {
49         mVerifier.initForExportTest(V21);
50         mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
51                 .put(StructuredName.FAMILY_NAME, "Ando")
52                 .put(StructuredName.GIVEN_NAME, "Roid");
53         mVerifier.addPropertyNodesVerifierElem()
54                 .addExpectedNode("FN", "Roid Ando")
55                 .addExpectedNode("N", "Ando;Roid;;;",
56                         Arrays.asList("Ando", "Roid", "", "", ""));
57     }
58
59     private void testStructuredNameBasic(int vcardType) {
60         mVerifier.initForExportTest(vcardType);
61         mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
62                 .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
63                 .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
64                 .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
65                 .put(StructuredName.PREFIX, "AppropriatePrefix")
66                 .put(StructuredName.SUFFIX, "AppropriateSuffix")
67                 .put(StructuredName.DISPLAY_NAME, "DISPLAY NAME");
68
69         mVerifier.addPropertyNodesVerifierElem()
70                 .addExpectedNodeWithOrder("N",
71                         "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
72                         + "AppropriatePrefix;AppropriateSuffix",
73                         Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
74                                 "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
75                 .addExpectedNodeWithOrder("FN", "DISPLAY NAME");
76     }
77
78     public void testStructuredNameBasicV21() {
79         testStructuredNameBasic(V21);
80     }
81
82     public void testStructuredNameBasicV30() {
83         testStructuredNameBasic(V30);
84     }
85
86     public void testStructuredNameBasicV40() {
87         testStructuredNameBasic(V40);
88     }
89
90     /**
91      * Test that only "primary" StructuredName is emitted, so that our vCard file
92      * will not confuse the external importer, assuming there may be some importer
93      * which presume that there's only one property toward each of  "N", "FN", etc.
94      * Note that more than one "N", "FN", etc. properties are acceptable in vCard spec.
95      */
96     private void testStructuredNameUsePrimaryCommon(int vcardType) {
97         mVerifier.initForExportTest(vcardType);
98         final ContactEntry entry = mVerifier.addInputEntry();
99         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
100                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
101                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
102                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
103                 .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
104                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
105                 .put(StructuredName.DISPLAY_NAME, "DoNotEmitDisplayName1");
106
107         // With "IS_PRIMARY=1". This is what we should use.
108         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
109                 .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
110                 .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
111                 .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
112                 .put(StructuredName.PREFIX, "AppropriatePrefix")
113                 .put(StructuredName.SUFFIX, "AppropriateSuffix")
114                 .put(StructuredName.DISPLAY_NAME, "AppropriateDisplayName")
115                 .put(StructuredName.IS_PRIMARY, 1);
116
117         // With "IS_PRIMARY=1", but we should ignore this time, since this is second, not first.
118         // vCard 2.1 does not specify anything about the number of N properties. We choose not
119         // emitting this property.
120         // vCard 3.0 does (There must be one N property)
121         // vCard 4.0 (rev13) does (cardinality (0, 1)).
122         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
123                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
124                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
125                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
126                 .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
127                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
128                 .put(StructuredName.DISPLAY_NAME, "DoNotEmitDisplayName2")
129                 .put(StructuredName.IS_PRIMARY, 1);
130
131        mVerifier.addPropertyNodesVerifierElem()
132                 .addExpectedNodeWithOrder("N",
133                         "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
134                         + "AppropriatePrefix;AppropriateSuffix",
135                         Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
136                                 "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
137                 .addExpectedNodeWithOrder("FN", "AppropriateDisplayName");
138     }
139
140     public void testStructuredNameUsePrimaryV21() {
141         testStructuredNameUsePrimaryCommon(V21);
142     }
143
144     public void testStructuredNameUsePrimaryV30() {
145         testStructuredNameUsePrimaryCommon(V30);
146     }
147
148     public void testStructuredNameUsePrimaryV40() {
149         testStructuredNameUsePrimaryCommon(V40);
150     }
151
152     /**
153      * Tests that only "super primary" StructuredName is emitted.
154      * See also the comment in {@link #testStructuredNameUsePrimaryCommon(int)}.
155      */
156     private void testStructuredNameUseSuperPrimaryCommon(int vcardType) {
157         mVerifier.initForExportTest(vcardType);
158         final ContactEntry entry = mVerifier.addInputEntry();
159         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
160                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
161                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
162                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
163                 .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
164                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
165                 .put(StructuredName.DISPLAY_NAME, "DoNotEmitDisplay1");
166
167         // With "IS_PRIMARY=1", but we should ignore this time.
168         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
169                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
170                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
171                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
172                 .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
173                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
174                 .put(StructuredName.DISPLAY_NAME, "DoNotEmitDisplay2")
175                 .put(StructuredName.IS_PRIMARY, 1);
176
177         // With "IS_SUPER_PRIMARY=1". This is what we should use.
178         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
179                 .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
180                 .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
181                 .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
182                 .put(StructuredName.PREFIX, "AppropriatePrefix")
183                 .put(StructuredName.SUFFIX, "AppropriateSuffix")
184                 .put(StructuredName.DISPLAY_NAME, "AppropriateDisplayName")
185                 .put(StructuredName.IS_SUPER_PRIMARY, 1);
186
187         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
188                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3")
189                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3")
190                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3")
191                 .put(StructuredName.PREFIX, "DoNotEmitPrefix3")
192                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix3")
193                 .put(StructuredName.DISPLAY_NAME, "DoNotEmitDisplay3")
194                 .put(StructuredName.IS_PRIMARY, 1);
195
196         final PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem();
197         elem.addExpectedNodeWithOrder("N",
198                 "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
199                 + "AppropriatePrefix;AppropriateSuffix",
200                 Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
201                         "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"));
202
203         elem.addExpectedNodeWithOrder("FN", "AppropriateDisplayName");
204     }
205
206     public void testStructuredNameUseSuperPrimaryV21() {
207         testStructuredNameUseSuperPrimaryCommon(V21);
208     }
209
210     public void testStructuredNameUseSuperPrimaryV30() {
211         testStructuredNameUseSuperPrimaryCommon(V30);
212     }
213
214     public void testStructuredNameUseSuperPrimaryV40() {
215         testStructuredNameUseSuperPrimaryCommon(V40);
216     }
217
218     /**
219      * Tests phonetic names field are handled correctly.
220      *
221      * vCard 2.1 does not have any field corresponding to them.
222      * vCard 3.0 has SORT-STRING property, which does not support multiple values inside it.
223      * vCard 4.0 (rev13) has SORT-AS parameter, which has three values (family, given, middle)
224      * inside it.
225      */
226     private void testStructuredNamePhoneticNameCommon(int vcardType) {
227         mVerifier.initForExportTest(vcardType);
228         final ContactEntry entry = mVerifier.addInputEntry();
229         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
230                 .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
231                 .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
232                 .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
233                 .put(StructuredName.PREFIX, "AppropriatePrefix")
234                 .put(StructuredName.SUFFIX, "AppropriateSuffix")
235                 .put(StructuredName.DISPLAY_NAME, "AppropriateDisplayName")
236                 .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
237                 .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
238                 .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
239
240         final PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem();
241         if (VCardConfig.isVersion40(vcardType)) {
242             final ContentValues contentValues = new ContentValues();
243             contentValues.put("SORT-AS",
244                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName");
245             // vCard 4.0 (rev13) now uses SORT-AS parameter, which is not compatible with
246             // either 2.1 nor 3.0.
247             elem.addExpectedNodeWithOrder("N",
248                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
249                     + "AppropriatePrefix;AppropriateSuffix",
250                     Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
251                             "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"),
252                     contentValues);
253         } else {
254             elem.addExpectedNodeWithOrder("N",
255                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
256                     + "AppropriatePrefix;AppropriateSuffix",
257                     Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
258                             "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"));
259             if (VCardConfig.isVersion30(vcardType)) {
260                 elem.addExpectedNode("SORT-STRING",
261                         "AppropriatePhoneticGiven AppropriatePhoneticMiddle"
262                         + " AppropriatePhoneticFamily");
263             }
264         }
265
266         elem.addExpectedNodeWithOrder("FN", "AppropriateDisplayName")
267             .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
268             .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
269             .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
270     }
271
272     public void testStructuredNamePhoneticNameV21() {
273         testStructuredNamePhoneticNameCommon(V21);
274     }
275
276     public void testStructuredNamePhoneticNameV30() {
277         testStructuredNamePhoneticNameCommon(V30);
278     }
279
280     public void testStructuredNamePhoneticNameV40() {
281         testStructuredNamePhoneticNameCommon(V40);
282     }
283
284     // TODO: need to add test cases confirming escaping, empty values, etc.
285
286     /**
287      * Confirms all the other sides of the handling is correctly interpreted at one time.
288      *
289      * A kind of regression test for StructuredName handling.
290      */
291     private void testStructuredNameComplicatedCommon(int vcardType) {
292         mVerifier.initForExportTest(vcardType);
293         final ContactEntry entry = mVerifier.addInputEntry();
294         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
295                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
296                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
297                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
298                 .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
299                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
300                 .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1")
301                 .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1")
302                 .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
303
304         // With "IS_PRIMARY=1", but we should ignore this time.
305         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
306                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
307                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
308                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
309                 .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
310                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
311                 .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2")
312                 .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2")
313                 .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2")
314                 .put(StructuredName.IS_PRIMARY, 1);
315
316         // With "IS_SUPER_PRIMARY=1". This is what we should use.
317         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
318                 .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
319                 .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
320                 .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
321                 .put(StructuredName.PREFIX, "AppropriatePrefix")
322                 .put(StructuredName.SUFFIX, "AppropriateSuffix")
323                 .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
324                 .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
325                 .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle")
326                 .put(StructuredName.IS_SUPER_PRIMARY, 1);
327
328         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
329                 .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3")
330                 .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3")
331                 .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3")
332                 .put(StructuredName.PREFIX, "DoNotEmitPrefix3")
333                 .put(StructuredName.SUFFIX, "DoNotEmitSuffix3")
334                 .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3")
335                 .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3")
336                 .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3")
337                 .put(StructuredName.IS_PRIMARY, 1);
338
339         final PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElem();
340         if (VCardConfig.isVersion40(vcardType)) {
341             final ContentValues contentValues = new ContentValues();
342             contentValues.put("SORT-AS",
343                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName");
344             // vCard 4.0 (rev13) now uses SORT-AS parameter, which is not compatible with
345             // either 2.1 nor 3.0.
346             elem.addExpectedNodeWithOrder("N",
347                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
348                     + "AppropriatePrefix;AppropriateSuffix",
349                     Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
350                             "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"),
351                     contentValues);
352         } else {
353             elem.addExpectedNodeWithOrder("N",
354                     "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
355                     + "AppropriatePrefix;AppropriateSuffix",
356                     Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
357                             "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"));
358             if (VCardConfig.isVersion30(vcardType)) {
359                 elem.addExpectedNode("SORT-STRING",
360                         "AppropriatePhoneticGiven AppropriatePhoneticMiddle"
361                         + " AppropriatePhoneticFamily");
362             }
363         }
364
365         elem.addExpectedNodeWithOrder("FN",
366                 "AppropriatePrefix AppropriateGivenName "
367                 + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
368             .addExpectedNode("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
369             .addExpectedNode("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
370             .addExpectedNode("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
371     }
372
373     public void testStructuredNameComplicatedV21() {
374         testStructuredNameComplicatedCommon(V21);
375     }
376
377     public void testStructuredNameComplicatedV30() {
378         testStructuredNameComplicatedCommon(V30);
379     }
380
381     public void testStructuredNameComplicatedV40() {
382         testStructuredNameComplicatedCommon(V40);
383     }
384
385     public void testNickNameV30() {
386         mVerifier.initForExportTest(V30);
387         mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
388                 .put(Nickname.NAME, "Nicky");
389
390         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
391             .addExpectedNodeWithOrder("NICKNAME", "Nicky");
392     }
393
394     public void testNickNameV40() {
395         mVerifier.initForExportTest(V40);
396         mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
397                 .put(Nickname.NAME, "Nicky");
398
399         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
400             .addExpectedNodeWithOrder("NICKNAME", "Nicky");
401     }
402
403     private void testPhoneBasicCommon(int vcardType) {
404         mVerifier.initForExportTest(vcardType);
405         mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE)
406                 .put(Phone.NUMBER, "1")
407                 .put(Phone.TYPE, Phone.TYPE_HOME);
408         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
409                 .addExpectedNode("TEL", "1", new TypeSet("HOME"));
410     }
411
412     public void testPhoneBasicV21() {
413         testPhoneBasicCommon(V21);
414     }
415
416     public void testPhoneBasicV30() {
417         testPhoneBasicCommon(V30);
418     }
419
420     public void testPhoneBasicV40() {
421         testPhoneBasicCommon(V40);
422     }
423
424     public void testPhoneRefrainFormatting() {
425         mVerifier.initForExportTest(V21 | VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING);
426         mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE)
427                 .put(Phone.NUMBER, "1234567890(abcdefghijklmnopqrstuvwxyz)")
428                 .put(Phone.TYPE, Phone.TYPE_HOME);
429         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
430                 .addExpectedNode("TEL", "1234567890(abcdefghijklmnopqrstuvwxyz)",
431                         new TypeSet("HOME"));
432     }
433
434     /**
435      * Tests that vCard composer emits corresponding type param which we expect.
436      */
437     private void testPhoneVariousTypeSupport(int vcardType) {
438         mVerifier.initForExportTest(vcardType);
439         ContactEntry entry = mVerifier.addInputEntry();
440         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
441                 .put(Phone.NUMBER, "10")
442                 .put(Phone.TYPE, Phone.TYPE_HOME);
443         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
444                 .put(Phone.NUMBER, "20")
445                 .put(Phone.TYPE, Phone.TYPE_WORK);
446         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
447                 .put(Phone.NUMBER, "30")
448                 .put(Phone.TYPE, Phone.TYPE_FAX_HOME);
449         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
450                 .put(Phone.NUMBER, "40")
451                 .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
452         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
453                 .put(Phone.NUMBER, "50")
454                 .put(Phone.TYPE, Phone.TYPE_MOBILE);
455         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
456                 .put(Phone.NUMBER, "60")
457                 .put(Phone.TYPE, Phone.TYPE_PAGER);
458         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
459                 .put(Phone.NUMBER, "70")
460                 .put(Phone.TYPE, Phone.TYPE_OTHER);
461         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
462                 .put(Phone.NUMBER, "80")
463                 .put(Phone.TYPE, Phone.TYPE_CAR);
464         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
465                 .put(Phone.NUMBER, "90")
466                 .put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN);
467         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
468                 .put(Phone.NUMBER, "100")
469                 .put(Phone.TYPE, Phone.TYPE_ISDN);
470         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
471                 .put(Phone.NUMBER, "110")
472                 .put(Phone.TYPE, Phone.TYPE_MAIN);
473         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
474                 .put(Phone.NUMBER, "120")
475                 .put(Phone.TYPE, Phone.TYPE_OTHER_FAX);
476         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
477                 .put(Phone.NUMBER, "130")
478                 .put(Phone.TYPE, Phone.TYPE_TELEX);
479         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
480                 .put(Phone.NUMBER, "140")
481                 .put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
482         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
483                 .put(Phone.NUMBER, "150")
484                 .put(Phone.TYPE, Phone.TYPE_WORK_PAGER);
485         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
486                 .put(Phone.NUMBER, "160")
487                 .put(Phone.TYPE, Phone.TYPE_MMS);
488
489         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
490                 .addExpectedNode("TEL", "10", new TypeSet("HOME"))
491                 .addExpectedNode("TEL", "20", new TypeSet("WORK"))
492                 .addExpectedNode("TEL", "30", new TypeSet("HOME", "FAX"))
493                 .addExpectedNode("TEL", "40", new TypeSet("WORK", "FAX"))
494                 .addExpectedNode("TEL", "50", new TypeSet("CELL"))
495                 .addExpectedNode("TEL", "60", new TypeSet("PAGER"))
496                 .addExpectedNode("TEL", "70", new TypeSet("VOICE"))
497                 .addExpectedNode("TEL", "80", new TypeSet("CAR"))
498                 .addExpectedNode("TEL", "90", new TypeSet("WORK", "PREF"))
499                 .addExpectedNode("TEL", "100", new TypeSet("ISDN"))
500                 .addExpectedNode("TEL", "110", new TypeSet("PREF"))
501                 .addExpectedNode("TEL", "120", new TypeSet("FAX"))
502                 .addExpectedNode("TEL", "130", new TypeSet("TLX"))
503                 .addExpectedNode("TEL", "140", new TypeSet("WORK", "CELL"))
504                 .addExpectedNode("TEL", "150", new TypeSet("WORK", "PAGER"))
505                 .addExpectedNode("TEL", "160", new TypeSet("MSG"));
506     }
507
508     public void testPhoneVariousTypeSupportV21() {
509         testPhoneVariousTypeSupport(V21);
510     }
511
512     public void testPhoneVariousTypeSupportV30() {
513         testPhoneVariousTypeSupport(V30);
514     }
515
516     public void testPhoneVariousTypeSupportV40() {
517         testPhoneVariousTypeSupport(V40);
518     }
519
520     /**
521      * Tests that "PREF"s are emitted appropriately.
522      */
523     private void testPhonePrefHandlingCommon(int vcardType) {
524         mVerifier.initForExportTest(vcardType);
525         ContactEntry entry = mVerifier.addInputEntry();
526         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
527                 .put(Phone.NUMBER, "1")
528                 .put(Phone.TYPE, Phone.TYPE_HOME);
529         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
530                 .put(Phone.NUMBER, "2")
531                 .put(Phone.TYPE, Phone.TYPE_WORK)
532                 .put(Phone.IS_PRIMARY, 1);
533         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
534                 .put(Phone.NUMBER, "3")
535                 .put(Phone.TYPE, Phone.TYPE_FAX_HOME)
536                 .put(Phone.IS_PRIMARY, 1);
537         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
538                 .put(Phone.NUMBER, "4")
539                 .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
540
541         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
542                 .addExpectedNode("TEL", "4", new TypeSet("WORK", "FAX"))
543                 .addExpectedNode("TEL", "3", new TypeSet("HOME", "FAX", "PREF"))
544                 .addExpectedNode("TEL", "2", new TypeSet("WORK", "PREF"))
545                 .addExpectedNode("TEL", "1", new TypeSet("HOME"));
546     }
547
548     public void testPhonePrefHandlingV21() {
549         testPhonePrefHandlingCommon(V21);
550     }
551
552     public void testPhonePrefHandlingV30() {
553         testPhonePrefHandlingCommon(V30);
554     }
555
556     public void testPhonePrefHandlingV40() {
557         testPhonePrefHandlingCommon(V40);
558     }
559
560     private void testMiscPhoneTypeHandling(int vcardType) {
561         mVerifier.initForExportTest(vcardType);
562         ContactEntry entry = mVerifier.addInputEntry();
563         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
564                 .put(Phone.NUMBER, "1")
565                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
566                 .put(Phone.LABEL, "Modem");
567         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
568                 .put(Phone.NUMBER, "2")
569                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
570                 .put(Phone.LABEL, "MSG");
571         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
572                 .put(Phone.NUMBER, "3")
573                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
574                 .put(Phone.LABEL, "BBS");
575         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
576                 .put(Phone.NUMBER, "4")
577                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
578                 .put(Phone.LABEL, "VIDEO");
579         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
580                 .put(Phone.NUMBER, "5")
581                 .put(Phone.TYPE, Phone.TYPE_CUSTOM);
582         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
583                 .put(Phone.NUMBER, "6")
584                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
585                 .put(Phone.LABEL, "_AUTO_CELL");  // The old indicator for the type mobile.
586         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
587                 .put(Phone.NUMBER, "7")
588                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
589                 .put(Phone.LABEL, "\u643A\u5E2F");  // Mobile phone in Japanese Kanji
590         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
591                 .put(Phone.NUMBER, "8")
592                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
593                 .put(Phone.LABEL, "invalid");
594         PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName();
595         if (VCardConfig.isVersion30(vcardType) || VCardConfig.isVersion40(vcardType)) {
596             // vCard 3.0 accepts "invalid". Also stop using toUpper()
597             elem.addExpectedNode("TEL", "1", new TypeSet("Modem"))
598                     .addExpectedNode("TEL", "2", new TypeSet("MSG"))
599                     .addExpectedNode("TEL", "3", new TypeSet("BBS"))
600                     .addExpectedNode("TEL", "4", new TypeSet("VIDEO"))
601                     .addExpectedNode("TEL", "5", new TypeSet("VOICE"))
602                     .addExpectedNode("TEL", "6", new TypeSet("CELL"))
603                     .addExpectedNode("TEL", "7", new TypeSet("CELL"))
604                     .addExpectedNode("TEL", "8", new TypeSet("invalid"));
605         } else {
606             elem.addExpectedNode("TEL", "1", new TypeSet("MODEM"))
607                     .addExpectedNode("TEL", "2", new TypeSet("MSG"))
608                     .addExpectedNode("TEL", "3", new TypeSet("BBS"))
609                     .addExpectedNode("TEL", "4", new TypeSet("VIDEO"))
610                     .addExpectedNode("TEL", "5", new TypeSet("VOICE"))
611                     .addExpectedNode("TEL", "6", new TypeSet("CELL"))
612                     .addExpectedNode("TEL", "7", new TypeSet("CELL"))
613                     .addExpectedNode("TEL", "8", new TypeSet("X-invalid"));
614         }
615     }
616
617     public void testPhoneTypeHandlingV21() {
618         testMiscPhoneTypeHandling(V21);
619     }
620
621     public void testPhoneTypeHandlingV30() {
622         testMiscPhoneTypeHandling(V30);
623     }
624
625     public void testPhoneTypeHandlingV40() {
626         testMiscPhoneTypeHandling(V40);
627     }
628
629     private void testEmailBasicCommon(int vcardType) {
630         mVerifier.initForExportTest(vcardType);
631         mVerifier.addInputEntry().addContentValues(Email.CONTENT_ITEM_TYPE)
632                 .put(Email.DATA, "sample@example.com");
633         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
634             .addExpectedNode("EMAIL", "sample@example.com");
635     }
636
637     public void testEmailBasicV21() {
638         testEmailBasicCommon(V21);
639     }
640
641     public void testEmailBasicV30() {
642         testEmailBasicCommon(V30);
643     }
644
645     public void testEmailBasicV40() {
646         testEmailBasicCommon(V40);
647     }
648
649     private void testEmailVariousTypeSupportCommon(int vcardType) {
650         mVerifier.initForExportTest(vcardType);
651         ContactEntry entry = mVerifier.addInputEntry();
652         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
653                 .put(Email.DATA, "type_home@example.com")
654                 .put(Email.TYPE, Email.TYPE_HOME);
655         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
656                 .put(Email.DATA, "type_work@example.com")
657                 .put(Email.TYPE, Email.TYPE_WORK);
658         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
659                 .put(Email.DATA, "type_mobile@example.com")
660                 .put(Email.TYPE, Email.TYPE_MOBILE);
661         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
662                 .put(Email.DATA, "type_other@example.com")
663                 .put(Email.TYPE, Email.TYPE_OTHER);
664         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
665                 .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME"))
666                 .addExpectedNode("EMAIL", "type_work@example.com", new TypeSet("WORK"))
667                 .addExpectedNode("EMAIL", "type_mobile@example.com", new TypeSet("CELL"))
668                 .addExpectedNode("EMAIL", "type_other@example.com");
669     }
670
671     public void testEmailVariousTypeSupportV21() {
672         testEmailVariousTypeSupportCommon(V21);
673     }
674
675     public void testEmailVariousTypeSupportV30() {
676         testEmailVariousTypeSupportCommon(V30);
677     }
678
679     public void testEmailVariousTypeSupportV40() {
680         testEmailVariousTypeSupportCommon(V40);
681     }
682
683     private void testEmailPrefHandlingCommon(int vcardType) {
684         mVerifier.initForExportTest(vcardType);
685         ContactEntry entry = mVerifier.addInputEntry();
686         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
687                 .put(Email.DATA, "type_home@example.com")
688                 .put(Email.TYPE, Email.TYPE_HOME)
689                 .put(Email.IS_PRIMARY, 1);
690         entry.addContentValues(Email.CONTENT_ITEM_TYPE)
691                 .put(Email.DATA, "type_notype@example.com")
692                 .put(Email.IS_PRIMARY, 1);
693
694         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
695                 .addExpectedNode("EMAIL", "type_notype@example.com", new TypeSet("PREF"))
696                 .addExpectedNode("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF"));
697     }
698
699     public void testEmailPrefHandlingV21() {
700         testEmailPrefHandlingCommon(V21);
701     }
702
703     public void testEmailPrefHandlingV30() {
704         testEmailPrefHandlingCommon(V30);
705     }
706
707     public void testEmailPrefHandlingV40() {
708         testEmailPrefHandlingCommon(V40);
709     }
710
711     private void testPostalAddressCommon(int vcardType) {
712         mVerifier.initForExportTest(vcardType);
713         mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
714                 .put(StructuredPostal.POBOX, "Pobox")
715                 .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood")
716                 .put(StructuredPostal.STREET, "Street")
717                 .put(StructuredPostal.CITY, "City")
718                 .put(StructuredPostal.REGION, "Region")
719                 .put(StructuredPostal.POSTCODE, "100")
720                 .put(StructuredPostal.COUNTRY, "Country")
721                 .put(StructuredPostal.FORMATTED_ADDRESS, "Formatted Address")
722                 .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK);
723         // adr-value    = 0*6(text-value ";") text-value
724         //              ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
725         //              ; Country Name
726         //
727         // The NEIGHBORHOOD field is appended after the CITY field.
728         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
729                 .addExpectedNode("ADR",
730                         Arrays.asList("Pobox", "", "Street", "City Neighborhood",
731                                 "Region", "100", "Country"), new TypeSet("WORK"));
732     }
733
734     public void testPostalAddressV21() {
735         testPostalAddressCommon(V21);
736     }
737
738     public void testPostalAddressV30() {
739         testPostalAddressCommon(V30);
740     }
741
742     public void testPostalAddressV40() {
743         testPostalAddressCommon(V40);
744     }
745
746     private void testPostalAddressNonNeighborhood(int vcardType) {
747         mVerifier.initForExportTest(vcardType);
748         mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
749                 .put(StructuredPostal.CITY, "City");
750         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
751                 .addExpectedNode("ADR",
752                         Arrays.asList("", "", "", "City", "", "", ""), new TypeSet("HOME"));
753     }
754
755     public void testPostalAddressNonNeighborhoodV21() {
756         testPostalAddressNonNeighborhood(V21);
757     }
758
759     public void testPostalAddressNonNeighborhoodV30() {
760         testPostalAddressNonNeighborhood(V30);
761     }
762
763     public void testPostalAddressNonNeighborhoodV40() {
764         testPostalAddressNonNeighborhood(V40);
765     }
766
767     private void testPostalAddressNonCity(int vcardType) {
768         mVerifier.initForExportTest(vcardType);
769         mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
770                 .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood");
771         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
772                 .addExpectedNode("ADR",
773                         Arrays.asList("", "", "", "Neighborhood", "", "", ""), new TypeSet("HOME"));
774     }
775
776     public void testPostalAddressNonCityV21() {
777         testPostalAddressNonCity(V21);
778     }
779
780     public void testPostalAddressNonCityV30() {
781         testPostalAddressNonCity(V30);
782     }
783
784     public void testPostalAddressNonCityV40() {
785         testPostalAddressNonCity(V40);
786     }
787
788     private void testPostalOnlyWithFormattedAddressCommon(int vcardType) {
789         mVerifier.initForExportTest(vcardType);
790         mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
791                 .put(StructuredPostal.REGION, "")  // Must be ignored.
792                 .put(StructuredPostal.FORMATTED_ADDRESS,
793                 "Formatted address CA 123-334 United Statue");
794         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
795                 .addExpectedNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
796                         Arrays.asList("", "Formatted address CA 123-334 United Statue",
797                                 "", "", "", "", ""), new TypeSet("HOME"));
798     }
799
800     public void testPostalOnlyWithFormattedAddressV21() {
801         testPostalOnlyWithFormattedAddressCommon(V21);
802     }
803
804     public void testPostalOnlyWithFormattedAddressV30() {
805         testPostalOnlyWithFormattedAddressCommon(V30);
806     }
807
808     public void testPostalOnlyWithFormattedAddressV40() {
809         testPostalOnlyWithFormattedAddressCommon(V40);
810     }
811
812     /**
813      * Tests that the vCard composer honors formatted data when it is available
814      * even when it is partial.
815      */
816     private void testPostalWithBothStructuredAndFormattedCommon(int vcardType) {
817         mVerifier.initForExportTest(vcardType);
818         mVerifier.addInputEntry().addContentValues(StructuredPostal.CONTENT_ITEM_TYPE)
819                 .put(StructuredPostal.POBOX, "Pobox")
820                 .put(StructuredPostal.COUNTRY, "Country")
821                 .put(StructuredPostal.FORMATTED_ADDRESS,
822                         "Formatted address CA 123-334 United Statue");  // Should be ignored
823         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
824                 .addExpectedNode("ADR", "Pobox;;;;;;Country",
825                         Arrays.asList("Pobox", "", "", "", "", "", "Country"),
826                         new TypeSet("HOME"));
827     }
828
829     public void testPostalWithBothStructuredAndFormattedV21() {
830         testPostalWithBothStructuredAndFormattedCommon(V21);
831     }
832
833     public void testPostalWithBothStructuredAndFormattedV30() {
834         testPostalWithBothStructuredAndFormattedCommon(V30);
835     }
836
837     public void testPostalWithBothStructuredAndFormattedV40() {
838         testPostalWithBothStructuredAndFormattedCommon(V40);
839     }
840
841     private void testOrganizationCommon(int vcardType) {
842         mVerifier.initForExportTest(vcardType);
843         ContactEntry entry = mVerifier.addInputEntry();
844         entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
845                 .put(Organization.COMPANY, "CompanyX")
846                 .put(Organization.DEPARTMENT, "DepartmentY")
847                 .put(Organization.TITLE, "TitleZ")
848                 .put(Organization.JOB_DESCRIPTION, "Description Rambda")  // Ignored.
849                 .put(Organization.OFFICE_LOCATION, "Mountain View")  // Ignored.
850                 .put(Organization.PHONETIC_NAME, "PhoneticName!")  // Ignored
851                 .put(Organization.SYMBOL, "(^o^)/~~");  // Ignore him (her).
852         entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
853                 .putNull(Organization.COMPANY)
854                 .put(Organization.DEPARTMENT, "DepartmentXX")
855                 .putNull(Organization.TITLE);
856         entry.addContentValues(Organization.CONTENT_ITEM_TYPE)
857                 .put(Organization.COMPANY, "CompanyXYZ")
858                 .putNull(Organization.DEPARTMENT)
859                 .put(Organization.TITLE, "TitleXYZYX");
860         // Currently we do not use group but depend on the order.
861         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
862                 .addExpectedNodeWithOrder("ORG", "CompanyX;DepartmentY",
863                         Arrays.asList("CompanyX", "DepartmentY"))
864                 .addExpectedNodeWithOrder("TITLE", "TitleZ")
865                 .addExpectedNodeWithOrder("ORG", "DepartmentXX")
866                 .addExpectedNodeWithOrder("ORG", "CompanyXYZ")
867                 .addExpectedNodeWithOrder("TITLE", "TitleXYZYX");
868     }
869
870     public void testOrganizationV21() {
871         testOrganizationCommon(V21);
872     }
873
874     public void testOrganizationV30() {
875         testOrganizationCommon(V30);
876     }
877
878     public void testOrganizationV40() {
879         testOrganizationCommon(V40);
880     }
881
882     private void testImVariousTypeSupportCommon(int vcardType) {
883         mVerifier.initForExportTest(vcardType);
884         ContactEntry entry = mVerifier.addInputEntry();
885         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
886                 .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
887                 .put(Im.DATA, "aim");
888         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
889                 .put(Im.PROTOCOL, Im.PROTOCOL_MSN)
890                 .put(Im.DATA, "msn");
891         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
892                 .put(Im.PROTOCOL, Im.PROTOCOL_YAHOO)
893                 .put(Im.DATA, "yahoo");
894         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
895                 .put(Im.PROTOCOL, Im.PROTOCOL_SKYPE)
896                 .put(Im.DATA, "skype");
897         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
898                 .put(Im.PROTOCOL, Im.PROTOCOL_QQ)
899                 .put(Im.DATA, "qq");
900         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
901                 .put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK)
902                 .put(Im.DATA, "google talk");
903         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
904                 .put(Im.PROTOCOL, Im.PROTOCOL_ICQ)
905                 .put(Im.DATA, "icq");
906         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
907                 .put(Im.PROTOCOL, Im.PROTOCOL_JABBER)
908                 .put(Im.DATA, "jabber");
909         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
910                 .put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING)
911                 .put(Im.DATA, "netmeeting");
912
913         // No determined way to express unknown type...
914         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
915                 .addExpectedNode("X-JABBER", "jabber")
916                 .addExpectedNode("X-ICQ", "icq")
917                 .addExpectedNode("X-GOOGLE-TALK", "google talk")
918                 .addExpectedNode("X-QQ", "qq")
919                 .addExpectedNode("X-SKYPE-USERNAME", "skype")
920                 .addExpectedNode("X-YAHOO", "yahoo")
921                 .addExpectedNode("X-MSN", "msn")
922                 .addExpectedNode("X-NETMEETING", "netmeeting")
923                 .addExpectedNode("X-AIM", "aim");
924     }
925
926     public void testImBasiV21() {
927         testImVariousTypeSupportCommon(V21);
928     }
929
930     public void testImBasicV30() {
931         testImVariousTypeSupportCommon(V30);
932     }
933
934     public void testImBasicV40() {
935         testImVariousTypeSupportCommon(V40);
936     }
937
938     private void testImPrefHandlingCommon(int vcardType) {
939         mVerifier.initForExportTest(vcardType);
940         ContactEntry entry = mVerifier.addInputEntry();
941         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
942                 .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
943                 .put(Im.DATA, "aim1");
944         entry.addContentValues(Im.CONTENT_ITEM_TYPE)
945                 .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
946                 .put(Im.DATA, "aim2")
947                 .put(Im.TYPE, Im.TYPE_HOME)
948                 .put(Im.IS_PRIMARY, 1);
949
950         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
951                 .addExpectedNode("X-AIM", "aim1")
952                 .addExpectedNode("X-AIM", "aim2", new TypeSet("HOME", "PREF"));
953     }
954
955     public void testImPrefHandlingV21() {
956         testImPrefHandlingCommon(V21);
957     }
958
959     public void testImPrefHandlingV30() {
960         testImPrefHandlingCommon(V30);
961     }
962
963     public void testImPrefHandlingV40() {
964         testImPrefHandlingCommon(V40);
965     }
966
967     private void testWebsiteCommon(int vcardType) {
968         mVerifier.initForExportTest(vcardType);
969         ContactEntry entry = mVerifier.addInputEntry();
970         entry.addContentValues(Website.CONTENT_ITEM_TYPE)
971                 .put(Website.URL, "http://website.example.android.com/index.html")
972                 .put(Website.TYPE, Website.TYPE_BLOG);
973         entry.addContentValues(Website.CONTENT_ITEM_TYPE)
974                 .put(Website.URL, "ftp://ftp.example.android.com/index.html")
975                 .put(Website.TYPE, Website.TYPE_FTP);
976
977         // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it.
978         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
979                 .addExpectedNode("URL", "ftp://ftp.example.android.com/index.html")
980                 .addExpectedNode("URL", "http://website.example.android.com/index.html");
981     }
982
983     public void testWebsiteV21() {
984         testWebsiteCommon(V21);
985     }
986
987     public void testWebsiteV30() {
988         testWebsiteCommon(V30);
989     }
990
991     public void testWebsiteV40() {
992         testWebsiteCommon(V40);
993     }
994
995     private String getAndroidPropValue(final String mimeType, String value, Integer type) {
996         return getAndroidPropValue(mimeType, value, type, null);
997     }
998
999     private String getAndroidPropValue(final String mimeType, String value,
1000             Integer type, String label) {
1001         return (mimeType + ";" + value + ";"
1002                 + (type != null ? type : "") + ";"
1003                 + (label != null ? label : "") + ";;;;;;;;;;;;");
1004     }
1005
1006     private void testEventCommon(int vcardType) {
1007         mVerifier.initForExportTest(vcardType);
1008         ContactEntry entry = mVerifier.addInputEntry();
1009         entry.addContentValues(Event.CONTENT_ITEM_TYPE)
1010                 .put(Event.TYPE, Event.TYPE_ANNIVERSARY)
1011                 .put(Event.START_DATE, "1982-06-16");
1012         entry.addContentValues(Event.CONTENT_ITEM_TYPE)
1013                 .put(Event.TYPE, Event.TYPE_BIRTHDAY)
1014                 .put(Event.START_DATE, "2008-10-22");
1015         entry.addContentValues(Event.CONTENT_ITEM_TYPE)
1016                 .put(Event.TYPE, Event.TYPE_OTHER)
1017                 .put(Event.START_DATE, "2018-03-12");
1018         entry.addContentValues(Event.CONTENT_ITEM_TYPE)
1019                 .put(Event.TYPE, Event.TYPE_CUSTOM)
1020                 .put(Event.LABEL, "The last day")
1021                 .put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed.");
1022         entry.addContentValues(Event.CONTENT_ITEM_TYPE)
1023                 .put(Event.TYPE, Event.TYPE_BIRTHDAY)
1024                 .put(Event.START_DATE, "2009-05-19");  // Should be ignored.
1025         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
1026                 .addExpectedNode("BDAY", "2008-10-22")
1027                 .addExpectedNode("X-ANDROID-CUSTOM",
1028                         getAndroidPropValue(
1029                                 Event.CONTENT_ITEM_TYPE, "1982-06-16", Event.TYPE_ANNIVERSARY))
1030                 .addExpectedNode("X-ANDROID-CUSTOM",
1031                         getAndroidPropValue(
1032                                 Event.CONTENT_ITEM_TYPE, "2018-03-12", Event.TYPE_OTHER))
1033                 .addExpectedNode("X-ANDROID-CUSTOM",
1034                         getAndroidPropValue(
1035                                 Event.CONTENT_ITEM_TYPE,
1036                                 "When the Tower of Hanoi with 64 rings is completed.",
1037                                 Event.TYPE_CUSTOM, "The last day"));
1038     }
1039
1040     public void testEventV21() {
1041         testEventCommon(V21);
1042     }
1043
1044     public void testEventV30() {
1045         testEventCommon(V30);
1046     }
1047
1048     public void testEventV40() {
1049         testEventCommon(V40);
1050     }
1051
1052     private void testNoteCommon(int vcardType) {
1053         mVerifier.initForExportTest(vcardType);
1054         ContactEntry entry = mVerifier.addInputEntry();
1055         entry.addContentValues(Note.CONTENT_ITEM_TYPE)
1056                 .put(Note.NOTE, "note1");
1057         entry.addContentValues(Note.CONTENT_ITEM_TYPE)
1058                 .put(Note.NOTE, "note2")
1059                 .put(Note.IS_PRIMARY, 1);  // Just ignored.
1060         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
1061                 .addExpectedNodeWithOrder("NOTE", "note1")
1062                 .addExpectedNodeWithOrder("NOTE", "note2");
1063     }
1064
1065     public void testNoteV21() {
1066         testNoteCommon(V21);
1067     }
1068
1069     public void testNoteV30() {
1070         testNoteCommon(V30);
1071     }
1072
1073     public void testNoteV40() {
1074         testNoteCommon(V40);
1075     }
1076
1077     private void testPhotoCommon(int vcardType) {
1078         final boolean useB =
1079             (VCardConfig.isVersion30(vcardType) || VCardConfig.isVersion40(vcardType));
1080         mVerifier.initForExportTest(vcardType);
1081         ContactEntry entry = mVerifier.addInputEntry();
1082         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1083                 .put(StructuredName.FAMILY_NAME, "PhotoTest");
1084         entry.addContentValues(Photo.CONTENT_ITEM_TYPE)
1085                 .put(Photo.PHOTO, sPhotoByteArray);
1086
1087         ContentValues contentValuesForPhoto = new ContentValues();
1088         contentValuesForPhoto.put("ENCODING", (useB ? "b" : "BASE64"));
1089         mVerifier.addPropertyNodesVerifierElem()
1090                 .addExpectedNode("FN", "PhotoTest")
1091                 .addExpectedNode("N", "PhotoTest;;;;",
1092                         Arrays.asList("PhotoTest", "", "", "", ""))
1093                 .addExpectedNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
1094                         contentValuesForPhoto, new TypeSet("JPEG"), null);
1095     }
1096
1097     public void testPhotoV21() {
1098         testPhotoCommon(V21);
1099     }
1100
1101     public void testPhotoV30() {
1102         testPhotoCommon(V30);
1103     }
1104
1105     public void testPhotoV40() {
1106         testPhotoCommon(V40);
1107     }
1108
1109     private void testRelationCommon(int vcardType) {
1110         mVerifier.initForExportTest(vcardType);
1111         mVerifier.addInputEntry().addContentValues(Relation.CONTENT_ITEM_TYPE)
1112                 .put(Relation.TYPE, Relation.TYPE_MOTHER)
1113                 .put(Relation.NAME, "Ms. Mother");
1114         mVerifier.addContentValuesVerifierElem().addExpected(Relation.CONTENT_ITEM_TYPE)
1115                 .put(Relation.TYPE, Relation.TYPE_MOTHER)
1116                 .put(Relation.NAME, "Ms. Mother");
1117     }
1118
1119     public void testRelationV21() {
1120         testRelationCommon(V21);
1121     }
1122
1123     public void testRelationV30() {
1124         testRelationCommon(V30);
1125     }
1126
1127     public void testV30HandleEscape() {
1128         mVerifier.initForExportTest(V30);
1129         mVerifier.addInputEntry().addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1130                 .put(StructuredName.FAMILY_NAME, "\\")
1131                 .put(StructuredName.GIVEN_NAME, ";")
1132                 .put(StructuredName.MIDDLE_NAME, ",")
1133                 .put(StructuredName.PREFIX, "\n")
1134                 .put(StructuredName.DISPLAY_NAME, "[<{Unescaped:Asciis}>]");
1135         // Verifies the vCard String correctly escapes each character which must be escaped.
1136         mVerifier.addLineVerifierElem()
1137                 .addExpected("N:\\\\;\\;;\\,;\\n;")
1138                 .addExpected("FN:[<{Unescaped:Asciis}>]");
1139         mVerifier.addPropertyNodesVerifierElem()
1140                 .addExpectedNode("FN", "[<{Unescaped:Asciis}>]")
1141                 .addExpectedNode("N", Arrays.asList("\\", ";", ",", "\n", ""));
1142     }
1143
1144     /**
1145      * There's no "NICKNAME" property in vCard 2.1, while there is in vCard 3.0.
1146      * We use Android-specific "X-ANDROID-CUSTOM" property.
1147      * This test verifies the functionality.
1148      */
1149     public void testNickNameV21() {
1150         mVerifier.initForExportTest(V21);
1151         mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
1152                 .put(Nickname.NAME, "Nicky");
1153         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
1154                 .addExpectedNode("X-ANDROID-CUSTOM",
1155                         Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;");
1156         mVerifier.addContentValuesVerifierElem().addExpected(Nickname.CONTENT_ITEM_TYPE)
1157                 .put(Nickname.NAME, "Nicky");
1158     }
1159
1160     public void testTolerateBrokenPhoneNumberEntryV21() {
1161         mVerifier.initForExportTest(V21);
1162         ContactEntry entry = mVerifier.addInputEntry();
1163         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
1164                 .put(Phone.TYPE, Phone.TYPE_HOME)
1165                 .put(Phone.NUMBER, "111-222-3333 (Miami)\n444-5555-666 (Tokyo);"
1166                         + "777-888-9999 (Chicago);111-222-3333 (Miami)");
1167         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
1168                 .addExpectedNode("TEL", "111-222-3333", new TypeSet("HOME"))
1169                 .addExpectedNode("TEL", "444-555-5666", new TypeSet("HOME"))
1170                 .addExpectedNode("TEL", "777-888-9999", new TypeSet("HOME"));
1171     }
1172
1173     private void testPickUpNonEmptyContentValuesCommon(int vcardType) {
1174         mVerifier.initForExportTest(vcardType);
1175         ContactEntry entry = mVerifier.addInputEntry();
1176         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1177                 .put(StructuredName.IS_PRIMARY, 1);  // Empty name. Should be ignored.
1178         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1179                 .put(StructuredName.FAMILY_NAME, "family1")  // Not primary. Should be ignored.
1180                 .put(StructuredName.DISPLAY_NAME, "display");
1181         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1182                 .put(StructuredName.IS_PRIMARY, 1)
1183                 .put(StructuredName.FAMILY_NAME, "family2")  // This entry is what we want.
1184                 .put(StructuredName.DISPLAY_NAME, "display");
1185         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1186                 .put(StructuredName.IS_PRIMARY, 1)
1187                 .put(StructuredName.FAMILY_NAME, "family3")
1188                 .put(StructuredName.DISPLAY_NAME, "display");
1189         entry.addContentValues(StructuredName.CONTENT_ITEM_TYPE)
1190                 .put(StructuredName.FAMILY_NAME, "family4")
1191                 .put(StructuredName.DISPLAY_NAME, "display");
1192         mVerifier.addPropertyNodesVerifierElem()
1193                 .addExpectedNode("N", Arrays.asList("family2", "", "", "", ""))
1194                 .addExpectedNode("FN", "display");
1195     }
1196
1197     public void testPickUpNonEmptyContentValuesV21() {
1198         testPickUpNonEmptyContentValuesCommon(V21);
1199     }
1200
1201     public void testPickUpNonEmptyContentValuesV30() {
1202         testPickUpNonEmptyContentValuesCommon(V30);
1203     }
1204
1205     public void testPickUpNonEmptyContentValuesV40() {
1206         testPickUpNonEmptyContentValuesCommon(V40);
1207     }
1208
1209     public void testUseMultiByteTypeV30() {
1210         mVerifier.initForExportTest(V30);
1211         final ContactEntry entry = mVerifier.addInputEntry();
1212         entry.addContentValues(Phone.CONTENT_ITEM_TYPE)
1213                 .put(Phone.TYPE, Phone.TYPE_CUSTOM)
1214                 .put(Phone.LABEL, "\u96FB\u8A71")
1215                 .put(Phone.NUMBER, "1");
1216         mVerifier.addLineVerifierElem()
1217                 .addExpected("N:")
1218                 .addExpected("FN:")
1219                 .addExpected("TEL;TYPE=\u96FB\u8A71:1");
1220         mVerifier.addPropertyNodesVerifierElemWithEmptyName()
1221                 .addExpectedNode("TEL", "1", new TypeSet("\u96FB\u8A71"));
1222     }
1223 }