• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.test.runner.junit4;
17 
18 import android.app.Instrumentation;
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.util.Log;
22 
23 import com.android.test.InjectBundle;
24 import com.android.test.InjectContext;
25 import com.android.test.InjectInstrumentation;
26 
27 import org.junit.runners.BlockJUnit4ClassRunner;
28 import org.junit.runners.model.FrameworkField;
29 import org.junit.runners.model.InitializationError;
30 
31 import java.lang.reflect.Field;
32 import java.util.List;
33 
34 /**
35  * A specialized {@link BlockJUnit4ClassRunner} that can handle {@link InjectContext} and
36  * {@link InjectInstrumentation}.
37  */
38 class AndroidJUnit4ClassRunner extends BlockJUnit4ClassRunner {
39 
40     private static final String LOG_TAG = "AndroidJUnit4ClassRunner";
41     private final Instrumentation mInstr;
42     private final Bundle mBundle;
43 
44     @SuppressWarnings("serial")
45     private static class InvalidInjectException extends Exception {
InvalidInjectException(String message)46         InvalidInjectException(String message) {
47             super(message);
48         }
49     }
50 
AndroidJUnit4ClassRunner(Class<?> klass, Instrumentation instr, Bundle bundle)51     public AndroidJUnit4ClassRunner(Class<?> klass, Instrumentation instr, Bundle bundle)
52             throws InitializationError {
53         super(klass);
54         mInstr = instr;
55         mBundle = bundle;
56     }
57 
58     @Override
createTest()59     protected Object createTest() throws Exception {
60         Object test = super.createTest();
61         inject(test);
62         return test;
63     }
64 
65     @Override
collectInitializationErrors(List<Throwable> errors)66     protected void collectInitializationErrors(List<Throwable> errors) {
67         super.collectInitializationErrors(errors);
68 
69         validateInjectFields(errors);
70     }
71 
validateInjectFields(List<Throwable> errors)72     private void validateInjectFields(List<Throwable> errors) {
73         List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
74                 InjectInstrumentation.class);
75         for (FrameworkField instrField : instrFields) {
76             validateInjectField(errors, instrField, Instrumentation.class);
77         }
78         List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
79                 InjectContext.class);
80         for (FrameworkField contextField : contextFields) {
81             validateInjectField(errors, contextField, Context.class);
82         }
83         List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
84                 InjectBundle.class);
85         for (FrameworkField bundleField : bundleFields) {
86             validateInjectField(errors, bundleField, Bundle.class);
87         }
88     }
89 
validateInjectField(List<Throwable> errors, FrameworkField instrField, Class<?> expectedType)90     private void validateInjectField(List<Throwable> errors, FrameworkField instrField,
91             Class<?> expectedType) {
92         if (!instrField.isPublic()) {
93             errors.add(new InvalidInjectException(String.format(
94                     "field %s in class %s has an InjectInstrumentation annotation," +
95                     " but is not public", instrField.getName(), getTestClass().getName())));
96         }
97         if (!expectedType.isAssignableFrom(instrField.getType())) {
98             errors.add(new InvalidInjectException(String.format(
99                     "field %s in class %s has an InjectInstrumentation annotation," +
100                     " but its not of %s type", instrField.getName(),
101                     getTestClass().getName(), expectedType.getName())));
102         }
103     }
104 
inject(Object test)105     private void inject(Object test) {
106         List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
107                 InjectInstrumentation.class);
108         for (FrameworkField instrField : instrFields) {
109             setFieldValue(test, instrField.getField(), mInstr);
110         }
111         List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
112                 InjectContext.class);
113         for (FrameworkField contextField : contextFields) {
114             setFieldValue(test, contextField.getField(), mInstr.getTargetContext());
115         }
116         List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
117                 InjectBundle.class);
118         for (FrameworkField bundleField : bundleFields) {
119             setFieldValue(test, bundleField.getField(), mBundle);
120         }
121     }
122 
setFieldValue(Object test, Field field, Object value)123     private void setFieldValue(Object test, Field field, Object value) {
124         try {
125             field.set(test, value);
126         } catch (IllegalArgumentException e) {
127             Log.e(LOG_TAG, String.format(
128                     "Failed to inject value for field %s in class %s", field.getName(),
129                     test.getClass().getName()), e);
130         } catch (IllegalAccessException e) {
131             Log.e(LOG_TAG, String.format(
132                     "Failed to inject value for field %s in class %s", field.getName(),
133                     test.getClass().getName()), e);
134         }
135     }
136 }
137