/* * Capsule * Copyright (c) 2014-2015, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are licensed under the terms * of the Eclipse Public License v1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package co.paralleluniverse.capsule.test; import co.paralleluniverse.capsule.Jar; import co.paralleluniverse.common.Exceptions; import co.paralleluniverse.common.JarClassLoader; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringReader; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.nio.file.Path; import java.util.Properties; /** * * @author pron */ public final class CapsuleTestUtils { private static final Class<?> capsuleClass; static { try { capsuleClass = Class.forName("Capsule"); accessible(capsuleClass.getDeclaredField("PROFILE")).set(null, 10); // disable profiling even when log=debug } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } public static Object newCapsule(Jar jar, Path path) { try { jar.write(path); //accessible(capsuleClass.getDeclaredField("MY_JAR")).set(null, path); final String mainClass = jar.getAttribute("Main-Class"); final Class<?> clazz = Class.forName(mainClass); return newCapsule(clazz, path); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } catch (Exception e) { throw rethrow(e); } } public static Class<?> loadCapsule(Jar jar, Path path) { try { jar.write(path); final String mainClass = jar.getAttribute("Main-Class"); final Class<?> clazz = new JarClassLoader(path, true).loadClass(mainClass); return clazz; } catch (Exception e) { throw new AssertionError(e); } } public static Object newCapsule(Class<?> clazz, Path path) { try { Constructor<?> ctor = accessible(clazz.getDeclaredConstructor(Path.class)); return ctor.newInstance(path); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } catch (Exception e) { throw new AssertionError(e); } } public static void setCacheDir(Class<?> capsuleClass, Path cache) { try { accessible(actualCapsuleClass(capsuleClass).getDeclaredField("CACHE_DIR")).set(null, cache); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } public static void setProperties(Class<?> capsuleClass, Properties props) { try { accessible(actualCapsuleClass(capsuleClass).getDeclaredField("PROPERTIES")).set(null, props); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } public static void resetOutputStreams(Class<?> capsuleClass) { setSTDOUT(capsuleClass, System.out); setSTDERR(capsuleClass, System.err); } public static <T extends PrintStream> T setSTDOUT(Class<?> capsuleClass, T ps) { setStream(capsuleClass, "STDOUT", ps); return ps; } public static <T extends PrintStream> T setSTDERR(Class<?> capsuleClass, T ps) { setStream(capsuleClass, "STDERR", ps); return ps; } public static void setStream(Class<?> capsuleClass, String stream, PrintStream ps) { try { accessible(actualCapsuleClass(capsuleClass).getDeclaredField(stream)).set(null, ps); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } public static void setCacheDir(Path cache) { setCacheDir(capsuleClass, cache); } public static void setProperties(Properties props) { setProperties(capsuleClass, props); } public static void resetOutputStreams() { resetOutputStreams(capsuleClass); } public static <T extends PrintStream> T setSTDOUT(T ps) { return setSTDOUT(capsuleClass, ps); } public static <T extends PrintStream> T setSTDERR(T ps) { return setSTDERR(capsuleClass, ps); } public static void setStream(String stream, PrintStream ps) { setStream(capsuleClass, stream, ps); } public static <T extends AccessibleObject> T accessible(T x) { if (!x.isAccessible()) x.setAccessible(true); if (x instanceof Field) { Field field = (Field) x; if ((field.getModifiers() & Modifier.FINAL) != 0) { try { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } } return x; } public static Class<?> actualCapsuleClass(Class<?> clazz) { for (Class<?> c = clazz; c != null; c = c.getSuperclass()) { if (c.getName().equals("Capsule")) return c; } throw new AssertionError("Class " + clazz.getName() + " is not a capsule class"); } public static boolean isCI() { return (isEnvTrue("CI") || isEnvTrue("CONTINUOUS_INTEGRATION") || isEnvTrue("TRAVIS")); } private static boolean isEnvTrue(String envVar) { final String ev = System.getenv(envVar); if (ev == null) return false; try { return Boolean.parseBoolean(ev); } catch (Exception e) { return false; } } public static RuntimeException rethrow(Throwable t) { return Exceptions.rethrow(t); } public static final PrintStream DEVNULL = new PrintStream(new OutputStream() { @Override public void write(int b) { } // OPTIONAL (overriding the above method is enough) @Override public void write(byte[] b, int off, int len) { } @Override public void write(byte[] b) throws IOException { } }); public static class StringPrintStream extends PrintStream { private final ByteArrayOutputStream baos; public StringPrintStream() { super(new ByteArrayOutputStream()); this.baos = (ByteArrayOutputStream) out; } @Override public String toString() { close(); return baos.toString(); } public BufferedReader toReader() { return new BufferedReader(new StringReader(toString())); } } private CapsuleTestUtils() { } }