/** * Serializes the result into a binary representation. To ensure it can be deserialized without the test classes, * all references to test files are removed by transfering to Java basic classes. * * @param result * the result to be serialized * * @return a serialized representation of the result * * @throws Exception * if the result can not be deserialized */ public byte[] serialize(Result result) throws Exception { final ByteArrayOutputStream os = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(copy(result)); return os.toByteArray(); }
private Result copy(Result old) throws Exception { final Result result = new Result(); copyFields(old, result); copyFailures(old, result); return result; }
private void copyFields(final Result old, final Result result) throws NoSuchFieldException, IllegalAccessException { final AtomicInteger count = getAccessibleResultField(result, "count"); count.set(old.getRunCount()); final AtomicInteger ignoreCount = getAccessibleResultField(result, "ignoreCount"); ignoreCount.set(old.getIgnoreCount()); final AtomicLong runTime = getAccessibleResultField(result, "runTime"); runTime.set(old.getRunTime()); final AtomicLong startTime = getAccessibleResultField(result, "startTime"); startTime.set(((AtomicLong) getAccessibleResultField(old, "startTime")).get()); }
private void copyFailures(final Result old, final Result result) throws NoSuchFieldException, IllegalAccessException { final CopyOnWriteArrayList<Failure> failures = getAccessibleResultField(result, "failures"); old.getFailures().stream().map(of -> { final Throwable nt = copyThrowable(of.getException()); final Description nd = copyDescription(of.getDescription()); return new Failure(nd, nt); }).collect(Collectors.toCollection(() -> failures)); }
private static Result invokeRun(final String className, final ClassLoader cl) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IOException, InvocationTargetException { TestExecutionContext.current().ifPresent(ctx -> { System.getProperties().putAll(ctx.getEnv()); init(ctx, cl); }); try { final Class<?> testClass = cl.loadClass(className); final Object runner = cl.loadClass(JUnitRunner.class.getName()).newInstance(); final Method run = runner.getClass().getDeclaredMethod("run", Class.class); return new ResultHelper().deserialize((byte[]) run.invoke(runner, testClass)); } finally { TestExecutionContext.current().ifPresent(ctx -> destroy(ctx, cl)); } }
/** * Executes the test using the current classloader that created the instance of the JUnit Runner. The result is * serialized to transfer the result across classloader boundaries. * * @param testClass * the class to be executed * * @return a binary representation of the {@link org.junit.runner.Result} * * @throws Exception * if the test execution or result serialization failed. */ public byte[] run(Class<?> testClass) throws Exception { final Computer computer = new Computer(); final JUnitCore core = new JUnitCore(); return new ResultHelper().serialize(core.run(computer, testClass)); }