/** * Initializes the test context with the provided set of properties * * @param input * the input parameters for the test * @param env * the environment parameters for the test execution. */ public static void init(Properties input, Properties env) { CURRENT_CONTEXT.set(new TestExecutionContext(input, env)); }
private static BiConsumer<String, String> defaultConsumer() { return (key, value) -> TestExecutionContext.current() .map(TestExecutionContext::getOutput) .ifPresent(output -> output.setProperty(key, value)); }
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)); } }
/** * Initializes the specified context in the provided classloader, given the classloader is a different one than * of the specified context * @param ctx * the context that should be transferred to the other classloader * @param cl * the classloader whose context should be initialized */ public static void init(final TestExecutionContext ctx, final ClassLoader cl) { //avoid overwriting the context in the same classloader if (!Objects.equals(ctx.getClass().getClassLoader(), cl)) { //NOSONAR runUnchecked(() -> cl.loadClass(ctx.getClass().getName()) .getMethod("init", Properties.class, Properties.class) .invoke(null, ctx.getInput(), ctx.getEnv())); } }
/** * Destroys the context of the context in the provided classloader, given the classloader is a different one than * of the specified context. The output properties from the other classloader are taken over to the given * context * @param ctx * the context to which the output properties of teh other classloader should be transferred * @param cl * the classloader whose context should be destroyed */ public static void destroy(final TestExecutionContext ctx, final ClassLoader cl) { //avoid destroying the context in the same classloader try { Class<?> contextClass = cl.loadClass(ctx.getClass().getName()); if (!Objects.equals(ctx.getClass(), contextClass)) { final Properties props = (Properties) cl.loadClass(ctx.getClass().getName()) .getMethod("destroy") .invoke(null); ctx.getOutput().putAll(props); } } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { throw new UncheckedException("Unable to destroy context", e); } }
/** * Destroys the test context for the current thread. */ public static Properties destroy() { final Properties output = current().map(TestExecutionContext::getOutput) .orElseThrow(() -> new IllegalStateException("Context not initialized")); CURRENT_CONTEXT.remove(); return output; }
public ParameterProvider() { this.provider = key -> Optional.ofNullable(TestExecutionContext.current() .map(TestExecutionContext::getInput) .orElse(System.getProperties()) .getProperty(key)); }