blob: 92bac8a831a31d09f5414b6d58483cd330a35f1c [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.test.runner.junit4;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.android.test.InjectBundle;
import com.android.test.InjectContext;
import com.android.test.InjectInstrumentation;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.InitializationError;
import java.lang.reflect.Field;
import java.util.List;
/**
* A specialized {@link BlockJUnit4ClassRunner} that can handle {@link InjectContext} and
* {@link InjectInstrumentation}.
*/
class AndroidJUnit4ClassRunner extends BlockJUnit4ClassRunner {
private static final String LOG_TAG = "AndroidJUnit4ClassRunner";
private final Instrumentation mInstr;
private final Bundle mBundle;
@SuppressWarnings("serial")
private static class InvalidInjectException extends Exception {
InvalidInjectException(String message) {
super(message);
}
}
public AndroidJUnit4ClassRunner(Class<?> klass, Instrumentation instr, Bundle bundle)
throws InitializationError {
super(klass);
mInstr = instr;
mBundle = bundle;
}
@Override
protected Object createTest() throws Exception {
Object test = super.createTest();
inject(test);
return test;
}
@Override
protected void collectInitializationErrors(List<Throwable> errors) {
super.collectInitializationErrors(errors);
validateInjectFields(errors);
}
private void validateInjectFields(List<Throwable> errors) {
List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
InjectInstrumentation.class);
for (FrameworkField instrField : instrFields) {
validateInjectField(errors, instrField, Instrumentation.class);
}
List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
InjectContext.class);
for (FrameworkField contextField : contextFields) {
validateInjectField(errors, contextField, Context.class);
}
List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
InjectBundle.class);
for (FrameworkField bundleField : bundleFields) {
validateInjectField(errors, bundleField, Bundle.class);
}
}
private void validateInjectField(List<Throwable> errors, FrameworkField instrField,
Class<?> expectedType) {
if (!instrField.isPublic()) {
errors.add(new InvalidInjectException(String.format(
"field %s in class %s has an InjectInstrumentation annotation," +
" but is not public", instrField.getName(), getTestClass().getName())));
}
if (!expectedType.isAssignableFrom(instrField.getType())) {
errors.add(new InvalidInjectException(String.format(
"field %s in class %s has an InjectInstrumentation annotation," +
" but its not of %s type", instrField.getName(),
getTestClass().getName(), expectedType.getName())));
}
}
private void inject(Object test) {
List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
InjectInstrumentation.class);
for (FrameworkField instrField : instrFields) {
setFieldValue(test, instrField.getField(), mInstr);
}
List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
InjectContext.class);
for (FrameworkField contextField : contextFields) {
setFieldValue(test, contextField.getField(), mInstr.getTargetContext());
}
List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
InjectBundle.class);
for (FrameworkField bundleField : bundleFields) {
setFieldValue(test, bundleField.getField(), mBundle);
}
}
private void setFieldValue(Object test, Field field, Object value) {
try {
field.set(test, value);
} catch (IllegalArgumentException e) {
Log.e(LOG_TAG, String.format(
"Failed to inject value for field %s in class %s", field.getName(),
test.getClass().getName()), e);
} catch (IllegalAccessException e) {
Log.e(LOG_TAG, String.format(
"Failed to inject value for field %s in class %s", field.getName(),
test.getClass().getName()), e);
}
}
}