1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.vcard.tests;
17
18import com.android.vcard.VCardInterpreter;
19import com.android.vcard.VCardParser;
20import com.android.vcard.VCardParser_V21;
21import com.android.vcard.VCardParser_V30;
22import com.android.vcard.VCardProperty;
23import com.android.vcard.exception.VCardException;
24
25import android.test.AndroidTestCase;
26
27import java.io.IOException;
28import java.io.InputStream;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.List;
32
33/**
34 * Tests for basic {@link VCardParser} capability (e.g. if it calls callbacks
35 * in {@link VCardInterpreter}}.
36 */
37public class VCardParserTests extends AndroidTestCase {
38    private enum Order {
39        START,
40        END,
41        START_ENTRY,
42        END_ENTRY,
43        PROPERTY_CREATED,
44    }
45
46    private class MockVCardInterpreter implements VCardInterpreter {
47        private final List<Order> mHistory = new ArrayList<Order>();
48        private final List<Order> mExpectedOrder = new ArrayList<Order>();
49
50        public MockVCardInterpreter addExpectedOrder(Order order) {
51            mExpectedOrder.add(order);
52            return this;
53        }
54
55        private void inspectOrder(Order order) {
56            mHistory.add(order);
57            final Order top = mExpectedOrder.get(0);
58            assertEquals(top, order);
59            mExpectedOrder.remove(0);
60        }
61
62        public void verify() {
63            assertTrue(String.format("Remaining: " + Arrays.toString(mExpectedOrder.toArray())),
64                    mExpectedOrder.isEmpty());
65        }
66
67        @Override
68        public void onVCardStarted() {
69            inspectOrder(Order.START);
70        }
71
72        @Override
73        public void onVCardEnded() {
74            inspectOrder(Order.END);
75        }
76
77        @Override
78        public void onEntryStarted() {
79            inspectOrder(Order.START_ENTRY);
80        }
81
82        @Override
83        public void onEntryEnded() {
84            inspectOrder(Order.END_ENTRY);
85        }
86
87        @Override
88        public void onPropertyCreated(VCardProperty property) {
89            inspectOrder(Order.PROPERTY_CREATED);
90        }
91    }
92
93    public void testSimple() throws IOException, VCardException {
94        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_simple_1);
95        try {
96            VCardParser parser = new VCardParser_V21();
97            MockVCardInterpreter interpreter = new MockVCardInterpreter();
98            interpreter.addExpectedOrder(Order.START)
99                    .addExpectedOrder(Order.START_ENTRY)
100                    .addExpectedOrder(Order.PROPERTY_CREATED)
101                    .addExpectedOrder(Order.END_ENTRY)
102                    .addExpectedOrder(Order.END);
103            parser.addInterpreter(interpreter);
104            parser.parse(inputStream);
105            interpreter.verify();
106        } finally {
107            inputStream.close();
108        }
109    }
110
111    public void testNest() throws IOException, VCardException {
112        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_nest);
113        try {
114            VCardParser parser = new VCardParser_V21();
115            MockVCardInterpreter interpreter = new MockVCardInterpreter();
116            interpreter.addExpectedOrder(Order.START)
117                    .addExpectedOrder(Order.START_ENTRY)
118                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
119                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
120                    .addExpectedOrder(Order.START_ENTRY)  // First nested vCard begins
121                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
122                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
123                    .addExpectedOrder(Order.END_ENTRY)  // First nested vCard ends
124                    .addExpectedOrder(Order.START_ENTRY)  // Second nested vCard begins
125                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
126                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
127                    .addExpectedOrder(Order.END_ENTRY)  // Second nested vCard ends
128                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
129                    .addExpectedOrder(Order.END_ENTRY)
130                    .addExpectedOrder(Order.END);
131            parser.addInterpreter(interpreter);
132            parser.parse(inputStream);
133            interpreter.verify();
134        } finally {
135            inputStream.close();
136        }
137    }
138
139    /**
140     * Test vCard containing v3.0 line continuations and with non-standard
141     * line terminators \r\r\n coming from iOS 6.1.3. Tests to make sure the
142     * parser correctly skips the extra line terminators and still
143     * successfully concatenates the multi-line block.
144     */
145    public void testIosMultiline() throws IOException, VCardException {
146        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v30_ios_613_multiline);
147        try {
148            VCardParser parser = new VCardParser_V30();
149            MockVCardInterpreter interpreter = new MockVCardInterpreter();
150            interpreter.addExpectedOrder(Order.START)
151                    .addExpectedOrder(Order.START_ENTRY)
152                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
153                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
154                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For FN
155                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For ORG
156                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For item1
157                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
158                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For item2
159                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For item3
160                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For PHOTO
161                    .addExpectedOrder(Order.END_ENTRY)
162                    .addExpectedOrder(Order.END);
163            parser.addInterpreter(interpreter);
164            parser.parse(inputStream);
165            interpreter.verify();
166        } finally {
167            inputStream.close();
168        }
169    }
170
171    /**
172     * Tests if {@link VCardParser#parse(InputStream)} parses the whole vCard file and
173     * {@link VCardParser#parseOne(InputStream)} parses just first entry of a vCard file
174     * with multiple vCard entries.
175     */
176    public void testParseOne() throws IOException, VCardException {
177        InputStream inputStream =
178                getContext().getResources().openRawResource(R.raw.v21_multiple_entry);
179        try {
180            VCardParser parser = new VCardParser_V21();
181            MockVCardInterpreter interpreter = new MockVCardInterpreter();
182            interpreter.addExpectedOrder(Order.START)
183                    .addExpectedOrder(Order.START_ENTRY)
184                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
185                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
186                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
187                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
188                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
189                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
190                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
191                    .addExpectedOrder(Order.END_ENTRY)
192                    .addExpectedOrder(Order.START_ENTRY)
193                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
194                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
195                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
196                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
197                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
198                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
199                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
200                    .addExpectedOrder(Order.END_ENTRY)
201                    .addExpectedOrder(Order.START_ENTRY)
202                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
203                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
204                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
205                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
206                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
207                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
208                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
209                    .addExpectedOrder(Order.END_ENTRY)
210                    .addExpectedOrder(Order.END);
211            parser.addInterpreter(interpreter);
212            // Use parse() to check we
213            parser.parse(inputStream);
214            interpreter.verify();
215        } finally {
216            inputStream.close();
217        }
218
219        inputStream = getContext().getResources().openRawResource(R.raw.v21_multiple_entry);
220        try {
221            VCardParser parser = new VCardParser_V21();
222            MockVCardInterpreter interpreter = new MockVCardInterpreter();
223            interpreter.addExpectedOrder(Order.START)
224                    .addExpectedOrder(Order.START_ENTRY)
225                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
226                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
227                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
228                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
229                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
230                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
231                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
232                    .addExpectedOrder(Order.END_ENTRY)
233                    .addExpectedOrder(Order.END);
234            parser.addInterpreter(interpreter);
235            parser.parseOne(inputStream);
236            interpreter.verify();
237        } finally {
238            inputStream.close();
239        }
240
241    }
242}
243