TestEventReader.java
package org.codehaus.stax.test.evt;
import java.util.NoSuchElementException;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
/**
* Class that contains simple tests for making sure that event objects
* created by the {@link XMLEventFactory} have expected properties.
*
* @author Tatu Saloranta
*/
public class TestEventReader
extends BaseEventTest
{
public void testSimpleValid()
throws XMLStreamException
{
/* Whether prolog/epilog white space is reported is not defined
* by StAX specs, thus, let's not add any
*/
String XML = "<?xml version='1.0' ?>"
+"<!DOCTYPE root [ ]>"
+"<root attr='123'><!-- comment -->\n"
+"</root>";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(DTD, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(COMMENT, er.nextEvent().getEventType());
// for fun, let's just use next() instead of nextEvent()
XMLEvent evt = (XMLEvent) er.next();
assertTokenType(CHARACTERS, evt.getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
assertFalse(er.hasNext());
er.close();
}
}
public void testInvalidUsage()
throws XMLStreamException
{
String XML = "<?xml version='1.0' ?><root />";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
@SuppressWarnings("unused")
XMLEvent evt = (XMLEvent) er.nextEvent();
// Let's try removal:
String msg = null;
try {
er.remove();
msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove()";
} catch (UnsupportedOperationException e) {
; // good
} catch (Throwable t) {
msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove(); instead got: "+t;
}
if (msg != null) {
fail(msg);
}
}
}
/**
* The main purpose of this test is to ensure that an exception
* is thrown at the end.
*/
public void testIterationEndException()
throws XMLStreamException
{
String XML = "<root />";
for (int i = 0; i < 4; ++i) {
boolean coal = (i & 1) != 0;
boolean checkHasNext = (i & 2) != 0;
XMLEventReader er = getReader(XML, true, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
if (checkHasNext) {
assertFalse(er.hasNext());
}
XMLEvent ev = null;
try {
ev = er.nextEvent();
} catch (NoSuchElementException nex) {
continue; // good
} catch (Throwable t) {
fail("Expected a NoSuchElementException after iterating through the document; got "+t);
}
// Shouldn't get this far...
fail("Expected a NoSuchElementException after iterating through the document; got event: "+ev);
}
}
public void testNextTagOk()
throws XMLStreamException
{
String XML = "<root>\n"
+"<branch> <leaf> </leaf></branch>"
+"</root>";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextTag().getEventType());
assertTokenType(START_ELEMENT, er.nextTag().getEventType());
/* Ok, let's mix in bit of peeking to ensure reader won't
* be confused too badly...
*/
// This should be space between <branch> and <leaf>...
assertTokenType(CHARACTERS, er.peek().getEventType());
// And then the leaf
assertTokenType(START_ELEMENT, er.nextTag().getEventType());
assertTokenType(END_ELEMENT, er.nextTag().getEventType());
assertTokenType(END_ELEMENT, er.nextTag().getEventType());
assertTokenType(END_ELEMENT, er.nextTag().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
assertFalse(er.hasNext());
}
}
public void testNextTagInvalid()
throws XMLStreamException
{
String XML = "<root> non-empty<leaf /></root>";
String XML2 = "<root><leaf></leaf>text </root>";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
String msg = null;
try {
/*XMLEvent evt =*/ er.nextTag();
msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS";
} catch (XMLStreamException sex) {
// fine!
} catch (Throwable t) {
msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS; got ("+t.getClass()+"): "+t;
}
if (msg != null) {
fail(msg);
}
er.close();
/* any other easily failing cases? Maybe if we are on top of
* END_ELEMENT, and will hit another one?
*/
er = getReader(XML2, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
try {
XMLEvent evt = er.nextTag();
msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got event "+tokenTypeDesc(evt);
} catch (XMLStreamException sex) {
msg = null; // fine!
} catch (Throwable t) {
msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got: "+t;
}
if (msg != null) {
fail(msg);
}
er.close();
}
}
public void testSkip()
throws XMLStreamException
{
String XML = "<?xml version='1.0' ?><!DOCTYPE root><root>\n"
+"<branch> <leaf> </leaf></branch><!-- comment -->"
+"</root>";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.peek().getEventType());
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
assertTokenType(DTD, er.peek().getEventType());
assertTokenType(DTD, er.nextEvent().getEventType());
assertTokenType(START_ELEMENT, er.peek().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(CHARACTERS, er.peek().getEventType());
assertTokenType(CHARACTERS, er.nextEvent().getEventType());
// branch
assertTokenType(START_ELEMENT, er.peek().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(CHARACTERS, er.peek().getEventType());
assertTokenType(CHARACTERS, er.nextEvent().getEventType());
// leaf
assertTokenType(START_ELEMENT, er.peek().getEventType());
assertTokenType(START_ELEMENT, er.nextEvent().getEventType());
assertTokenType(CHARACTERS, er.peek().getEventType());
assertTokenType(CHARACTERS, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.peek().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.peek().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(COMMENT, er.peek().getEventType());
assertTokenType(COMMENT, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.peek().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_DOCUMENT, er.peek().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
assertFalse(er.hasNext());
}
}
/**
* This test was inspired by an actual bug in one of implementations:
* initial state was not properly set if nextTag() was called (instead
* of nextEvent()), and subsequent peek() failed.
*/
public void testPeek()
throws XMLStreamException
{
String XML = "<root>text</root>";
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent tag = er.nextTag();
assertTokenType(START_ELEMENT, tag.getEventType());
// Now, peek() should produce text..
XMLEvent text = er.peek();
assertTokenType(CHARACTERS, text.getEventType());
Characters chars = text.asCharacters();
assertNotNull(chars);
assertEquals("text", chars.getData());
// and need nextEvent() to get rid of it, too:
text = er.nextEvent();
// Let's verify it again:
assertTokenType(CHARACTERS, text.getEventType());
chars = text.asCharacters();
assertNotNull(chars);
assertEquals("text", chars.getData());
assertTokenType(END_ELEMENT, er.nextTag().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
// And at the end, peek() should return null
assertNull(er.peek());
}
}
public void testElementText()
throws XMLStreamException
{
String TEXT1 = "some\ntest";
String TEXT2 = "inside CDATA too!";
String XML = "<root>"+TEXT1+"<![CDATA["+TEXT2+"]]></root>";
// First, let's see how things work without peeking:
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent elem = er.nextEvent();
assertTokenType(START_ELEMENT, elem.getEventType());
try {
assertEquals(TEXT1+TEXT2, er.getElementText());
} catch (XMLStreamException sex) {
fail("Failed on XMLEventReader.getElementText(): "+sex);
}
/* 06-Jan-2006, TSa: I'm really not sure whether to expect
* END_ELEMENT, or END_DOCUMENT here... maybe the latter
* makes more sense? For now let's accept both, however.
*/
elem = er.nextEvent();
if (elem.getEventType() != END_DOCUMENT
&& elem.getEventType() != END_ELEMENT) {
fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType()));
}
}
// and then with peeking:
for (int i = 0; i < 4; ++i) {
boolean ns = (i & 1) != 0;
boolean coal = (i & 2) != 0;
XMLEventReader er = getReader(XML, ns, coal);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent elem = er.nextEvent();
assertTokenType(START_ELEMENT, elem.getEventType());
XMLEvent peeked = er.peek();
assertTokenType(CHARACTERS, peeked.getEventType());
assertEquals(TEXT1+TEXT2, er.getElementText());
/* 06-Jan-2006, TSa: I'm really not sure whether to expect
* END_ELEMENT, or END_DOCUMENT here... maybe the latter
* makes more sense? For now let's accept both, however.
*/
elem = er.nextEvent();
if (elem.getEventType() != END_DOCUMENT
&& elem.getEventType() != END_ELEMENT) {
fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType()));
}
}
}
/*
/////////////////////////////////////////////////
// Internal methods:
/////////////////////////////////////////////////
*/
private XMLEventReader getReader(String contents, boolean nsAware,
boolean coalesce)
throws XMLStreamException
{
return getReader(contents, nsAware, coalesce, true);
}
private XMLEventReader getReader(String contents, boolean nsAware,
boolean coalesce, boolean expandEnt)
throws XMLStreamException
{
//XMLInputFactory f = getInputFactory();
XMLInputFactory f = getNewInputFactory();
setNamespaceAware(f, nsAware);
setCoalescing(f, coalesce);
setSupportDTD(f, true);
setValidating(f, false);
setReplaceEntities(f, expandEnt);
return constructEventReader(f, contents);
}
}