package jmri.configurexml; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.OverridingMethodsMustInvokeSuper; import jmri.jmrit.XmlFile; import jmri.util.JUnitUtil; import org.jdom2.JDOMException; import org.junit.jupiter.api.*; import org.junit.jupiter.params.provider.Arguments; /** * Base for XML schema testing * * @author Bob Jacobsen Copyright 2009, 2014 * @since 3.9.2 */ public class SchemaTestBase { private XmlFile.Validate validate; /** * Configure for handling I/O checks: * * @param path the path to this directory * @return the stream of files to process */ protected static Stream setTestFilesBelowThisPath(String path) { ArrayList files = new ArrayList<>(); // the following are just tested for schema pass/fail, not load/store files.addAll(getFiles(new File(path+"/valid"), true, true).collect(Collectors.toList())); files.addAll(getFiles(new File(path+"/invalid"), true, false).collect(Collectors.toList())); // also tested for load/store files.addAll(getFiles(new File(path+"/load"), true, true).collect(Collectors.toList())); assertFalse( files.isEmpty(), "There should be something here; misconfigured?"); return files.stream(); } public void validate(File file, boolean pass) { assumeFalse( Boolean.getBoolean("jmri.skipschematests"), "Ignoring schema validation."); XmlFile.setDefaultValidate(XmlFile.Validate.CheckDtdThenSchema); XmlFile xf = new XmlFileImpl(); try { xf.rootFromFile(file); if (!pass) { fail( () -> "Validation of \"" + file.getPath() + "\" should have failed"); } } catch (IOException | JDOMException ex) { // throw unexpected errors if (pass) { fail("Failed to validate \"" + file.getPath() + "\" due to: " + ex, ex); } } } /** * Get all XML files in a directory and validate them. * * @param directory the directory containing XML files * @param recurse if true, will recurse into subdirectories * @param pass if true, successful validation will pass; if false, * successful validation will fail * @return a stream of {@link Arguments}, where each Argument contains the * {@link java.io.File} with a filename ending in {@literal .xml} to * validate and a boolean matching the pass parameter */ public static Stream getFiles(File directory, boolean recurse, boolean pass) { ArrayList files = new ArrayList<>(); if (directory.isDirectory()) { for (File file : directory.listFiles()) { if (file.isDirectory()) { if (recurse) { files.addAll(getFiles(file, recurse, pass).collect(Collectors.toList())); } } else { files.addAll(getFiles(file, recurse, pass).collect(Collectors.toList())); } } } else if (directory.getName().endsWith(".xml")) { files.add(Arguments.of(directory, pass)); } return files.stream(); } /** * Get all XML files in the immediate subdirectories of a directory and * validate them. * * @param directory the directory containing subdirectories containing XML * files * @param recurse if true, will recurse into subdirectories * @param pass if true, successful validation will pass; if false, * successful validation will fail * @return a stream of {@link Arguments}, where each Argument contains the * {@link java.io.File} with a filename ending in {@literal .xml} to * validate and a boolean matching the pass parameter * @throws IllegalArgumentException if directory is a file */ public static Stream getDirectories(File directory, boolean recurse, boolean pass) throws IllegalArgumentException { ArrayList files = new ArrayList<>(); if (directory.isDirectory()) { for (File file : directory.listFiles()) { if (file.isDirectory()) { files.addAll(getFiles(file, recurse, pass).collect(Collectors.toList())); } } } else { throw new IllegalArgumentException("directory must be a directory, not a file"); } return files.stream(); } @BeforeEach @OverridingMethodsMustInvokeSuper public void setUp() { JUnitUtil.setUp(); JUnitUtil.resetProfileManager(); this.validate = XmlFile.getDefaultValidate(); } @AfterEach @OverridingMethodsMustInvokeSuper public void tearDown() { XmlFile.setDefaultValidate(this.validate); JUnitUtil.deregisterBlockManagerShutdownTask(); JUnitUtil.tearDown(); } private static class XmlFileImpl extends XmlFile { // empty implementation of abstract class } }