• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 
17 package vogar.target.junit;
18 
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26 import junit.framework.AssertionFailedError;
27 import org.junit.runners.BlockJUnit4ClassRunner;
28 import org.junit.runners.model.FrameworkMethod;
29 import org.junit.runners.model.InitializationError;
30 import org.junit.runners.model.RunnerBuilder;
31 
32 /**
33  * A specialization of {@link BlockJUnit4ClassRunner} to implement behavior required by Vogar.
34  *
35  * <ol>
36  * <li>Defers validation of test methods,
37  * see {@link ValidateTestMethodWhenRunBlockJUnit4ClassRunner}.</li>
38  * <li>Applies global rules, see {@link ApplyGlobalRulesBlockJUnit4ClassRunner}</li>
39  * <li>Selects either explicitly requested methods, or all methods.</li>
40  * </ol>
41  */
42 public class VogarBlockJUnit4ClassRunner
43         extends ValidateTestMethodWhenRunBlockJUnit4ClassRunner {
44 
45     private final RunnerParams runnerParams;
46 
47     /**
48      * Used by annotation runner.
49      */
50     @SuppressWarnings("unused")
VogarBlockJUnit4ClassRunner(Class<?> klass, RunnerBuilder suiteBuilder)51     public VogarBlockJUnit4ClassRunner(Class<?> klass, RunnerBuilder suiteBuilder)
52             throws InitializationError {
53         this(klass, ((VogarRunnerBuilder) suiteBuilder).getRunnerParams());
54     }
55 
VogarBlockJUnit4ClassRunner(Class<?> klass, RunnerParams runnerParams)56     public VogarBlockJUnit4ClassRunner(Class<?> klass, RunnerParams runnerParams)
57             throws InitializationError {
58         super(klass, runnerParams.getTestRule());
59         this.runnerParams = runnerParams;
60     }
61 
62     @Override
getChildren()63     protected List<FrameworkMethod> getChildren() {
64         // Overridden to handle requested methods.
65         Set<String> requestedMethodNames = JUnitUtils.mergeQualificationAndArgs(
66                 runnerParams.getQualification(), runnerParams.getArgs());
67         List<FrameworkMethod> methods = super.getChildren();
68 
69         // If specific methods have been requested then select them from all the methods that were
70         // found. If they cannot be found then add a fake one that will report the method as
71         // missing.
72         if (!requestedMethodNames.isEmpty()) {
73             // Store all the methods in a map by name. That should be safe as test methods do not
74             // have parameters so there can only be one method in a class with each name.
75             Map<String, FrameworkMethod> map = new HashMap<>();
76             for (FrameworkMethod method : methods) {
77                 map.put(method.getName(), method);
78             }
79 
80             methods = new ArrayList<>();
81             for (final String name : requestedMethodNames) {
82                 FrameworkMethod method = map.get(name);
83                 if (method == null) {
84                     // The method could not be found so add one that when invoked will report the
85                     // method as missing.
86                     methods.add(new MissingFrameworkMethod(name));
87                 } else {
88                     methods.add(method);
89                 }
90             }
91         }
92         return methods;
93     }
94 
95     /**
96      * A {@link FrameworkMethod} that is used when a specific method has been requested but no
97      * suitable {@link Method} exists.
98      *
99      * <p>It overrides a number of methods that are called during normal processing in order to
100      * avoid throwing a NPE. It also overrides {@link #validatePublicVoidNoArg(boolean, List)} to
101      * report the method as being missing. It relies on a {@link ValidateMethodStatement} to call
102      * that method immediately prior to invoking the method.
103      */
104     private static class MissingFrameworkMethod extends FrameworkMethod {
105         private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
106         private static final Method DUMMY_METHOD;
107         static {
108             DUMMY_METHOD = Object.class.getMethods()[0];
109         }
110         private final String name;
111 
MissingFrameworkMethod(String name)112         public MissingFrameworkMethod(String name) {
113             super(DUMMY_METHOD);
114             this.name = name;
115         }
116 
117         @Override
getName()118         public String getName() {
119             // Overridden to avoid NPE.
120             return name;
121         }
122 
123         @Override
validatePublicVoidNoArg(boolean isStatic, List<Throwable> errors)124         public void validatePublicVoidNoArg(boolean isStatic, List<Throwable> errors) {
125             // Overridden to report the method as missing.
126             errors.add(new AssertionFailedError("Method \"" + name + "\" not found"));
127         }
128 
129         @Override
getAnnotations()130         public Annotation[] getAnnotations() {
131             // Overridden to avoid NPE.
132             return NO_ANNOTATIONS;
133         }
134 
135         @Override
getAnnotation(Class<T> annotationType)136         public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
137             // Overridden to avoid NPE.
138             return null;
139         }
140     }
141 }
142