package org.jacorb.test.harness; /* * JacORB - a free Java ORB * * Copyright (C) 1999-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PrintWriter; import java.io.StringWriter; import java.net.Socket; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.Random; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.regex.Matcher; import java.util.regex.Pattern; import junit.framework.AssertionFailedError; import org.junit.Assert; import org.slf4j.Logger; /** * Utility class used to setup JUnit-TestSuite * * @author Alphonse Bendt */ public class TestUtils { private static Random portRandom = new Random(); /** * The minimum server currentMinPort number for IPv4. */ private static final int MIN_PORT = 1024; /** * The maximum server currentMinPort number for IPv4. */ private static final int MAX_PORT = 65355; public static final boolean isIBM = (System.getProperty ("java.vendor").equals ("IBM Corporation")); public static final boolean is17 = (System.getProperty ("java.version").startsWith ("1.7")); private static String testHome = null; private static String jacorbHome = null; private static String systemRoot = null; private static Logger logger; private static java.util.logging.Logger jdkLogger; private static java.util.logging.Logger apacheLogger; public static final boolean verbose = "true".equalsIgnoreCase(System.getProperty("jacorb.test.verbose")); public static final int timeout = Integer.valueOf(System.getProperty("jacorb.test.timeout.server", "60000")); public static final boolean isSSLEnabled = Boolean.valueOf(System.getProperty("jacorb.test.ssl", "false")); // Ensure logging is initialised static { getLogger(); } /** * Return a preconfigured logger for the test framework. * @return a SLF4J Logger */ public static Logger getLogger () { if (logger == null) { Formatter formatter = new Formatter() { @Override public String format(LogRecord arg0) { StringBuilder b = new StringBuilder(); b.append ("[TEST] "); b.append(arg0.getLevel()); b.append(" "); b.append(arg0.getMessage()); b.append(System.getProperty("line.separator")); Throwable t = arg0.getThrown(); return t == null ? b.toString() : b.toString () + getStackTrace (t); } private String getStackTrace (Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter (sw)); return sw.toString(); } }; Handler handler = new ConsoleHandler(); handler.setFormatter(formatter); handler.setLevel(TestUtils.verbose ? Level.FINER : Level.OFF); apacheLogger = java.util.logging.Logger.getLogger("org.apache.camel.test"); apacheLogger.setUseParentHandlers (false); apacheLogger.setLevel (TestUtils.verbose ? Level.FINER : Level.OFF); apacheLogger.addHandler(handler); jdkLogger = java.util.logging.Logger.getLogger("org.jacorb.test"); jdkLogger.setUseParentHandlers (false); jdkLogger.setLevel (TestUtils.verbose ? Level.FINER : Level.OFF); jdkLogger.addHandler(handler); logger = org.slf4j.LoggerFactory.getLogger ("org.jacorb.test"); } return logger; } public static String jacorbHome() { if (jacorbHome == null) { jacorbHome = osDependentPath((testHome() + "/../../")); } return jacorbHome; } /** * Returns the name of the home directory of this regression suite. */ public static String testHome() { if (testHome == null) { // See if we set it as a property using TestLauncher testHome = System.getProperty ("jacorb.test.home"); // Try to find it from the run directory if (testHome == null) { URL url = TestUtils.class.getResource("/."); String result = url.toString(); if (result.matches("file:/.*?")) { result = result.substring (5, result.indexOf("/target/test-classes/")); } testHome = osDependentPath(result); } } if (testHome == null) { throw new RuntimeException("unable to determine testhome (set it with -Djacorb.test.home)"); } return testHome; } public static String osDependentPath(String path) { path=(new File(path)).toString(); return path.trim(); } /** * In addition to file and path separators being different, * Windows requires an additional environment variable for * SystemRoot in DirectLauncer. */ public static boolean isWindows() { return (System.getProperty("os.name").indexOf("Windows") != -1) ; } /** * Returns the SystemRoot, should be used on Windows only. This * is necessary to prevent the following error: * "Unrecognised Windows Sockets error: 10106: create" */ public static String systemRoot() throws RuntimeException, java.io.IOException { if (isWindows()) { if (systemRoot == null) { //See if we set it as a property using TestLauncher. //This means we are likely in the DirectLauncher systemRoot = System.getProperty ("jacorb.SystemRoot"); if (systemRoot == null) { //We are likely in the TestLauncher, see if we can //get it from the system environment. Properties env = new Properties(); try { String setCmd = getSetCommand(); Process proc = Runtime.getRuntime().exec(setCmd); InputStream ioStream = proc.getInputStream(); env.load(ioStream); systemRoot = env.getProperty("SystemRoot"); ioStream.close(); proc.destroy(); } catch(java.io.IOException e) { throw e; } if (systemRoot == null) { throw new RuntimeException("Could not find SystemRoot, make sure SystemRoot env var is set"); } //The '\' character gets interpeted as an escape if (systemRoot.charAt(1) == ':' && systemRoot.charAt(2) != '\\') { String prefix = systemRoot.substring(0, 2); String suffix = systemRoot.substring(2, systemRoot.length()); systemRoot = prefix + "\\" + suffix; } } } } else { throw new RuntimeException("TestUtils.systemRoot() was called on a non-Windows OS"); } return systemRoot; } /** * Private method to get the set command. This is necessary because * if SystemRoot has not been set, it needs to be set for DirectLauncer. */ private static String getSetCommand() { String setCmd; String osName = System.getProperty("os.name"); if (osName.indexOf("indows") != -1) { if (osName.indexOf("indows 9") != -1) { setCmd = "command.com /c set"; } else { setCmd = "cmd.exe /c set"; } } else { setCmd = "/usr/bin/env"; //should double check for all unix platforms } return setCmd; } /** * create properties that contain the correct (JDK specific) * settings to create a Sun or IBM ORB. */ public static Properties newForeignORBProperties() { final Properties props = new Properties(); if (TestUtils.isIBM) { props.setProperty ("org.omg.CORBA.ORBClass", "com.ibm.CORBA.iiop.ORB"); props.setProperty ("org.omg.CORBA.ORBSingletonClass", "com.ibm.rmi.corba.ORBSingleton"); } else { props.setProperty("org.omg.CORBA.ORBClass", "com.sun.corba.se.impl.orb.ORBImpl"); props.setProperty("org.omg.CORBA.ORBSingletonClass", "com.sun.corba.se.impl.orb.ORBSingleton"); } return props; } public static boolean getStringAsBoolean(String value) { return "true".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value); } public static void deleteRecursively(File name) { if (name.isDirectory()) { File[] subdirs = name.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory(); } }); for (int i = 0; i < subdirs.length; ++i) { deleteRecursively(subdirs[i]); } File[] files = name.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isFile(); } }); for (int i = 0; i < files.length; ++i) { files[i].delete(); } name.delete(); } if (name.isFile()) { name.delete(); } } public static File createTempDir(final String name) { String dir = System.getProperty("java.io.tmpdir"); dir += File.separator + name + "-" + System.currentTimeMillis(); final File tmpDir = new File(dir); Assert.assertTrue(tmpDir.mkdir()); tmpDir.deleteOnExit(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { TestUtils.deleteRecursively(tmpDir); }; }); return tmpDir; } private static File[] getSubDirectories(File src) { return src.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory(); } }); } private static List<File> getFilesInDirectory(File src, final String suffix) { final File[] fileList = src.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(suffix); } }); Assert.assertNotNull(src + " does not exist.", fileList); return Arrays.asList(fileList); } public static List<File> getJavaFilesRecursively(File src) { final String suffix = ".java"; return getFilesRecursively(src, suffix); } public static List<File> getFilesRecursively(File src, final String suffix) { List<File> result = new ArrayList<File>(); result.addAll(getFilesInDirectory(src, suffix)); File[] dirs = getSubDirectories(src); for (int i = 0; i < dirs.length; ++i) { result.addAll(getFilesRecursively(dirs[i], suffix)); } return result; } public static ClassLoader compileJavaFiles(File dirCompilation, File[] files, boolean failureExpected) throws IOException { Assert.assertNotNull(files); if (files.length == 0) { return null; } dirCompilation.mkdir(); Assert.assertTrue(dirCompilation.isDirectory()); Assert.assertTrue(dirCompilation.exists()); Assert.assertTrue(dirCompilation.canWrite()); File file = new File(dirCompilation, "files.txt"); file.delete(); file.createNewFile(); PrintWriter writer = new PrintWriter(new FileWriter(file)); for (int i = 0; i < files.length; ++i) { writer.println(files[i].getAbsolutePath()); } writer.close(); String javaHome = System.getProperty("java.home"); String testHome = testHome(); String classpath = testHome + File.separator + ".." + File.separator + ".." + File.separator + "classes"; if (javaHome.endsWith("jre")) { javaHome = javaHome.substring(0, javaHome.length() - 4); } String cmd = javaHome + "/bin/javac -d " + dirCompilation + " -bootclasspath " + classpath + ":" + System.getProperty("sun.boot.class.path") + " @" + file.getAbsolutePath(); TestUtils.getLogger().debug("[COMPILE] " + cmd); TestUtils.getLogger().debug("[COMPILE] " + files.length + " java files"); try { Process proc = Runtime.getRuntime().exec(cmd); int exit = proc.waitFor(); if (failureExpected && exit == 0) { Assert.fail("should fail: " + cmd); } if (exit != 0) { InputStream in = proc.getErrorStream(); LineNumberReader reader = new LineNumberReader(new InputStreamReader(in)); StringBuffer b = new StringBuffer(); String line; while ((line = reader.readLine()) != null) { b.append(line); b.append("\n"); } Assert.fail(cmd + "\n" + b.toString()); } return new URLClassLoader(new URL[] {dirCompilation.toURI().toURL()}); } catch (Exception e) { if (!failureExpected) { AssertionFailedError error = new AssertionFailedError("cmd: " + cmd); error.initCause(e); throw error; } return null; } } public static long getSystemPropertyAsLong(final String property, final long defaultValue) { long parseLong; try { parseLong = Long.parseLong(System.getProperty(property)); } catch (Exception e) { parseLong = defaultValue; } return parseLong; } public static boolean getSystemPropertyAsBoolean(final String property, final boolean defaultValue) { String value = System.getProperty (property); if (value == null) { return defaultValue; } return getStringAsBoolean(value); } public static long getMediumTimeout() { return Long.getLong("jacorb.test.timeout.medium", 20000).longValue(); } /** * wait until a server IOR shows up (file size > 0) and print it out * to stdout so it can be picked up by a client process. */ public static void printServerIOR(File iorFile) throws InterruptedException, FileNotFoundException, IOException { long maxWait = System.currentTimeMillis() + timeout; while(iorFile.length() == 0 && System.currentTimeMillis() < maxWait) { Thread.sleep(1000); } Thread.sleep(1000); BufferedReader in = new BufferedReader(new FileReader(iorFile)); String ior = in.readLine(); in.close(); if (ior == null) { throw new IllegalArgumentException("cannot read IOR from file " + iorFile + " within " + TestUtils.timeout); } System.out.println("SERVER IOR: " + ior); } /** * copied here from ObjectUtil to make the package org.jacorb.test.harness independent from the orb core */ public static Class<?> classForName(String name) throws ClassNotFoundException, IllegalArgumentException { if (name == null) { throw new IllegalArgumentException("Class name must not be null!"); } try { // Here we prefer classLoader.loadClass() over the three-argument // form of Class.forName(), as the latter is reported to cause // caching of stale Class instances (due to a buggy cache of // loaded classes). return Thread.currentThread().getContextClassLoader().loadClass(name); } catch (Exception e) { // As a fallback, we prefer Class.forName(name) because it loads // array classes (i.e., it handles arguments like // "[Lsome.class.Name;" or "[[I;", which classLoader.loadClass() // does not handle). return Class.forName(name); } } public static int patternMatcher(Pattern pattern, String text) { Matcher matcher = pattern.matcher(text); if (matcher.find()) { return matcher.end(); } return 0; } /** * Locate an available port. * * https://stackoverflow.com/questions/434718/sockets-discover-port-availability-using-java * https://stackoverflow.com/questions/2675362/how-to-find-an-available-port * </br> * Only meant to be used by those tests that inherit from {@link FixedPortORBTestCase} or * {@link FixedPortClientServerTestCase} */ static int getNextAvailablePort() { int result = MIN_PORT, port = 0, counter = 0; // Only try so many times to find a usable port. while ( counter < ( MAX_PORT - MIN_PORT ) ) { // Attempt to find a usable port randomly. port = randInt (MIN_PORT, MAX_PORT); if ( available ( port )) { result = port; break; } counter++; } getLogger().debug("Returning port " + port); return result; } /** * Returns a pseudo-random number between min and max, inclusive. * The difference between min and max can be at most * <code>Integer.MAX_VALUE - 1</code>. * * @param min Minimum value * @param max Maximum value. Must be greater than min. * @return Integer between min and max, inclusive. * @see java.util.Random#nextInt(int) */ private static int randInt(int min, int max) { // nextInt is normally exclusive of the top value, // so add 1 to make it inclusive int randomNum = portRandom.nextInt((max - min) + 1) + min; return randomNum; } /** * Attempt to determine if a socket is in use. * * @param port * @return */ private static boolean available(int port) { Socket s = null; try { s = new Socket("localhost", port); s.setReuseAddress(true); // If the code makes it this far without an exception it means // something is using the port and has responded. getLogger().debug("Port " + port + " is not available"); return false; } catch (IOException e) { getLogger().debug("Port " + port + " is available"); return true; } finally { if (s != null) { try { s.close(); } catch (IOException e) { throw new RuntimeException("Failed to close the socket", e); } } } } }