blob: 7e849d6f6bee0a2043576711a5bc7f36e87fb589 [file]
/* Copyright 2004 The Apache Software Foundation
*
* 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 ValidatingXSRTests.detailed;
import com.foo.sample.HeadingDocument;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.impl.validator.ValidatingXMLStreamReader;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openuri.test.location.LocationDocument;
import org.openuri.test.mixedContent.LetterDocument;
import org.openuri.test.mixedContent.NoMixedDocument;
import org.openuri.test.person.Name;
import org.openuri.test.person.PersonDocument;
import org.openuri.test.person.PersonType;
import tools.util.JarUtil;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.StreamReaderDelegate;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import static org.junit.jupiter.api.Assertions.*;
// Schema Imports
public class ValidatingXmlStreamReaderTests {
// Base variable
static String casesLoc = "xbean/ValidatingStream/";
//////////////////////////////////////////////////////////////////////
// Tests
// NOTE: Tests that use getCasesFile are reading files
// from cases/qatest/files/xbean
// Tests that use getResourceFromJar are getting the contents of
// the file in the same location, but packaged into xmlcases.jar
// SO, any change to the xml files for these tests will not be
// reflected till they make it into xmlcases.jar. (ant build.xmlcases)
@Test
void testDocWithNoSchema() throws Exception {
checkDocIsInvalid(getCasesFile(casesLoc + "po.xml"), null);
}
@Test
void testValidLocationDoc() throws Exception {
checkDocIsValid(getCasesFile(casesLoc + "location.xml"), null);
}
@Test
void testInvalidLocationDoc() throws Exception {
checkDocIsInvalid(getCasesFile(casesLoc + "location-inv.xml"), LocationDocument.type);
}
@Test
void testValidPersonDoc() throws Exception {
checkDocIsValid(getCasesFile(casesLoc + "person.xml"), PersonDocument.type);
}
@Test
void testInvalidPersonDoc() throws Exception {
checkDocIsInvalid(getCasesFile(casesLoc + "person-inv.xml"), PersonDocument.type);
}
@Test
void testValidMixedContentDoc() throws Exception {
checkDocIsValid(getCasesFile(casesLoc + "mixed-content.xml"), LetterDocument.type);
}
@Test
void testInvalidNomixedContentDoc() throws Exception {
checkDocIsInvalid(getCasesFile(casesLoc + "nomixed-content-inv.xml"), NoMixedDocument.type);
}
@Test
void testInvalidMissingAttributeDoc() throws Exception {
checkDocIsInvalid(getCasesFile(casesLoc + "foo-inv.xml"), HeadingDocument.type);
}
@Test
void testContentName() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-frag.xml");
SchemaType type = Name.type;
assertTrue(checkContent(sXml, type, true), "Xml-fragment is not valid:\n" + sXml);
}
// Same as testContentName.. expect the xml has no chars before the first
// start element
@Test
void testContentName2() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-frag2.xml");
SchemaType type = Name.type;
assertTrue(checkContent(sXml, type, true), "Xml-fragment is not valid:\n" + sXml);
}
@Test
void testContentSibling() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-sibling.xml");
SchemaType type = PersonType.type;
assertTrue(checkContent(sXml, type, true), "Xml-fragment is not valid:\n" + sXml);
}
@Test
void testInvalidContentSibling() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-sibling-inv.xml");
SchemaType type = PersonType.type;
assertFalse(checkContent(sXml, type, true), "Invalid Xml-fragment is getting validated:\n" + sXml);
}
@Test
void testValidXsiType() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-justname.xml");
SchemaType type = Name.type;
assertTrue(checkContent(sXml, type, true), "Xml-fragment is not valid:\n" + sXml);
}
@Test
void testInvalidXsiType() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-justname-inv.xml");
SchemaType type = Name.type;
assertFalse(checkContent(sXml, type, true), "Invalid Xml-fragment is getting validated:\n" + sXml);
}
@Test
void testIncompatibleXsiType() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "person-xsi-inv.xml");
SchemaType type = Name.type;
assertFalse(checkContent(sXml, type, true), "Invalid Xml-fragment is getting validated:\n" + sXml);
}
@Test
void testValidMixedContent() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "mixed-content.xml");
SchemaType type = org.openuri.test.mixedContent.LetterType.type;
assertTrue(checkContent(sXml, type, true), "Xml-fragment is not valid:\n" + sXml);
}
@Test
@Disabled
public void testGlobalAttribute() throws Exception {
String sXml = JarUtil.getResourceFromJar(casesLoc + "global-attr.xml");
assertTrue(checkContent(sXml, null, true), "Global Attribute test failed:\n");
}
// Tests for increasing code-coverage metrics
@Test
void testValXsrReuse() throws Exception {
Collection<XmlError> errors = new ArrayList<>();
File[] xmls = new File[2];
xmls[0] = getCasesFile(casesLoc + "person.xml");
xmls[1] = getCasesFile(casesLoc + "person-inv.xml");
SchemaType type = PersonDocument.type;
boolean[] ret = runValidator(xmls, type, errors);
String common = "Test for ValidatingXmlStreamReader reuse failed";
assertEquals(2, ret.length, common + "\nReturn value has more than 2 elements");
assertTrue(ret[0] && !ret[1], common + "\nExpected: true & false. Actual: " + ret[0] + " & " + ret[1]);
}
// public void testIllegalEvent() throws Exception {
// Will require writing another XSR wrapper.. albeit simple
// }
private boolean runValidator(File xml,
SchemaType type,
Collection<XmlError> errors)
throws IllegalArgumentException, Exception {
if (errors == null) {
throw new IllegalArgumentException(
"Collection object cannot be null");
}
XMLStreamReader xsr = XMLInputFactory.newInstance().
createXMLStreamReader(new FileInputStream(xml));
ValidatingXMLStreamReader valXsr = new ValidatingXMLStreamReader();
valXsr.init(xsr,
false,
type,
XmlBeans.typeLoaderForClassLoader(ValidatingXMLStreamReader.class.getClassLoader()),
null,
errors);
// Walk through the xml
while (valXsr.hasNext()) {
valXsr.next();
}
return valXsr.isValid();
//return true;
}
// This method is primarily for testing re-use of the ValXSR object.
// but could come in handy later..
private boolean[] runValidator(File[] xml,
SchemaType type,
Collection<XmlError> errors)
throws IllegalArgumentException, Exception {
if (errors == null) {
throw new IllegalArgumentException(
"Collection object cannot be null");
}
ValidatingXMLStreamReader valXsr = new ValidatingXMLStreamReader();
boolean[] retArray = new boolean[xml.length];
for (int i = 0; i < xml.length; i++) {
XMLStreamReader xsr = XMLInputFactory.newInstance().
createXMLStreamReader(new FileInputStream(xml[i]));
valXsr.init(xsr,
false,
type,
XmlBeans.typeLoaderForClassLoader(ValidatingXMLStreamReader.class.getClassLoader()),
null,
errors);
// Walk through the xml
while (valXsr.hasNext()) {
valXsr.next();
}
retArray[i] = valXsr.isValid();
}
return retArray;
}
protected void checkDocIsValid(File file, SchemaType type) throws Exception {
Collection<XmlError> errors = new ArrayList<>();
boolean isValid = runValidator(file, type, errors);
assertTrue(isValid, "File '" + file.getName() + "' is invalid.");
}
protected void checkDocIsInvalid(File file, SchemaType type) throws Exception {
Collection<XmlError> errors = new ArrayList<>();
boolean isValid = runValidator(file, type, errors);
assertFalse(isValid, "File '" + file.getName() + "' is valid, but was expecting invalid.");
}
public boolean checkContent(String fragment,
SchemaType type,
boolean printErrors) throws Exception {
XMLStreamReader xsr = XMLInputFactory.newInstance().
createXMLStreamReader(new StringReader(fragment));
XmlContentTestXSR cxsr = new XmlContentTestXSR(xsr);
Collection<XmlError> errors = new ArrayList<>();
ValidatingXMLStreamReader valXsr = new ValidatingXMLStreamReader();
valXsr.init(cxsr,
false,
type,
XmlBeans.typeLoaderForClassLoader(ValidatingXMLStreamReader.class.getClassLoader()),
null,
errors);
// Walk through the xml
while (valXsr.hasNext()) {
valXsr.next();
}
return valXsr.isValid();
}
private static File getCasesFile(String path)
throws java.io.IOException {
if (path.isEmpty()) {
throw new IOException("getCasesFile was called with path of len 0");
}
return JarUtil.getResourceFromJarasFile(path);
//return new File(casesRoot + path);
}
/////////////////////////////////////////////////////////////////////////
// XmlStreamReader extension for content Validation
// will not work for Global Attribute
private static class XmlContentTestXSR extends StreamReaderDelegate implements XMLStreamReader {
private static final int TAGOPEN = 100;
private static final int TAGCLOSE = 101;
private static final int UNDEFINED = 99;
private static final int ATTRIBUTE = 102;
private static final int ENDCONTENT = 103;
int state = -1;
int depth = -1;
boolean initialized = false;
int attributeCount = -1;
boolean hasAttributes = false;
// Constructor Wrappers
public XmlContentTestXSR(XMLStreamReader xsr)
throws XMLStreamException {
super(xsr);
}
public boolean hasNext() {
if (state == UNDEFINED || state == ENDCONTENT) {
return false;
}
if (!initialized) // next() has not been called yet
{
return true;
}
return true;
}
public int next()
throws XMLStreamException {
int _next;
if (!initialized) {
// First time next() is called..
// Scan for the first XMLEvent.START_ELEMENT
_next = UNDEFINED;
while ((super.hasNext()) && (_next != XMLEvent.START_ELEMENT)) {
_next = super.next();
}
if (_next != XMLEvent.START_ELEMENT) {
throw new XMLStreamException(
"Could not find a start element");
}
initialized = true;
// Now move past the first tag
state = TAGOPEN;
depth = 1;
if ((attributeCount = super.getAttributeCount()) > 0) {
// The first element has attributes.. this is part of
// the content. So the first event should XMLEvent.ATTRIBUTE
_next = XMLEvent.ATTRIBUTE;
} else {
// return super.next();
/*
If content is <xml-fragment/> then we will have returned
END_ELEMENT above, without ever generating a START_ELEMENT
In this case probably we should detect this and return a
END_DOCUMENT
*/
_next = super.next();
if (_next == XMLEvent.END_ELEMENT) {
_next = XMLEvent.END_DOCUMENT;
state = ENDCONTENT;
}
}
return _next;
}
_next = super.next();
switch (_next) {
case XMLEvent.START_ELEMENT:
state = TAGOPEN;
depth++;
break;
case XMLEvent.END_ELEMENT:
--depth;
if (depth < 0 && state == TAGOPEN) {
throw new XMLStreamException(
"Illegal XML Stream state");
} else if (depth == 0 && state == TAGOPEN) {
state = ENDCONTENT;
// at this point we will return ENDDOCUMENT
_next = XMLEvent.END_DOCUMENT;
}
break;
}
return _next;
}
}
}