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 */
16package libcore.junit.junit3;
17
18import java.lang.annotation.Annotation;
19import java.lang.reflect.Method;
20import java.util.ArrayList;
21import java.util.List;
22import junit.framework.TestCase;
23import org.junit.Rule;
24import org.junit.rules.MethodRule;
25import org.junit.rules.TestRule;
26import org.junit.runner.Description;
27import org.junit.runners.model.FrameworkMethod;
28import org.junit.runners.model.MultipleFailureException;
29import org.junit.runners.model.Statement;
30import org.junit.runners.model.TestClass;
31
32import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
33
34/**
35 * A {@link TestCase} that supports the @Rule annotation from JUnit 4.
36 *
37 * <p>It supports both {@link TestRule} and {@link MethodRule} based rules when used with the
38 * {@code @Rule} annotation on public fields and methods. The rules encapsulate the
39 * {@link TestCase#runBare()} method and so are run before the {@link TestCase#setUp()} and after
40 * the {@link TestCase#tearDown()} methods.
41 *
42 * <p>Classes that extend this must have a single no argument constructor.
43 */
44public abstract class TestCaseWithRules extends TestCase {
45
46    private final TestClass testClass;
47
48    private final List<Throwable> validationErrors;
49
50    public TestCaseWithRules() {
51        testClass = new TestClass(getClass());
52
53        validationErrors = new ArrayList<>();
54        RULE_VALIDATOR.validate(testClass, validationErrors);
55    }
56
57    @Override
58    public void runBare() throws Throwable {
59        if (!validationErrors.isEmpty()) {
60            throw new MultipleFailureException(validationErrors);
61        }
62
63        Statement statement = new Statement() {
64            @Override
65            public void evaluate() throws Throwable {
66                superRunBare();
67            }
68        };
69
70        final String name = getName();
71        FrameworkMethod frameworkMethod;
72        try {
73            Method method = getClass().getMethod(name, (Class[]) null);
74            frameworkMethod = new FrameworkMethod(method);
75        } catch (NoSuchMethodException e) {
76            frameworkMethod = new FrameworkMethod(null) {
77                @Override
78                public String getName() {
79                    return name;
80                }
81
82                @Override
83                public Annotation[] getAnnotations() {
84                    return new Annotation[0];
85                }
86
87                @Override
88                public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
89                    return null;
90                }
91            };
92        }
93        Description description =
94                Description.createTestDescription(getClass(), frameworkMethod.getName(),
95                        frameworkMethod.getAnnotations());
96
97        List<Object> rules = testClass.getAnnotatedFieldValues(this, Rule.class, Object.class);
98        for (Object rule : rules) {
99            if (rule instanceof TestRule) {
100                statement = ((TestRule) rule).apply(statement, description);
101            } else {
102                statement = ((MethodRule) rule).apply(statement, frameworkMethod, this);
103            }
104        }
105
106        statement.evaluate();
107    }
108
109    private void superRunBare() throws Throwable {
110        super.runBare();
111    }
112}
113