1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project
3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License.
6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at
7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software
11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and
14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License.
15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.testrunner;
18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestCase;
20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.lang.reflect.Method;
22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.ArrayList;
23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.Collections;
24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.List;
25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/**
27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenient class that encapsulates functions for adding test classes
28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
29ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu * @hide
30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class TestCaseCollector {
32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private ClassLoader mClassLoader;
34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private List<TestCase> mTestCases;
35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private TestCaseFilter mFilter;
36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public TestCaseCollector(ClassLoader classLoader, TestCaseFilter filter) {
38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mClassLoader = classLoader;
39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mTestCases = new ArrayList<TestCase>();
40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mFilter = filter;
41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Adds classes to test by providing a list of class names in string
45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * The class name may be in "<class name>#<method name>" format
47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @param classNames class must be subclass of {@link UiAutomatorTestCase}
49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @throws ClassNotFoundException
50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public void addTestClasses(List<String> classNames) throws ClassNotFoundException {
52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        for (String className : classNames) {
53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            addTestClass(className);
54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Adds class to test by providing class name in string.
59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * The class name may be in "<class name>#<method name>" format
61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @param classNames classes must be subclass of {@link UiAutomatorTestCase}
63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @throws ClassNotFoundException
64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public void addTestClass(String className) throws ClassNotFoundException {
66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int hashPos = className.indexOf('#');
67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        String methodName = null;
68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (hashPos != -1) {
69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            methodName = className.substring(hashPos + 1);
70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            className = className.substring(0, hashPos);
71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        addTestClass(className, methodName);
73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Adds class to test by providing class name and method name in separate strings
77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @param className class must be subclass of {@link UiAutomatorTestCase}
79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @param methodName may be null, in which case all "public void testNNN(void)" functions
80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *                   will be added
81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @throws ClassNotFoundException
82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public void addTestClass(String className, String methodName) throws ClassNotFoundException {
84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        Class<?> clazz = mClassLoader.loadClass(className);
85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (methodName != null) {
86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            addSingleTestMethod(clazz, methodName);
87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } else {
88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            Method[] methods = clazz.getMethods();
89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            for (Method method : methods) {
90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (mFilter.accept(method)) {
91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    addSingleTestMethod(clazz, method.getName());
92e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Gets the list of added test cases so far
99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @return
101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public List<TestCase> getTestCases() {
103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return Collections.unmodifiableList(mTestCases);
104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected void addSingleTestMethod(Class<?> clazz, String method) {
107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (!(mFilter.accept(clazz))) {
108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            throw new RuntimeException("Test class must be derived from UiAutomatorTestCase");
109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        try {
111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            TestCase testCase = (TestCase) clazz.newInstance();
112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            testCase.setName(method);
113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestCases.add(testCase);
114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } catch (InstantiationException e) {
115e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            throw new RuntimeException("Could not instantiate test class. Class: "
116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    + clazz.getName());
117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } catch (IllegalAccessException e) {
118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            throw new RuntimeException("Could not access test class. Class: " + clazz.getName());
119e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
120e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
121e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
123e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
124e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Determine if a class and its method should be accepted into test suite
125e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
126e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
127e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public interface TestCaseFilter {
128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
129e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        /**
130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * Determine that based on the method signature, if it can be accepted
131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * @param method
132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         */
133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public boolean accept(Method method);
134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        /**
136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * Determine that based on the class type, if it can be accepted
137e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * @param clazz
138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * @return
139e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         */
140e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public boolean accept(Class<?> clazz);
141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu}
143