blob: c4e5bdc371be24e9b088b76f5f4d8466e29c6661 [file] [log] [blame]
/* 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 compile.scomp.checkin;
import compile.scomp.common.CompileCommon;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.XmlOptions.BeanMethod;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.tool.*;
import org.apache.xmlbeans.impl.util.FilerImpl;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.TopLevelComplexType;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Stream;
import static common.Common.getRootFile;
import static java.util.Collections.singletonList;
import static org.junit.Assert.*;
@SuppressWarnings({"SpellCheckingInspection", "ResultOfMethodCallIgnored"})
public class CompilationTests {
private static final File fwroot = new File(getRootFile());
//location of files under "cases folder"
private static final String fileLocation = CompileCommon.fileLocation;
private static final File outputroot = new File(fwroot, "build/test/output");
private static final String[] invalidSchemas = {
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>\n" +
" <xs:complexType name='base' final='extension'/>\n" +
" <xs:complexType name='ext'>\n" +
" <xs:complexContent>\n" +
" <xs:extension base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>\n" +
" <xs:complexType name='base' final='#all'/>\n" +
" <xs:complexType name='ext'>\n" +
" <xs:complexContent>\n" +
" <xs:extension base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' finalDefault='#all'>\n" +
" <xs:complexType name='base'/>\n" +
" <xs:complexType name='rest'>\n" +
" <xs:complexContent>\n" +
" <xs:restriction base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' finalDefault='restriction'>\n" +
" <xs:complexType name='base'/>\n" +
" <xs:complexType name='rest'>\n" +
" <xs:complexContent>\n" +
" <xs:restriction base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
};
static String[] validSchemas = {
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>\n" +
" <xs:complexType name='base' final='extension'/>\n" +
" <xs:complexType name='rest'>\n" +
" <xs:complexContent>\n" +
" <xs:restriction base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>\n" +
" <xs:complexType name='base' final='restriction'/>\n" +
" <xs:complexType name='ext'>\n" +
" <xs:complexContent>\n" +
" <xs:extension base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' finalDefault='restriction'>\n" +
" <xs:complexType name='base'/>\n" +
" <xs:complexType name='ext'>\n" +
" <xs:complexContent>\n" +
" <xs:extension base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' finalDefault='extension'>\n" +
" <xs:complexType name='base'/>\n" +
" <xs:complexType name='rest'>\n" +
" <xs:complexContent>\n" +
" <xs:restriction base='base'/>\n" +
" </xs:complexContent>\n" +
" </xs:complexType>\n" +
"</xs:schema>\n",
};
@Test
public void testJ2EE() {
deltree(xbeanOutput("compile/scomp/j2ee"));
// First, compile schema
File srcdir = xbeanOutput("compile/scomp/j2ee/j2eeconfigxml/src");
File classesdir = xbeanOutput("compile/scomp/j2ee/j2eeconfigxml/classes");
File outputjar = xbeanOutput("compile/scomp/j2ee/j2eeconfigxml.jar");
Parameters params = new Parameters();
params.setXsdFiles(
xbeanCase("j2ee/application-client_1_4.xsd"),
xbeanCase("j2ee/application_1_4.xsd"),
xbeanCase("j2ee/connector_1_5.xsd"),
xbeanCase("j2ee/ejb-jar_2_1.xsd"),
xbeanCase("j2ee/j2ee_1_4.xsd"),
xbeanCase("j2ee/jsp_2_0.xsd"),
xbeanCase("j2ee/web-app_2_4.xsd"),
xbeanCase("j2ee/XML.xsd"));
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
params.setMdefNamespaces(Collections.singleton("http://java.sun.com/xml/ns/j2ee"));
List<XmlError> errors = new ArrayList<>();
params.setErrorListener(errors);
boolean result = SchemaCompiler.compile(params);
StringWriter message = new StringWriter();
if (!result)
dumpErrors(errors, new PrintWriter(message));
assertTrue("Build failed:" + message, result);
assertTrue("Cannot find " + outputjar, outputjar.exists());
}
@Test
public void testIncrementalCompilation() throws IOException, XmlException {
File[] files = new File[]{
xbeanCase("incr/incr1.xsd"),
xbeanCase("incr/incr3.xsd"),
xbeanCase("incr/incr4.xsd"),
xbeanCase("incr/incr2.xsd"),
xbeanCase("incr/incr2-1.xsd")
};
int n = files.length;
SchemaDocument.Schema[] schemas = new SchemaDocument.Schema[n - 1];
SchemaTypeSystem system;
deltree(xbeanOutput("compile/scomp/incr"));
File out = xbeanOutput("compile/scomp/incr/out");
File outincr = xbeanOutput("compile/scomp/incr/outincr");
for (int i = 0; i < n - 2; i++)
schemas[i] = SchemaDocument.Factory.parse(files[i]).getSchema();
// Compile incrementally
// Initial compile
schemas[n - 2] = SchemaDocument.Factory.parse(files[n - 2]).getSchema();
List<XmlError> errors = new ArrayList<>();
XmlOptions options = (new XmlOptions()).setErrorListener(errors);
SchemaTypeSystem builtin = XmlBeans.getBuiltinTypeSystem();
system = XmlBeans.compileXsd(schemas, builtin, options);
Assert.assertNotNull("Compilation failed during inititial compile.", system);
System.out.println("-= Initial Compile =-");
for (int i = 0; i < system.globalTypes().length; i++) {
System.out.println("[" + i + "]-" + system.globalTypes()[i].getName());
}
for (int i = 0; i < system.globalAttributes().length; i++) {
System.out.println("[" + i + "]-" + system.globalAttributes()[i].getName());
}
for (int i = 0; i < system.globalElements().length; i++) {
System.out.println("[" + i + "]=" + system.globalElements()[i].getName());
}
// Incremental compile
String url = schemas[n - 2].documentProperties().getSourceName();
SchemaDocument.Schema[] schemas1 = new SchemaDocument.Schema[1];
schemas1[0] = SchemaDocument.Factory.parse(files[n - 1]).getSchema();
schemas1[0].documentProperties().setSourceName(url);
errors.clear();
system = XmlBeans.compileXsd(system, schemas1, builtin, options);
Assert.assertNotNull("Compilation failed during incremental compile.", system);
SchemaCodeGenerator.saveTypeSystem(system, outincr, null, null, null);
System.out.println("-= Incremental Compile =-");
for (int i = 0; i < system.globalTypes().length; i++) {
System.out.println("[" + i + "]-" + system.globalTypes()[i].getName());
}
for (int i = 0; i < system.globalAttributes().length; i++) {
System.out.println("[" + i + "]-" + system.globalAttributes()[i].getName());
}
for (int i = 0; i < system.globalElements().length; i++) {
System.out.println("[" + i + "]=" + system.globalElements()[i].getName());
}
// Now compile non-incrementally for the purpose of comparing the result
errors.clear();
schemas[n - 2] = schemas1[0];
system = XmlBeans.compileXsd(schemas, builtin, options);
Assert.assertNotNull("Compilation failed during reference compile.", system);
Filer filer = new FilerImpl(out, null, null, false, false);
system.save(filer);
System.out.println("-= Sanity Compile =-");
for (int i = 0; i < system.globalTypes().length; i++) {
System.out.println("[" + i + "]-" + system.globalTypes()[i].getName());
}
for (int i = 0; i < system.globalAttributes().length; i++) {
System.out.println("[" + i + "]-" + system.globalAttributes()[i].getName());
}
for (int i = 0; i < system.globalElements().length; i++) {
System.out.println("[" + i + "]=" + system.globalElements()[i].getName());
}
// Compare the results
String oldPropValue = System.getProperty("xmlbeans.diff.diffIndex");
System.setProperty("xmlbeans.diff.diffIndex", "false");
errors.clear();
List<String> diffs = new ArrayList<>();
Diff.dirsAsTypeSystems(out, outincr, diffs);
System.setProperty("xmlbeans.diff.diffIndex", oldPropValue == null ? "true" : oldPropValue);
assertEquals("Differences encountered:" + String.join("\n", diffs), 0, diffs.size());
}
@Test
public void testSchemaBookmarks() throws XmlException, IOException {
File srcSchema = xbeanCase("../../simple/person/person.xsd");
// Parse
SchemaDocument.Schema parsed = SchemaDocument.Factory.parse(srcSchema).getSchema();
// Navigate to the type definition
TopLevelComplexType[] cTypes = parsed.getComplexTypeArray();
boolean found = false;
int i;
for (i = 0; i < cTypes.length; i++)
if ("person".equals(cTypes[i].getName())) {
found = true;
break;
}
assertTrue("Could not find the \"person\" complex type", found);
// Set the bookmark
SchemaBookmark sb = new SchemaBookmark("MyBookmark");
cTypes[i].newCursor().setBookmark(sb);
// Compile it into STS
SchemaTypeSystem sts = XmlBeans.compileXsd(new XmlObject[]{parsed},
XmlBeans.getBuiltinTypeSystem(), null);
Assert.assertNotNull("Could not compile person.xsd", sts);
SchemaType personType = sts.findType(QNameHelper.forLNS("person", "http://openuri.org/mytest"));
Assert.assertNotNull("Could not find the \"person\" schema type", personType);
// Check that the bookmark made it through
Object val = personType.getUserData();
Assert.assertNotNull("Schema user data not found!", val);
Assert.assertEquals("MyBookmark", val);
}
@Test
public void testSimple() throws MalformedURLException, ClassNotFoundException {
deltree(xbeanOutput("compile/scomp/simple"));
// First, compile schema
// First, compile schema
File inputfile1 = xbeanCase("../../simple/person/person.xsd");
File inputfile2 = xbeanCase("../../simple/person/simplec.xsd");
File srcdir = xbeanOutput("simple/simpletypes/src");
File classesdir = xbeanOutput("compile/scomp/simple/simpletypes/classes");
File outputjar = xbeanOutput("compile/scomp/simple/simpletypes.jar");
Parameters params = new Parameters();
params.setXsdFiles(inputfile1, inputfile2);
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
assertTrue("Build failed", SchemaCompiler.compile(params));
// Then, compile java classes
File javasrc = new File(CompileCommon.fileLocation+"/simple");
File javaclasses = xbeanOutput("compile/scomp/simple/javaclasses");
javaclasses.mkdirs();
File[] testcp = Stream.concat(Stream.of(CodeGenUtil.systemClasspath()), Stream.of(outputjar)).toArray(File[]::new);
CodeGenUtil.externalCompile(singletonList(javasrc), javaclasses, testcp, true);
// Then run the test
URLClassLoader childcl = new URLClassLoader(new URL[]{outputjar.toURI().toURL()}, CompilationTests.class.getClassLoader());
Class<?> cl = childcl.loadClass("scomp.simple.SimplePersonTest");
Result result = JUnitCore.runClasses(cl);
assertEquals(0, result.getFailureCount());
}
@Test
@Ignore
public void testDownload() {
deltree(xbeanOutput("compile/scomp/include"));
{
// First, compile schema without download and verify failure
File srcdir = xbeanOutput("compile/scomp/include/shouldfail/src");
File classesdir = xbeanOutput("compile/scomp/include/shouldfail/classes");
File outputjar = xbeanOutput("compile/scomp/include/shouldfail.jar");
Parameters params = new Parameters();
params.setXsdFiles(xbeanCase("compile/scomp/j2ee/j2ee_1_4.xsd"));
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
assertFalse("Build should have failed", SchemaCompiler.compile(params));
assertFalse("Should not have created " + outputjar, outputjar.exists());
}
{
// now turn on download and verify success
File srcdir = xbeanOutput("compile/scomp/include/shouldsucceed/src");
File classesdir = xbeanOutput("compile/scomp/include/shouldsucceed/classes");
File outputjar = xbeanOutput("compile/scomp/include/shouldsucceed.jar");
Parameters params = new Parameters();
params.setDownload(true);
params.setXsdFiles(xbeanCase("compile/scomp/j2ee/j2ee_1_4.xsd"));
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
assertTrue("Build failed", SchemaCompiler.compile(params));
assertTrue("Cannout find " + outputjar, outputjar.exists());
}
}
@Test
public void testPricequote() {
deltree(xbeanOutput("compile/scomp/pricequote"));
// First, compile schema
File srcdir = xbeanOutput("compile/scomp/pricequote/src");
File classesdir = xbeanOutput("compile/scomp/pricequote/classes");
File outputjar = xbeanOutput("compile/scomp/pricequote/pricequote.jar");
Parameters params = new Parameters();
params.setXsdFiles(xbeanCase("pricequote/PriceQuote.xsd"));
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
assertTrue("Build failed " + fwroot, SchemaCompiler.compile(params));
assertTrue("Cannout find " + outputjar, outputjar.exists());
}
@Test
public void testInvalid() throws XmlException {
for (String schemaFile : invalidSchemas) {
// Parse the invalid schema files
SchemaDocument schema = SchemaDocument.Factory.parse(schemaFile);
// Now compile the invalid schemas, test that they fail
assertThrows("Schema should have failed to compile:\n" + schemaFile, XmlException.class,
() -> XmlBeans.loadXsd(schema));
}
}
@Test
public void testValid() throws XmlException {
for (String schemaFile : validSchemas) {
// Parse the valid schema files
SchemaDocument schema = SchemaDocument.Factory.parse(schemaFile);
// Compile the valid schemas. They should not fail
SchemaTypeLoader xs = XmlBeans.loadXsd(schema);
assertNotNull(xs);
}
}
@Test
public void partials() throws InterruptedException, IOException {
String[] files = {"partials/RootDocument.java", "partials/impl/RootDocumentImpl.java"};
String[] templ = new String[files.length];
for (int i=0; i<files.length; i++) {
Path p = xbeanCase(files[i]).toPath();
templ[i] = new String(Files.readAllBytes(p), StandardCharsets.UTF_8);
}
deltree(xbeanOutput("compile/scomp/partials"));
File srcdir = xbeanOutput("compile/scomp/partials/src");
File classesdir = xbeanOutput("compile/scomp/partials/classes");
File outputjar = xbeanOutput("compile/scomp/partials/partialMethods.jar");
Parameters params = new Parameters();
params.setXsdFiles(xbeanCase("partials/partialMethods.xsd"));
params.setSrcDir(srcdir);
params.setClassesDir(classesdir);
params.setOutputJar(outputjar);
params.setName("Partials");
// exclude each bean method and compare with the template with that method excluded too
for (BeanMethod removeMethod : BeanMethod.values()) {
Set<BeanMethod> partialMethods = new HashSet<>(Arrays.asList(BeanMethod.values()));
partialMethods.remove(removeMethod);
params.setPartialMethods(partialMethods);
SchemaCompiler.compile(params);
for (int i=0; i<files.length; i++) {
Path p = new File(srcdir, files[i]).toPath();
String act = new String(Files.readAllBytes(p), StandardCharsets.UTF_8);
String exp = templ[i];
// remove marker + content
exp = exp.replaceAll("(?m)^.*<" + removeMethod + ">(?s).+?</" + removeMethod + ">$\\n", "");
// activate alternative content
exp = exp.replaceAll("(?m)^.*//.*</?" + removeMethod + "_ELSE>$\\n", "");
// remove other alternative content
exp = exp.replaceAll("(?m)^.*<[^>]+_ELSE>(?s).+?</[^>]+_ELSE>$\\n", "");
// remove unused markers
exp = exp.replaceAll("(?m)^.*//.*<.*>$\\n", "");
assertEquals(files[i] + " - " + removeMethod + " failed", exp, act);
}
}
}
//TESTENV:
private static void dumpErrors(List<XmlError> errors, PrintWriter out) {
// Display the errors
for (XmlError error : errors) {
if (error.getSeverity() == XmlError.SEVERITY_ERROR)
out.println(error.toString());
}
}
private static File xbeanCase(String str) {
return new File(fileLocation, str);
}
private static File xbeanOutput(String str) {
File result = (new File(outputroot, str));
File parentdir = result.getParentFile();
parentdir.mkdirs();
return result;
}
private static void deltree(File dir) {
if (!dir.exists()) {
return;
}
if (dir.isDirectory()) {
String[] list = dir.list();
if (list != null) {
for (String s : list) {
deltree(new File(dir, s));
}
}
}
for (int i = 0; i < 5; i++) {
if (dir.delete()) {
return;
}
try {
System.out.println("Sleep 1s and try do delete it again: " + dir.getCanonicalPath());
Thread.sleep(1000);
} catch (InterruptedException|IOException ignored) {
}
}
throw new IllegalStateException("Could not delete " + dir);
}
}