1// Copyright 2007 The Android Open Source Project
2package com.android.providers.calendar;
3
4import com.android.calendarcommon2.ICalendar;
5
6import android.test.suitebuilder.annotation.SmallTest;
7import junit.framework.TestCase;
8
9import java.util.List;
10
11public class ICalendarTest extends TestCase {
12
13    @SmallTest
14    public void testAddParameter() throws Exception {
15        ICalendar.Property prop = new ICalendar.Property("prop1", "value1");
16        assertEquals(0, prop.getParameterNames().size());
17        prop.addParameter(new ICalendar.Parameter("param1", "foo"));
18        assertEquals(1, prop.getParameterNames().size());
19        prop.addParameter(new ICalendar.Parameter("param1", "bar"));
20        assertEquals(1, prop.getParameterNames().size());
21        prop.addParameter(new ICalendar.Parameter("param2", "baaz"));
22        assertEquals(2, prop.getParameterNames().size());
23        prop.addParameter(new ICalendar.Parameter("param1", "quux"));
24        assertEquals(2, prop.getParameterNames().size());
25        prop.addParameter(new ICalendar.Parameter("param3", "accent"));
26        assertEquals(3, prop.getParameterNames().size());
27        assertEquals("prop1;param1=foo;param1=bar;param1=quux;"
28                + "param2=baaz;param3=accent:value1", prop.toString());
29    }
30
31    @SmallTest
32    public void testAddProperty() throws Exception {
33        String text = "BEGIN:DUMMY\n" +
34                "prop2:value3\n" +
35                "prop1:value1\n" +
36                "prop1:value2\n" +
37                "END:DUMMY\n";
38
39        ICalendar.Component component = new ICalendar.Component("DUMMY", null);
40        // properties should be listed in insertion order, by property name.
41        component.addProperty(new ICalendar.Property("prop2", "value3"));
42        component.addProperty(new ICalendar.Property("prop1", "value1"));
43        component.addProperty(new ICalendar.Property("prop1", "value2"));
44        assertEquals(text, component.toString());
45    }
46
47    @SmallTest
48    public void testAddComponent() throws Exception {
49        String text = "BEGIN:DUMMY\n" +
50                "prop1:value1\n" +
51                "prop1:value12\n" +
52                "BEGIN:DUMMY2\n" +
53                "prop2:value2\n" +
54                "END:DUMMY2\n" +
55                "END:DUMMY\n";
56
57        ICalendar.Component parent = new ICalendar.Component("DUMMY", null);
58        // properties should precede components
59        ICalendar.Component child = new ICalendar.Component("DUMMY2", parent);
60        child.addProperty(new ICalendar.Property("prop2", "value2"));
61        parent.addChild(child);
62        parent.addProperty(new ICalendar.Property("prop1", "value1"));
63        parent.addProperty(new ICalendar.Property("prop1", "value12"));
64        assertEquals(text, parent.toString());
65    }
66
67    @SmallTest
68    public void testParseBasicComponent() throws Exception {
69        String text = "BEGIN:DUMMY\n" +
70                "PROP1;PARAM1=foo;PARAM2=bar:VALUE1\n" +
71                "PROP1;PARAM1=baaz;PARAM1=quux:VALUE2\n" +
72                "PROP2:VALUE3\n" +
73                "END:DUMMY\n";
74
75        ICalendar.Component component = ICalendar.parseComponent(text);
76
77        assertEquals("DUMMY", component.getName());
78        assertNull(component.getComponents());
79        assertEquals(2, component.getPropertyNames().size());
80        ICalendar.Property prop1 = component.getFirstProperty("PROP1");
81        assertEquals(2, prop1.getParameterNames().size());
82        assertEquals("foo", prop1.getFirstParameter("PARAM1").value);
83        assertEquals("bar", prop1.getFirstParameter("PARAM2").value);
84        List<ICalendar.Property> props = component.getProperties("PROP1");
85        assertEquals(2, props.size());
86        List<ICalendar.Parameter> params = props.get(1).getParameters("PARAM1");
87        assertEquals("baaz", params.get(0).value);
88        assertEquals("quux", params.get(1).value);
89    }
90
91    @SmallTest
92    public void testParseQuotedParam() throws Exception {
93        ICalendar.Component component
94                = new ICalendar.Component("DUMMY", null /* parent */);
95        ICalendar.parseComponent(
96                component,
97                "DTSTART;TZID=\"GMT+03:00\";TEST=test1;TEST=\"test2\":20101221T090000");
98        ICalendar.Property property = component.getFirstProperty("DTSTART");
99        assertEquals(2, property.getParameterNames().size());
100        assertEquals("GMT+03:00", property.getFirstParameter("TZID").value);
101        final List<ICalendar.Parameter> testParameters = property.getParameters("TEST");
102        assertEquals(2, testParameters.size());
103        assertEquals("test1", testParameters.get(0).value);
104        assertEquals("test2", testParameters.get(1).value);
105        assertEquals("20101221T090000", component.getFirstProperty("DTSTART").getValue());
106    }
107
108    @SmallTest
109    public void testParseBadQuotedParam() throws Exception {
110        ICalendar.Component component
111                = new ICalendar.Component("DUMMY", null /* parent */);
112
113        ICalendar.parseComponent(
114                component,
115                "FOO;PARAM1=\"param1\"\";PARAM=quote-before-param:value");
116        assertNull("Invalid quote before param value", component.getFirstProperty("FOO"));
117
118        ICalendar.parseComponent(
119                component,
120                "FOO;PARAM\"=expected-equal:value");
121        assertNull("Expected equal in param", component.getFirstProperty("FOO"));
122
123        ICalendar.parseComponent(
124                component,
125                "FOO;PARAM=text-not-allowed\"before-quote:value");
126        assertNull("Invalid quote in param value", component.getFirstProperty("FOO"));
127
128        ICalendar.parseComponent(
129                component,
130                "FOO;PARAM=\"missing-end-quote:value");
131        assertNull("missing-end-quote", component.getFirstProperty("FOO"));
132    }
133
134    @SmallTest
135    public void testParseChildComponent() throws Exception {
136        String childText = "BEGIN:CHILD\n" +
137                "PROP1;PARAM1=foo;PARAM2=bar:VALUE1\n" +
138                "PROP1;PARAM1=baaz;PARAM1=quux:VALUE2\n" +
139                "PROP2:VALUE3\n" +
140                "END:CHILD\n";
141
142        String completeText = "BEGIN:DUMMY\n" +
143                childText +
144                "END:DUMMY\n";
145
146        ICalendar.Component component = new ICalendar.Component("DUMMY", null);
147        component = ICalendar.parseComponent(component, childText);
148        assertEquals("DUMMY", component.getName());
149        assertEquals(1, component.getComponents().size());
150        assertEquals(completeText, component.toString());
151    }
152
153    @SmallTest
154    public void testParseBareEvent() throws Exception {
155        String text = "BEGIN:VEVENT\nEND:VEVENT\n";
156        ICalendar.Component event = ICalendar.parseEvent(text);
157
158        assertEquals("VEVENT", event.getName());
159        assertNull(event.getComponents());
160        assertEquals(0, event.getPropertyNames().size());
161    }
162
163    @SmallTest
164    public void testParseEvent1() throws Exception {
165        String text = "BEGIN:VEVENT\n" +
166                "DTSTART:19970714T170000Z\n" +
167                "DTEND:19970715T035959Z\n" +
168                "SUMMARY:Bastille Day Party\n" +
169                "END:VEVENT\n";
170
171        ICalendar.Component event = ICalendar.parseEvent(text);
172
173        assertEquals("VEVENT", event.getName());
174        assertNull(event.getComponents());
175        assertEquals(3, event.getPropertyNames().size());
176        assertEquals(1, event.getProperties("DTSTART").size());
177        assertEquals("19970714T170000Z", event.getFirstProperty("DTSTART").getValue());
178        assertEquals(0, event.getFirstProperty("DTSTART").getParameterNames().size());
179        assertEquals(1, event.getProperties("DTEND").size());
180        assertEquals(0, event.getFirstProperty("DTEND").getParameterNames().size());
181        assertEquals("19970715T035959Z", event.getFirstProperty("DTEND").getValue());
182        assertEquals(1, event.getProperties("SUMMARY").size());
183        assertEquals(0, event.getFirstProperty("SUMMARY").getParameterNames().size());
184        assertEquals("Bastille Day Party", event.getFirstProperty("SUMMARY").getValue());
185    }
186
187    @SmallTest
188    public void testParseEvent2() throws Exception {
189        String text = "BEGIN:VEVENT\n" +
190                "DTSTART;TZID=America/Los_Angeles:19970714T170000\n" +
191                "DURATION:+P3600S\n" +
192                "SUMMARY;FOO=1;BAR=2:Bastille Day Party\n" +
193                "END:VEVENT\n";
194
195        ICalendar.Component event = ICalendar.parseEvent(text);
196
197        assertEquals("VEVENT", event.getName());
198        assertNull(event.getComponents());
199        assertEquals(3, event.getPropertyNames().size());
200        assertEquals(1, event.getProperties("DTSTART").size());
201        assertEquals("19970714T170000", event.getFirstProperty("DTSTART").getValue());
202        assertEquals(1, event.getFirstProperty("DTSTART").getParameterNames().size());
203        assertEquals(1, event.getProperties("SUMMARY").size());
204    }
205
206    @SmallTest
207    public void testParseInvalidProperty() throws Exception {
208        String text = "BEGIN:VEVENT\n" +
209                "FOO;BAR\n" + // invalid line
210                "END:VEVENT\n";
211
212        ICalendar.Component event = ICalendar.parseEvent(text);
213
214        assertEquals("VEVENT", event.getName());
215        assertNull(event.getComponents());
216        assertEquals(0, event.getPropertyNames().size());
217    }
218
219    @SmallTest
220    public void testParseEventDoesNotStartWithBegin() throws Exception {
221        String text = "NOTBEGIN:DUMMY\n" +
222                "END:DUMMY\n";
223
224        try {
225            ICalendar.parseEvent(text);
226            fail("expected exception not thrown");
227        } catch (ICalendar.FormatException e) {
228            assertEquals("Expected " + ICalendar.Component.VEVENT, e.getMessage());
229        }
230    }
231
232    @SmallTest
233    public void testParseCalendarDoesNotStartWithBegin() throws Exception {
234        String text = "NOTBEGIN:DUMMY\n" +
235                "END:DUMMY\n";
236
237        try {
238            ICalendar.parseCalendar(text);
239            fail("expected exception not thrown");
240        } catch (ICalendar.FormatException e) {
241            assertEquals("Expected " + ICalendar.Component.VCALENDAR, e.getMessage());
242        }
243    }
244
245    @SmallTest
246    public void testParseComponentDoesNotStartWithBegin() throws Exception {
247        String text = "NOTBEGIN:DUMMY\n" +
248                "END:DUMMY\n";
249
250        ICalendar.Component component = ICalendar.parseComponent(text);
251        assertNull(component);
252    }
253
254    @SmallTest
255    public void testParseUnexpectedEndComponent() throws Exception {
256        String text = "BEGIN:PARENT\n" +
257                "END:BADPARENT\n";
258
259        ICalendar.Component component = ICalendar.parseComponent(text);
260        assertNotNull(component);
261    }
262
263    @SmallTest
264    public void testParseNoEndComponent() throws Exception {
265        String text = "BEGIN:DUMMY\n" +
266                "END:\n";
267
268        ICalendar.Component component = ICalendar.parseComponent(text);
269        assertNotNull(component);
270    }
271
272    @SmallTest
273    public void testNormalize() throws Exception {
274        String text = "BEGIN:VEVENT\n" +
275                "RRULE:FREQ=SECONDLY;BYSECOND=0,1,2,\r\n 3,4,5\r\n ,6,7,8\r\n" +
276                "END:VEVENT\n";
277
278        ICalendar.Component event = ICalendar.parseEvent(text);
279
280        assertEquals("VEVENT", event.getName());
281        assertNull(event.getComponents());
282        assertEquals(1, event.getPropertyNames().size());
283        assertEquals(1, event.getProperties("RRULE").size());
284        assertEquals("FREQ=SECONDLY;BYSECOND=0,1,2,3,4,5,6,7,8", event.getFirstProperty("RRULE").getValue());
285
286    }
287
288    @SmallTest
289    public void testNormalizeBadSep() throws Exception {
290        String text = "BEGIN:VEVENT\n" +
291                "RRULE:FREQ=SECONDLY;BYSECOND=0,1,2,\n 3,4,5\n ,6,7,8\n" +
292                "END:VEVENT\n";
293
294        ICalendar.Component event = ICalendar.parseEvent(text);
295
296        assertEquals("VEVENT", event.getName());
297        assertNull(event.getComponents());
298        assertEquals(1, event.getPropertyNames().size());
299        assertEquals(1, event.getProperties("RRULE").size());
300        assertEquals("FREQ=SECONDLY;BYSECOND=0,1,2,3,4,5,6,7,8", event.getFirstProperty("RRULE").getValue());
301    }
302
303
304    @SmallTest
305    public void testBad() throws Exception {
306        String text = "BEGIN:VEVENT\n" +
307                "RRULE=foo\n" +
308                "END:VEVENT\n";
309
310        ICalendar.Component event = ICalendar.parseEvent(text);
311
312        // Note that parseEvent doesn't throw the FormatException you might expect because
313        // ICalendar.parseComponentImpl catches the exception due to misformatted GData.
314        // TODO: update this test after cleaning up the ICalendar behavior
315    }
316}
317