/** * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.waveprotocol.wave.model.document.parser; import junit.framework.TestCase; import org.waveprotocol.wave.model.document.indexed.IndexedDocument; import org.waveprotocol.wave.model.document.raw.impl.Element; import org.waveprotocol.wave.model.document.raw.impl.Node; import org.waveprotocol.wave.model.document.raw.impl.Text; import org.waveprotocol.wave.model.document.util.DocProviders; import org.waveprotocol.wave.model.util.Pair; import org.waveprotocol.wave.model.util.StringMap; /** * Tests for parser package * */ public class ParserTest extends TestCase { public void testParseCharData() { { try { StreamingXmlParser parser = new StreamingXmlParser("abcde"); Item text = parser.getTextChunk(); assertEquals("abcde", text.data); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("ab^cde<"); Item text = parser.getTextChunk(); assertEquals("ab^cde", text.data); } catch (XmlParseException e) { fail(e.getMessage()); } } // non decimal digits try { StreamingXmlParser parser = new StreamingXmlParser("&#abc;"); Item text = parser.getTextChunk(); fail("Exception should've been thrown"); } catch (XmlParseException e) { } // Invalid codepoint try { StreamingXmlParser parser = new StreamingXmlParser("�"); Item text = parser.getTextChunk(); fail("Exception should've been thrown"); } catch (XmlParseException e) { } // Low surrogate followed by high surrogate try { StreamingXmlParser parser = new StreamingXmlParser("��"); Item text = parser.getTextChunk(); fail("Exception should've been thrown"); } catch (XmlParseException e) { } } public void testParseAttribute() { { try { StreamingXmlParser parser = new StreamingXmlParser("abcm='hello'"); Pair<String, String> attr = parser.attr(); assertEquals("abcm", attr.first); assertEquals("hello", attr.second); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("abcm='hello&'"); Pair<String, String> attr = parser.attr(); assertEquals("abcm", attr.first); assertEquals("hello&", attr.second); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("abcm='hello world'"); Pair<String, String> attr = parser.attr(); assertEquals("abcm", attr.first); assertEquals("hello world", attr.second); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("abcm='hello world>'"); Pair<String, String> attr = parser.attr(); assertEquals("abcm", attr.first); assertEquals("hello world>", attr.second); } catch (XmlParseException e) { fail(e.getMessage()); } } } public void testParseRepeatedAttribute() { try { StreamingXmlParser parser = new StreamingXmlParser(" abc='def' hello=\"world\" "); StringMap<String> attrList = parser.attrList(); assertEquals("def", attrList.get("abc")); assertEquals("world", attrList.get("hello")); } catch (XmlParseException e) { fail(e.getMessage()); } } public void testParseElement() { { try { StreamingXmlParser parser = new StreamingXmlParser("<doc abc='def' hello=\"world\"/>"); Item element = parser.startTag(); assertEquals("doc", element.name); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("<doc abc='def' hello=\"world\">asdf</doc>"); Item start = parser.startTag(); Item text = parser.getTextChunk(); Item end = parser.endTag(); assertEquals("doc", start.name); assertEquals("asdf", text.data); assertEquals("doc", end.name); } catch (XmlParseException e) { fail(e.getMessage()); } } } public void testPI() { { try { StreamingXmlParser parser = new StreamingXmlParser("<?hello abcdef?>"); Item pi; pi = parser.processingInstruction(); assertEquals("hello", pi.name); assertEquals("abcdef", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } } try { StreamingXmlParser parser = new StreamingXmlParser("<?ab cd?>"); Item pi; pi = parser.processingInstruction(); assertEquals("ab", pi.name); assertEquals("cd", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } { try { StreamingXmlParser parser = new StreamingXmlParser("<?x <??>"); Item pi; pi = parser.processingInstruction(); assertEquals("x", pi.name); assertEquals("<?", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { StreamingXmlParser parser = new StreamingXmlParser("<?a <body><ab?>"); Item pi; pi = parser.processingInstruction(); assertEquals("a", pi.name); assertEquals("<body><ab", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } } // test invalid start char for PITarget { try { StreamingXmlParser parser = new StreamingXmlParser("<?<doc> <bodyabc?>"); Item pi = parser.processingInstruction(); fail("should've thrown exception"); } catch (XmlParseException e) { } } try { StreamingXmlParser parser = new StreamingXmlParser("<?abc?>"); Item pi; pi = parser.processingInstruction(); assertEquals("abc", pi.name); assertEquals("", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } try { StreamingXmlParser parser = new StreamingXmlParser("<?abc ?>"); Item pi; pi = parser.processingInstruction(); assertEquals("abc", pi.name); assertEquals("", pi.data); } catch (XmlParseException e) { fail(e.getMessage()); } } public void testGetItem() { { try { StreamingXmlParser parser = new StreamingXmlParser("<doc abc='def' hello=\"world\"><x></x>asdf<z></z></doc>"); Item item; item = parser.getItem(); assertTrue(item.type == ItemType.START_ELEMENT); assertEquals("doc", item.name); item = parser.getItem(); assertTrue(item.type == ItemType.START_ELEMENT); assertEquals("x", item.name); item = parser.getItem(); assertTrue(item.type == ItemType.END_ELEMENT); assertEquals("x", item.name); item = parser.getItem(); assertTrue(item.type == ItemType.TEXT); assertEquals("asdf", item.data); item = parser.getItem(); assertTrue(item.type == ItemType.START_ELEMENT); assertEquals("z", item.name); item = parser.getItem(); assertTrue(item.type == ItemType.END_ELEMENT); assertEquals("z", item.name); item = parser.getItem(); assertTrue(item.type == ItemType.END_ELEMENT); assertEquals("doc", item.name); } catch (XmlParseException e) { fail(e.getMessage()); } } } public void testUTF16Surrogate() { // Test valid surrogate { try { XmlPullParser parser = new StreamingXmlParser("<doc>\uD800\uDC00def</doc>"); assertTrue(parser.next() == ItemType.START_ELEMENT); assertTrue(parser.next() == ItemType.TEXT); assertEquals("\uD800\uDC00def", parser.getText()); assertTrue(parser.next() == ItemType.END_ELEMENT); assertFalse(parser.hasNext()); } catch (XmlParseException e) { fail(e.getMessage()); } } // Test invalid surrogate throws exception { try { XmlPullParser parser = new StreamingXmlParser("<doc>\uD800\uD800def</doc>"); assertTrue(parser.next() == ItemType.START_ELEMENT); assertTrue(parser.next() == ItemType.TEXT); fail("Invalid surrogate should thrown parse exeption"); } catch (XmlParseException e) { // good, exception thrown } } } public void testXmlPullParserInterface() { xmlPullParserInterfaceTestHelper(true); xmlPullParserInterfaceTestHelper(false); } public void xmlPullParserInterfaceTestHelper(boolean useBufferedParser) { { try { XmlPullParser parser = getParser("", useBufferedParser); assertFalse(parser.hasNext()); } catch (XmlParseException e) { fail (e.getMessage()); } try { XmlPullParser parser = getParser("<doc/>", useBufferedParser); assertTrue(parser.hasNext()); assertTrue(parser.next() == ItemType.START_ELEMENT); assertTrue(parser.next() == ItemType.END_ELEMENT); assertTrue(!parser.hasNext()); } catch (XmlParseException e) { fail (e.getMessage()); } try { XmlPullParser parser = getParser("<doc abc='def' hello=\"world\"><x></x>asdf<z></z></doc>", useBufferedParser); assertTrue(parser.hasNext()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals(ItemType.TEXT, parser.next()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertFalse(parser.hasNext()); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { XmlPullParser parser = getParser("some text > & <", useBufferedParser); assertTrue(parser.hasNext()); assertEquals(ItemType.TEXT, parser.next()); assertEquals("some text > & <", parser.getText()); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { XmlPullParser parser = getParser( "<body><?a 'conv/title'='' 'lang'='unknown'?><line/>spelly test<?a 'lang'?></body>", useBufferedParser); assertTrue(parser.hasNext()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals("body", parser.getTagName()); assertEquals(ItemType.PROCESSING_INSTRUCTION, parser.next()); assertEquals("a", parser.getProcessingInstructionName()); assertEquals("'conv/title'='' 'lang'='unknown'", parser.getProcessingInstructionValue()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals(ItemType.TEXT, parser.next()); assertEquals("spelly test", parser.getText()); assertEquals(ItemType.PROCESSING_INSTRUCTION, parser.next()); assertEquals("a", parser.getProcessingInstructionName()); assertEquals("'lang'", parser.getProcessingInstructionValue()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals("body", parser.getTagName()); } catch (XmlParseException e) { fail(e.getMessage()); } } { try { XmlPullParser parser = getParser( "<body></body>hello<a/>", useBufferedParser); assertTrue(parser.hasNext()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals("body", parser.getTagName()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals("body", parser.getTagName()); assertEquals(ItemType.TEXT, parser.next()); assertEquals("hello", parser.getText()); assertEquals(ItemType.START_ELEMENT, parser.next()); assertEquals("a", parser.getTagName()); assertEquals(ItemType.END_ELEMENT, parser.next()); assertEquals("a", parser.getTagName()); } catch (XmlParseException e) { fail(e.getMessage()); } } } public void testIllFormedXml() { assertParserThrowsException("<? hello <doc>hello</doc>"); assertParserThrowsException("<doc src='hi>hello</doc>"); assertParserThrowsException("<doc hello </doc>"); assertParserThrowsException("<doc> hello <\\doc>"); assertParserThrowsException("<doc> hello"); assertParserThrowsException("<a><b>hello</a></b>"); assertParserThrowsException("<doc src='hi\">hello</doc>"); assertParserThrowsException("<doc>hello<? ></doc>"); assertParserThrowsException("<doc>hello<? foo></doc>"); } public void testDocProviderParse() { String testStr = "<body><?a \"conv/title\"=\"\" \"lang\"=\"unknown\"?><line/>spelly test<?a \"conv/title\" \"lang\"?></body>"; IndexedDocument<Node, Element, Text> parse = DocProviders.POJO.parse(testStr); assertEquals(testStr, parse.toXmlString()); } private void assertParserThrowsException(String input) { try { XmlPullParser parser = getParser(input, false); while (parser.hasNext()) { parser.next(); } } catch (XmlParseException e) { return; } catch (RuntimeXmlParseException e){ return; } fail("Parsing ill-formed expression did not throw exception."); } private XmlPullParser getParser(String input, boolean buffered) throws XmlParseException { if (buffered) { return XmlParserFactory.buffered(input); } else { return XmlParserFactory.unbuffered(input); } } // public void testNewXmlPullParserSpeed() { // String s = "<doc abc='def' hello=\"world\"><x></x>asdf<z></z></doc>"; // StringBuilder b = new StringBuilder(); // // for (int i = 0; i < 500000; ++i) { // b.append(s); // } // // try { // StreamingXmlParser parser = new StreamingXmlParser(b.toString()); // while (parser.hasNext()) { // parser.next(); // parser.getCurrentItem(); // } // } catch (XmlParseException e) { // fail(e.getMessage()); // } // } // // public void testOldXmlPullParserSpeed() { // String s = "<doc abc='def' hello=\"world\"><x></x>asdf<z></z></doc>"; // StringBuilder b = new StringBuilder(); // // for (int i = 0; i < 50000; ++i) { // b.append(s); // } // // XmlPullParser parser = new SimpleXmlParser(b.toString()); // while (parser.hasNext()) { // parser.next(); // } // } }