PullParserTest.java revision 773533775fab54079cebc329d54f6286f5ac16f2
1/*
2 * Copyright (C) 2010 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
17package libcore.xml;
18
19import java.io.ByteArrayInputStream;
20import java.io.IOException;
21import java.io.StringReader;
22import junit.framework.TestCase;
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25
26public abstract class PullParserTest extends TestCase {
27
28    public void testAttributeNoValueWithRelaxed() throws Exception {
29        XmlPullParser parser = newPullParser();
30        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
31        parser.setInput(new StringReader("<input checked></input>"));
32        assertEquals(XmlPullParser.START_TAG, parser.next());
33        assertEquals("input", parser.getName());
34        assertEquals("checked", parser.getAttributeName(0));
35        assertEquals("checked", parser.getAttributeValue(0));
36    }
37
38    public void testAttributeUnquotedValueWithRelaxed() throws Exception {
39        XmlPullParser parser = newPullParser();
40        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
41        parser.setInput(new StringReader("<input checked=true></input>"));
42        assertEquals(XmlPullParser.START_TAG, parser.next());
43        assertEquals("input", parser.getName());
44        assertEquals("checked", parser.getAttributeName(0));
45        assertEquals("true", parser.getAttributeValue(0));
46    }
47
48    public void testUnterminatedEntityWithRelaxed() throws Exception {
49        XmlPullParser parser = newPullParser();
50        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
51        parser.setInput(new StringReader("<foo bar='A&W'>mac&cheese</foo>"));
52        assertEquals(XmlPullParser.START_TAG, parser.next());
53        assertEquals("foo", parser.getName());
54        assertEquals("bar", parser.getAttributeName(0));
55        assertEquals("A&W", parser.getAttributeValue(0));
56        assertEquals(XmlPullParser.TEXT, parser.next());
57        assertEquals("mac&cheese", parser.getText());
58    }
59
60    public void testEntitiesAndNamespaces() throws Exception {
61        XmlPullParser parser = newPullParser();
62        parser.setFeature("http://xmlpull.org/v1/doc/features.html#process-namespaces", true);
63        parser.setInput(new StringReader(
64                "<foo:a xmlns:foo='http://foo' xmlns:bar='http://bar'><bar:b/></foo:a>"));
65        testNamespace(parser);
66    }
67
68    public void testEntitiesAndNamespacesWithRelaxed() throws Exception {
69        XmlPullParser parser = newPullParser();
70        parser.setFeature("http://xmlpull.org/v1/doc/features.html#process-namespaces", true);
71        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
72        parser.setInput(new StringReader(
73                "<foo:a xmlns:foo='http://foo' xmlns:bar='http://bar'><bar:b/></foo:a>"));
74        testNamespace(parser);
75    }
76
77    private void testNamespace(XmlPullParser parser) throws XmlPullParserException, IOException {
78        assertEquals(XmlPullParser.START_TAG, parser.next());
79        assertEquals("http://foo", parser.getNamespace());
80        assertEquals("a", parser.getName());
81        assertEquals(XmlPullParser.START_TAG, parser.next());
82        assertEquals("http://bar", parser.getNamespace());
83        assertEquals("b", parser.getName());
84        assertEquals(XmlPullParser.END_TAG, parser.next());
85        assertEquals("http://bar", parser.getNamespace());
86        assertEquals("b", parser.getName());
87        assertEquals(XmlPullParser.END_TAG, parser.next());
88        assertEquals("http://foo", parser.getNamespace());
89        assertEquals("a", parser.getName());
90    }
91
92    public void testRegularNumericEntities() throws Exception {
93        XmlPullParser parser = newPullParser();
94        parser.setInput(new StringReader("<foo>&#65;</foo>"));
95        assertEquals(XmlPullParser.START_TAG, parser.next());
96        assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
97        assertEquals("#65", parser.getName());
98        assertEquals("A", parser.getText());
99    }
100
101    public void testNumericEntitiesLargerThanChar() throws Exception {
102        XmlPullParser parser = newPullParser();
103        parser.setInput(new StringReader(
104                "<foo>&#2147483647; &#-2147483648;</foo>"));
105        assertParseFailure(parser);
106    }
107
108    public void testNumericEntitiesLargerThanInt() throws Exception {
109        XmlPullParser parser = newPullParser();
110        parser.setInput(new StringReader(
111                "<foo>&#2147483648;</foo>"));
112        assertParseFailure(parser);
113    }
114
115    public void testCharacterReferenceOfHexUtf16Surrogates() throws Exception {
116        testCharacterReferenceOfUtf16Surrogates("<foo>&#x10000; &#x10381; &#x10FFF0;</foo>");
117    }
118
119    public void testCharacterReferenceOfDecimalUtf16Surrogates() throws Exception {
120        testCharacterReferenceOfUtf16Surrogates("<foo>&#65536; &#66433; &#1114096;</foo>");
121    }
122
123    private void testCharacterReferenceOfUtf16Surrogates(String xml) throws Exception {
124        XmlPullParser parser = newPullParser();
125        parser.setInput(new StringReader(xml));
126        assertEquals(XmlPullParser.START_TAG, parser.next());
127        assertEquals(XmlPullParser.TEXT, parser.next());
128        assertEquals(new String(new int[] { 65536, ' ', 66433, ' ', 1114096 }, 0, 5),
129                parser.getText());
130        assertEquals(XmlPullParser.END_TAG, parser.next());
131    }
132
133    public void testCharacterReferenceOfLastUtf16Surrogate() throws Exception {
134        XmlPullParser parser = newPullParser();
135        parser.setInput(new StringReader("<foo>&#x10FFFF;</foo>"));
136        assertEquals(XmlPullParser.START_TAG, parser.next());
137        assertEquals(XmlPullParser.TEXT, parser.next());
138        assertEquals(new String(new int[] { 0x10FFFF }, 0, 1), parser.getText());
139        assertEquals(XmlPullParser.END_TAG, parser.next());
140    }
141
142    public void testOmittedNumericEntities() throws Exception {
143        XmlPullParser parser = newPullParser();
144        parser.setInput(new StringReader("<foo>&#;</foo>"));
145        assertParseFailure(parser);
146    }
147
148    /**
149     * Carriage returns followed by line feeds are silently discarded.
150     */
151    public void testCarriageReturnLineFeed() throws Exception {
152        testLineEndings("\r\n<foo\r\na='b\r\nc'\r\n>d\r\ne</foo\r\n>\r\n");
153    }
154
155    /**
156     * Lone carriage returns are treated like newlines.
157     */
158    public void testLoneCarriageReturn() throws Exception {
159        testLineEndings("\r<foo\ra='b\rc'\r>d\re</foo\r>\r");
160    }
161
162    public void testLoneNewLine() throws Exception {
163        testLineEndings("\n<foo\na='b\nc'\n>d\ne</foo\n>\n");
164    }
165
166    private void testLineEndings(String xml) throws XmlPullParserException, IOException {
167        XmlPullParser parser = newPullParser();
168        parser.setInput(new StringReader(xml));
169        assertEquals(XmlPullParser.START_TAG, parser.next());
170        assertEquals("foo", parser.getName());
171        assertEquals("b c", parser.getAttributeValue(0));
172        assertEquals(XmlPullParser.TEXT, parser.next());
173        assertEquals("d\ne", parser.getText());
174        assertEquals(XmlPullParser.END_TAG, parser.next());
175        assertEquals("foo", parser.getName());
176        assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
177    }
178
179    public void testXmlDeclaration() throws Exception {
180        XmlPullParser parser = newPullParser();
181        parser.setInput(new StringReader(
182                "<?xml version='1.0' encoding='UTF-8' standalone='no'?><foo/>"));
183        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
184        assertEquals("1.0", parser.getProperty(
185                "http://xmlpull.org/v1/doc/properties.html#xmldecl-version"));
186        assertEquals(Boolean.FALSE, parser.getProperty(
187                "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone"));
188        assertEquals("UTF-8", parser.getInputEncoding());
189    }
190
191    public void testXmlDeclarationExtraAttributes() throws Exception {
192        XmlPullParser parser = newPullParser();
193        parser.setInput(new StringReader(
194                "<?xml version='1.0' encoding='UTF-8' standalone='no' a='b'?><foo/>"));
195        try {
196            parser.nextToken();
197            fail();
198        } catch (XmlPullParserException expected) {
199        }
200    }
201
202    public void testCustomEntitiesUsingNext() throws Exception {
203        XmlPullParser parser = newPullParser();
204        parser.setInput(new StringReader(
205                "<foo a='cd&aaaaaaaaaa;ef'>wx&aaaaaaaaaa;yz</foo>"));
206        parser.defineEntityReplacementText("aaaaaaaaaa", "b");
207        assertEquals(XmlPullParser.START_TAG, parser.next());
208        assertEquals("cdbef", parser.getAttributeValue(0));
209        assertEquals(XmlPullParser.TEXT, parser.next());
210        assertEquals("wxbyz", parser.getText());
211    }
212
213    public void testCustomEntitiesUsingNextToken() throws Exception {
214        XmlPullParser parser = newPullParser();
215        parser.setInput(new StringReader(
216                "<foo a='cd&aaaaaaaaaa;ef'>wx&aaaaaaaaaa;yz</foo>"));
217        parser.defineEntityReplacementText("aaaaaaaaaa", "b");
218        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
219        assertEquals("cdbef", parser.getAttributeValue(0));
220        assertEquals(XmlPullParser.TEXT, parser.nextToken());
221        assertEquals("wx", parser.getText());
222        assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
223        assertEquals("aaaaaaaaaa", parser.getName());
224        assertEquals("b", parser.getText());
225        assertEquals(XmlPullParser.TEXT, parser.nextToken());
226        assertEquals("yz", parser.getText());
227    }
228
229    public void testCustomEntitiesAreNotEvaluated() throws Exception {
230        XmlPullParser parser = newPullParser();
231        parser.setInput(new StringReader(
232                "<foo a='&a;'>&a;</foo>"));
233        parser.defineEntityReplacementText("a", "&amp; &a;");
234        assertEquals(XmlPullParser.START_TAG, parser.next());
235        assertEquals("&amp; &a;", parser.getAttributeValue(0));
236        assertEquals(XmlPullParser.TEXT, parser.next());
237        assertEquals("&amp; &a;", parser.getText());
238    }
239
240    public void testMissingEntities() throws Exception {
241        XmlPullParser parser = newPullParser();
242        parser.setInput(new StringReader("<foo>&aaa;</foo>"));
243        assertParseFailure(parser);
244    }
245
246    public void testMissingEntitiesWithRelaxed() throws Exception {
247        XmlPullParser parser = newPullParser();
248        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
249        parser.setInput(new StringReader("<foo>&aaa;</foo>"));
250        assertEquals(XmlPullParser.START_TAG, parser.next());
251        assertEquals(XmlPullParser.TEXT, parser.next());
252        assertEquals(null, parser.getName());
253        assertEquals("Expected unresolved entities to be left in-place. The old parser "
254                + "would resolve these to the empty string.", "&aaa;", parser.getText());
255        assertEquals(XmlPullParser.END_TAG, parser.next());
256    }
257
258    public void testMissingEntitiesUsingNextToken() throws Exception {
259        XmlPullParser parser = newPullParser();
260        testMissingEntitiesUsingNextToken(parser);
261    }
262
263    public void testMissingEntitiesUsingNextTokenWithRelaxed() throws Exception {
264        XmlPullParser parser = newPullParser();
265        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
266        testMissingEntitiesUsingNextToken(parser);
267    }
268
269    private void testMissingEntitiesUsingNextToken(XmlPullParser parser)
270            throws XmlPullParserException, IOException {
271        parser.setInput(new StringReader("<foo>&aaa;</foo>"));
272        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
273        assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
274        assertEquals("aaa", parser.getName());
275        assertEquals(null, parser.getText());
276        assertEquals(XmlPullParser.END_TAG, parser.next());
277    }
278
279    public void testEntityInAttributeUsingNextToken() throws Exception {
280        XmlPullParser parser = newPullParser();
281        parser.setInput(new StringReader("<foo bar=\"&amp;\"></foo>"));
282        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
283        assertEquals("foo", parser.getName());
284        assertEquals("&", parser.getAttributeValue(null, "bar"));
285    }
286
287    public void testMissingEntitiesInAttributesUsingNext() throws Exception {
288        XmlPullParser parser = newPullParser();
289        parser.setInput(new StringReader("<foo b='&aaa;'></foo>"));
290        assertParseFailure(parser);
291    }
292
293    public void testMissingEntitiesInAttributesUsingNextWithRelaxed() throws Exception {
294        XmlPullParser parser = newPullParser();
295        parser.setInput(new StringReader("<foo b='&aaa;'></foo>"));
296        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
297        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
298        assertEquals(1, parser.getAttributeCount());
299        assertEquals("b", parser.getAttributeName(0));
300        assertEquals("Expected unresolved entities to be left in-place. The old parser "
301                + "would resolve these to the empty string.", "&aaa;", parser.getAttributeValue(0));
302    }
303
304    public void testMissingEntitiesInAttributesUsingNextToken() throws Exception {
305        XmlPullParser parser = newPullParser();
306        parser.setInput(new StringReader("<foo b='&aaa;'></foo>"));
307        testMissingEntitiesInAttributesUsingNextToken(parser);
308    }
309
310    public void testMissingEntitiesInAttributesUsingNextTokenWithRelaxed() throws Exception {
311        XmlPullParser parser = newPullParser();
312        parser.setInput(new StringReader("<foo b='&aaa;'></foo>"));
313        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
314        testMissingEntitiesInAttributesUsingNextToken(parser);
315    }
316
317    private void testMissingEntitiesInAttributesUsingNextToken(XmlPullParser parser)
318            throws IOException, XmlPullParserException {
319        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
320        assertEquals(1, parser.getAttributeCount());
321        assertEquals("b", parser.getAttributeName(0));
322        assertEquals("Expected unresolved entities to be left in-place. The old parser "
323                + "would resolve these to the empty string.", "&aaa;", parser.getAttributeValue(0));
324    }
325
326    public void testGreaterThanInText() throws Exception {
327        XmlPullParser parser = newPullParser();
328        parser.setInput(new StringReader("<foo>></foo>"));
329        assertEquals(XmlPullParser.START_TAG, parser.next());
330        assertEquals(XmlPullParser.TEXT, parser.next());
331        assertEquals(">", parser.getText());
332    }
333
334    public void testGreaterThanInAttribute() throws Exception{
335        XmlPullParser parser = newPullParser();
336        parser.setInput(new StringReader("<foo a='>'></foo>"));
337        assertEquals(XmlPullParser.START_TAG, parser.next());
338        assertEquals(">", parser.getAttributeValue(0));
339    }
340
341    public void testLessThanInText() throws Exception{
342        XmlPullParser parser = newPullParser();
343        parser.setInput(new StringReader("<foo><</foo>"));
344        assertParseFailure(parser);
345    }
346
347    public void testLessThanInAttribute() throws Exception{
348        XmlPullParser parser = newPullParser();
349        parser.setInput(new StringReader("<foo a='<'></foo>"));
350        assertParseFailure(parser);
351    }
352
353    public void testQuotesInAttribute() throws Exception{
354        XmlPullParser parser = newPullParser();
355        parser.setInput(new StringReader("<foo a='\"' b=\"'\"></foo>"));
356        assertEquals(XmlPullParser.START_TAG, parser.next());
357        assertEquals("\"", parser.getAttributeValue(0));
358        assertEquals("'", parser.getAttributeValue(1));
359    }
360
361    public void testQuotesInText() throws Exception{
362        XmlPullParser parser = newPullParser();
363        parser.setInput(new StringReader("<foo>\" '</foo>"));
364        assertEquals(XmlPullParser.START_TAG, parser.next());
365        assertEquals(XmlPullParser.TEXT, parser.next());
366        assertEquals("\" '", parser.getText());
367    }
368
369    public void testCdataDelimiterInAttribute() throws Exception{
370        XmlPullParser parser = newPullParser();
371        parser.setInput(new StringReader("<foo a=']]>'></foo>"));
372        assertEquals(XmlPullParser.START_TAG, parser.next());
373        assertEquals("]]>", parser.getAttributeValue(0));
374    }
375
376    public void testCdataDelimiterInText() throws Exception{
377        XmlPullParser parser = newPullParser();
378        parser.setInput(new StringReader("<foo>]]></foo>"));
379        assertParseFailure(parser);
380    }
381
382    public void testUnexpectedEof() throws Exception {
383        XmlPullParser parser = newPullParser();
384        parser.setInput(new StringReader("<foo><![C"));
385        assertParseFailure(parser);
386    }
387
388    public void testUnexpectedSequence() throws Exception {
389        XmlPullParser parser = newPullParser();
390        parser.setInput(new StringReader("<foo><![Cdata[bar]]></foo>"));
391        assertParseFailure(parser);
392    }
393
394    public void testThreeDashCommentDelimiter() throws Exception {
395        XmlPullParser parser = newPullParser();
396        parser.setInput(new StringReader("<foo><!--a---></foo>"));
397        assertParseFailure(parser);
398    }
399
400    public void testTwoDashesInComment() throws Exception {
401        XmlPullParser parser = newPullParser();
402        parser.setInput(new StringReader("<foo><!-- -- --></foo>"));
403        assertParseFailure(parser);
404    }
405
406    public void testEmptyComment() throws Exception {
407        XmlPullParser parser = newPullParser();
408        parser.setInput(new StringReader("<foo><!----></foo>"));
409        assertEquals(XmlPullParser.START_TAG, parser.next());
410        assertEquals(XmlPullParser.COMMENT, parser.nextToken());
411        assertEquals("", parser.getText());
412    }
413
414    /**
415     * Close braces require lookaheads because we need to defend against "]]>".
416     */
417    public void testManyCloseBraces() throws Exception{
418        XmlPullParser parser = newPullParser();
419        parser.setInput(new StringReader("<foo>]]]]]]]]]]]]]]]]]]]]]]]</foo>"));
420        assertEquals(XmlPullParser.START_TAG, parser.next());
421        assertEquals(XmlPullParser.TEXT, parser.next());
422        assertEquals("]]]]]]]]]]]]]]]]]]]]]]]", parser.getText());
423    }
424
425    public void testCommentUsingNext() throws Exception {
426        XmlPullParser parser = newPullParser();
427        parser.setInput(new StringReader("<foo>ab<!-- comment! -->cd</foo>"));
428        assertEquals(XmlPullParser.START_TAG, parser.next());
429        assertEquals(XmlPullParser.TEXT, parser.next());
430        assertEquals("abcd", parser.getText());
431    }
432
433    public void testCommentUsingNextToken() throws Exception {
434        XmlPullParser parser = newPullParser();
435        parser.setInput(new StringReader("<foo>ab<!-- comment! -->cd</foo>"));
436        assertEquals(XmlPullParser.START_TAG, parser.next());
437        assertEquals(XmlPullParser.TEXT, parser.nextToken());
438        assertEquals("ab", parser.getText());
439        assertEquals(XmlPullParser.COMMENT, parser.nextToken());
440        assertEquals(" comment! ", parser.getText());
441        assertEquals(XmlPullParser.TEXT, parser.nextToken());
442        assertEquals("cd", parser.getText());
443    }
444
445    public void testCdataUsingNext() throws Exception {
446        XmlPullParser parser = newPullParser();
447        parser.setInput(new StringReader("<foo>ab<![CDATA[cdef]]gh&amp;i]]>jk</foo>"));
448        assertEquals(XmlPullParser.START_TAG, parser.next());
449        assertEquals(XmlPullParser.TEXT, parser.next());
450        assertEquals("abcdef]]gh&amp;ijk", parser.getText());
451        assertEquals(XmlPullParser.END_TAG, parser.next());
452    }
453
454    public void testCdataUsingNextToken() throws Exception {
455        XmlPullParser parser = newPullParser();
456        parser.setInput(new StringReader("<foo>ab<![CDATA[cdef]]gh&amp;i]]>jk</foo>"));
457        assertEquals(XmlPullParser.START_TAG, parser.next());
458        assertEquals(XmlPullParser.TEXT, parser.nextToken());
459        assertEquals("ab", parser.getText());
460        assertEquals(XmlPullParser.CDSECT, parser.nextToken());
461        assertEquals("cdef]]gh&amp;i", parser.getText());
462        assertEquals(XmlPullParser.TEXT, parser.nextToken());
463        assertEquals("jk", parser.getText());
464        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
465    }
466
467    public void testEntityLooksLikeCdataClose() throws Exception {
468        XmlPullParser parser = newPullParser();
469        parser.setInput(new StringReader("<foo>&#93;&#93;></foo>"));
470        assertEquals(XmlPullParser.START_TAG, parser.next());
471        assertEquals(XmlPullParser.TEXT, parser.next());
472        assertEquals("]]>", parser.getText());
473    }
474
475    public void testProcessingInstructionUsingNext() throws Exception {
476        XmlPullParser parser = newPullParser();
477        parser.setInput(new StringReader("<foo>ab<?cd efg hij?>kl</foo>"));
478        assertEquals(XmlPullParser.START_TAG, parser.next());
479        assertEquals(XmlPullParser.TEXT, parser.next());
480        assertEquals("abkl", parser.getText());
481        assertEquals(XmlPullParser.END_TAG, parser.next());
482    }
483
484    public void testProcessingInstructionUsingNextToken() throws Exception {
485        XmlPullParser parser = newPullParser();
486        parser.setInput(new StringReader("<foo>ab<?cd efg hij?>kl</foo>"));
487        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
488        assertEquals(XmlPullParser.TEXT, parser.nextToken());
489        assertEquals("ab", parser.getText());
490        assertEquals(XmlPullParser.PROCESSING_INSTRUCTION, parser.nextToken());
491        assertEquals("cd efg hij", parser.getText());
492        assertEquals(XmlPullParser.TEXT, parser.nextToken());
493        assertEquals("kl", parser.getText());
494        assertEquals(XmlPullParser.END_TAG, parser.next());
495    }
496
497    public void testWhitespaceUsingNextToken() throws Exception {
498        XmlPullParser parser = newPullParser();
499        parser.setInput(new StringReader("  \n  <foo> \n </foo>   \n   "));
500        assertEquals(XmlPullParser.IGNORABLE_WHITESPACE, parser.nextToken());
501        assertEquals(true, parser.isWhitespace());
502        assertEquals("  \n  ", parser.getText());
503        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
504        assertEquals(XmlPullParser.TEXT, parser.nextToken());
505        assertEquals(true, parser.isWhitespace());
506        assertEquals(" \n ", parser.getText());
507        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
508        assertEquals(XmlPullParser.IGNORABLE_WHITESPACE, parser.nextToken());
509        assertEquals(true, parser.isWhitespace());
510        assertEquals("   \n   ", parser.getText());
511        assertEquals(XmlPullParser.END_DOCUMENT, parser.nextToken());
512    }
513
514    public void testLinesAndColumns() throws Exception {
515        XmlPullParser parser = newPullParser();
516        parser.setInput(new StringReader("\n"
517                + "  <foo><bar a='\n"
518                + "' b='cde'></bar\n"
519                + "><!--\n"
520                + "\n"
521                + "--><baz/>fg\n"
522                + "</foo>"));
523        assertEquals("1,1", parser.getLineNumber() + "," + parser.getColumnNumber());
524        assertEquals(XmlPullParser.IGNORABLE_WHITESPACE, parser.nextToken());
525        assertEquals("2,3", parser.getLineNumber() + "," + parser.getColumnNumber());
526        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
527        assertEquals("2,8", parser.getLineNumber() + "," + parser.getColumnNumber());
528        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
529        assertEquals("3,11", parser.getLineNumber() + "," + parser.getColumnNumber());
530        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
531        assertEquals("4,2", parser.getLineNumber() + "," + parser.getColumnNumber());
532        assertEquals(XmlPullParser.COMMENT, parser.nextToken());
533        assertEquals("6,4", parser.getLineNumber() + "," + parser.getColumnNumber());
534        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
535        assertEquals("6,10", parser.getLineNumber() + "," + parser.getColumnNumber());
536        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
537        assertEquals("6,10", parser.getLineNumber() + "," + parser.getColumnNumber());
538        assertEquals(XmlPullParser.TEXT, parser.nextToken());
539        assertEquals("7,1", parser.getLineNumber() + "," + parser.getColumnNumber());
540        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
541        assertEquals("7,7", parser.getLineNumber() + "," + parser.getColumnNumber());
542        assertEquals(XmlPullParser.END_DOCUMENT, parser.nextToken());
543        assertEquals("7,7", parser.getLineNumber() + "," + parser.getColumnNumber());
544    }
545
546    public void testEmptyEntityReferenceUsingNext() throws Exception {
547        XmlPullParser parser = newPullParser();
548        parser.setInput(new StringReader("<foo>&empty;</foo>"));
549        parser.defineEntityReplacementText("empty", "");
550        assertEquals(XmlPullParser.START_TAG, parser.next());
551        assertEquals(XmlPullParser.END_TAG, parser.next());
552    }
553
554    public void testEmptyEntityReferenceUsingNextToken() throws Exception {
555        XmlPullParser parser = newPullParser();
556        parser.setInput(new StringReader("<foo>&empty;</foo>"));
557        parser.defineEntityReplacementText("empty", "");
558        assertEquals(XmlPullParser.START_TAG, parser.nextToken());
559        assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
560        assertEquals("empty", parser.getName());
561        assertEquals("", parser.getText());
562        assertEquals(XmlPullParser.END_TAG, parser.nextToken());
563    }
564
565    public void testEmptyCdataUsingNext() throws Exception {
566        XmlPullParser parser = newPullParser();
567        parser.setInput(new StringReader("<foo><![CDATA[]]></foo>"));
568        assertEquals(XmlPullParser.START_TAG, parser.next());
569        assertEquals(XmlPullParser.END_TAG, parser.next());
570    }
571
572    public void testEmptyCdataUsingNextToken() throws Exception {
573        XmlPullParser parser = newPullParser();
574        parser.setInput(new StringReader("<foo><![CDATA[]]></foo>"));
575        assertEquals(XmlPullParser.START_TAG, parser.next());
576        assertEquals(XmlPullParser.CDSECT, parser.nextToken());
577        assertEquals("", parser.getText());
578        assertEquals(XmlPullParser.END_TAG, parser.next());
579    }
580
581    public void testParseReader() throws Exception {
582        String snippet = "<dagny dad=\"bob\">hello</dagny>";
583        XmlPullParser parser = newPullParser();
584        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
585        parser.setInput(new StringReader(snippet));
586        validate(parser);
587    }
588
589    public void testParseInputStream() throws Exception {
590        String snippet = "<dagny dad=\"bob\">hello</dagny>";
591        XmlPullParser parser = newPullParser();
592        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
593        parser.setInput(new ByteArrayInputStream(snippet.getBytes()), "UTF-8");
594        validate(parser);
595    }
596
597    static void validate(XmlPullParser parser)
598            throws XmlPullParserException, IOException {
599        assertEquals(XmlPullParser.START_DOCUMENT, parser.getEventType());
600        assertEquals(0, parser.getDepth());
601        assertEquals(XmlPullParser.START_TAG, parser.next());
602        assertEquals(1, parser.getDepth());
603        assertEquals("dagny", parser.getName());
604        assertEquals(1, parser.getAttributeCount());
605        assertEquals("dad", parser.getAttributeName(0));
606        assertEquals("bob", parser.getAttributeValue(0));
607        assertEquals("bob", parser.getAttributeValue(null, "dad"));
608        assertEquals(XmlPullParser.TEXT, parser.next());
609        assertEquals(1, parser.getDepth());
610        assertEquals("hello", parser.getText());
611        assertEquals(XmlPullParser.END_TAG, parser.next());
612        assertEquals(1, parser.getDepth());
613        assertEquals("dagny", parser.getName());
614        assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
615        assertEquals(0, parser.getDepth());
616    }
617
618    public void testNamespaces() throws Exception {
619        String xml = "<one xmlns='ns:default' xmlns:n1='ns:1' a='b'>\n"
620                + "  <n1:two c='d' n1:e='f' xmlns:n2='ns:2'>text</n1:two>\n"
621                + "</one>";
622
623        XmlPullParser parser = newPullParser();
624        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
625        parser.setInput(new StringReader(xml));
626
627        assertEquals(0, parser.getDepth());
628        assertEquals(0, parser.getNamespaceCount(0));
629
630        try {
631            parser.getNamespaceCount(1);
632            fail();
633        } catch (IndexOutOfBoundsException e) { /* expected */ }
634
635        // one
636        assertEquals(XmlPullParser.START_TAG, parser.next());
637        assertEquals(1, parser.getDepth());
638
639        checkNamespacesInOne(parser);
640
641        // n1:two
642        assertEquals(XmlPullParser.START_TAG, parser.nextTag());
643
644        assertEquals(2, parser.getDepth());
645        checkNamespacesInTwo(parser);
646
647        // Body of two.
648        assertEquals(XmlPullParser.TEXT, parser.next());
649
650        // End of two.
651        assertEquals(XmlPullParser.END_TAG, parser.nextTag());
652
653        // Depth should still be 2.
654        assertEquals(2, parser.getDepth());
655
656        // We should still be able to see the namespaces from two.
657        checkNamespacesInTwo(parser);
658
659        // End of one.
660        assertEquals(XmlPullParser.END_TAG, parser.nextTag());
661
662        // Depth should be back to 1.
663        assertEquals(1, parser.getDepth());
664
665        // We can still see the namespaces in one.
666        checkNamespacesInOne(parser);
667
668        // We shouldn't be able to see the namespaces in two anymore.
669        try {
670            parser.getNamespaceCount(2);
671            fail();
672        } catch (IndexOutOfBoundsException e) { /* expected */ }
673
674        assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
675
676        // We shouldn't be able to see the namespaces in one anymore.
677        try {
678            parser.getNamespaceCount(1);
679            fail();
680        } catch (IndexOutOfBoundsException e) { /* expected */ }
681
682        assertEquals(0, parser.getNamespaceCount(0));
683    }
684
685    private void checkNamespacesInOne(XmlPullParser parser) throws XmlPullParserException {
686        assertEquals(2, parser.getNamespaceCount(1));
687
688        // Prefix for default namespace is null.
689        assertNull(parser.getNamespacePrefix(0));
690        assertEquals("ns:default", parser.getNamespaceUri(0));
691
692        assertEquals("n1", parser.getNamespacePrefix(1));
693        assertEquals("ns:1", parser.getNamespaceUri(1));
694
695        assertEquals("ns:default", parser.getNamespace(null));
696
697        // KXML returns null.
698        // assertEquals("ns:default", parser.getNamespace(""));
699    }
700
701    private void checkNamespacesInTwo(XmlPullParser parser) throws XmlPullParserException {
702        // These should still be valid.
703        checkNamespacesInOne(parser);
704
705        assertEquals(3, parser.getNamespaceCount(2));
706
707        // Default ns should still be in the stack
708        assertNull(parser.getNamespacePrefix(0));
709        assertEquals("ns:default", parser.getNamespaceUri(0));
710    }
711
712    private void assertParseFailure(XmlPullParser parser) throws IOException {
713        try {
714            while (parser.next() != XmlPullParser.END_DOCUMENT) {
715            }
716            fail();
717        } catch (XmlPullParserException expected) {
718        }
719    }
720
721    /**
722     * Creates a new pull parser.
723     */
724    abstract XmlPullParser newPullParser();
725}
726