blob: 29a72437406e6a7769bdd746c364200f12520246 [file] [log] [blame]
package org.robolectric;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.annotation.Nonnull;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.robolectric.annotation.Config;
import org.robolectric.internal.ParallelUniverseInterface;
import org.robolectric.internal.SdkEnvironment;
import org.robolectric.internal.bytecode.InstrumentationConfiguration;
import org.robolectric.internal.bytecode.InstrumentationConfiguration.Builder;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.pluginapi.Sdk;
/**
* Test runner which prevents full initialization (bootstrap) of the Android process at test setup.
*/
public class BootstrapDeferringRobolectricTestRunner extends RobolectricTestRunner {
private static BootstrapWrapper bootstrapWrapper;
public BootstrapDeferringRobolectricTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Nonnull
@Override
protected Class<? extends TestLifecycle> getTestLifecycleClass() {
return MyTestLifecycle.class;
}
@Override
ParallelUniverseInterface getHooksInterface(SdkEnvironment sdkEnvironment) {
bootstrapWrapper = new BootstrapWrapper(super.getHooksInterface(sdkEnvironment));
return bootstrapWrapper;
}
@Nonnull
@Override
protected InstrumentationConfiguration createClassLoaderConfig(FrameworkMethod method) {
return new Builder(super.createClassLoaderConfig(method))
.doNotAcquireClass(BootstrapDeferringRobolectricTestRunner.class)
.doNotAcquireClass(RoboInject.class)
.doNotAcquireClass(MyTestLifecycle.class)
.doNotAcquireClass(BootstrapWrapper.class)
.build();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface RoboInject {
}
public static class MyTestLifecycle extends DefaultTestLifecycle {
@Override
public void prepareTest(Object test) {
super.prepareTest(test);
for (Field field : test.getClass().getDeclaredFields()) {
if (field.getAnnotation(RoboInject.class) != null) {
if (field.getType().isAssignableFrom(BootstrapWrapper.class)) {
field.setAccessible(true);
try {
field.set(test, bootstrapWrapper);
} catch (IllegalAccessException e) {
throw new RuntimeException("can't set " + field, e);
}
}
}
}
}
}
public static class BootstrapWrapper implements ParallelUniverseInterface {
public ParallelUniverseInterface hooksInterface;
public boolean legacyResources;
public ApkLoader apkLoader;
public Method method;
public Config config;
public AndroidManifest appManifest;
public SdkEnvironment sdkEnvironment;
public BootstrapWrapper(ParallelUniverseInterface hooksInterface) {
this.hooksInterface = hooksInterface;
}
@Override
public void setSdk(Sdk sdk) {
hooksInterface.setSdk(sdk);
}
@Override
public void setResourcesMode(boolean legacyResources) {
hooksInterface.setResourcesMode(legacyResources);
this.legacyResources = legacyResources;
}
@Override
public void setUpApplicationState(ApkLoader apkLoader, Method method, Config config,
AndroidManifest appManifest, SdkEnvironment sdkEnvironment) {
this.apkLoader = apkLoader;
this.method = method;
this.config = config;
this.appManifest = appManifest;
this.sdkEnvironment = sdkEnvironment;
}
@Override
public Thread getMainThread() {
return hooksInterface.getMainThread();
}
@Override
public void setMainThread(Thread newMainThread) {
hooksInterface.setMainThread(newMainThread);
}
@Override
public void tearDownApplication() {
hooksInterface.tearDownApplication();
}
@Override
public Object getCurrentApplication() {
return hooksInterface.getCurrentApplication();
}
public void callSetUpApplicationState() {
hooksInterface.setUpApplicationState(apkLoader, method, config, appManifest, sdkEnvironment);
}
}
}