aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/InstrumentationRunnerValidator.java
blob: 820fed7d3dc948896cb4feb1b3095b5a4c6f8e35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.ide.eclipse.adt.internal.launch.junit;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.xml.ManifestData;
import com.android.ide.common.xml.ManifestData.Instrumentation;
import com.android.ide.common.xml.ManifestData.UsesLibrary;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.internal.launch.LaunchMessages;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;

/**
 * Provides validation for Android instrumentation test runner
 */
class InstrumentationRunnerValidator {
    private final IJavaProject mJavaProject;
    private String[] mInstrumentationNames = null;
    private boolean mHasRunnerLibrary = false;

    static final String INSTRUMENTATION_OK = null;

    /**
     * Initializes the InstrumentationRunnerValidator.
     *
     * @param javaProject the {@link IJavaProject} for the Android project to validate
     */
    InstrumentationRunnerValidator(IJavaProject javaProject) {
        mJavaProject = javaProject;
        ManifestData manifestData = AndroidManifestHelper.parseForData(javaProject.getProject());
        init(manifestData);
    }

    /**
     * Initializes the InstrumentationRunnerValidator.
     *
     * @param project the {@link IProject} for the Android project to validate
     * @throws CoreException if a fatal error occurred in initialization
     */
    InstrumentationRunnerValidator(IProject project) throws CoreException {
        this(BaseProjectHelper.getJavaProject(project));
    }

    /**
     * Initializes the InstrumentationRunnerValidator with an existing {@link AndroidManifestHelper}
     *
     * @param javaProject the {@link IJavaProject} for the Android project to validate
     * @param manifestData the {@link ManifestData} for the Android project
     */
    InstrumentationRunnerValidator(IJavaProject javaProject, ManifestData manifestData) {
        mJavaProject = javaProject;
        init(manifestData);
    }

    private void init(ManifestData manifestData) {
        if (manifestData == null) {
            mInstrumentationNames = new String[0];
            mHasRunnerLibrary = false;
            return;
        }

        Instrumentation[] instrumentations = manifestData.getInstrumentations();
        mInstrumentationNames = new String[instrumentations.length];
        for (int i = 0; i < instrumentations.length; i++) {
            mInstrumentationNames[i] = instrumentations[i].getName();
        }
        mHasRunnerLibrary = hasTestRunnerLibrary(manifestData);
    }

    /**
     * Helper method to determine if given manifest has a <code>SdkConstants.LIBRARY_TEST_RUNNER
     * </code> library reference
     *
     * @param manifestParser the {@link ManifestData} to search
     * @return true if test runner library found, false otherwise
     */
    private boolean hasTestRunnerLibrary(ManifestData manifestData) {
       for (UsesLibrary lib : manifestData.getUsesLibraries()) {
           if (AdtConstants.LIBRARY_TEST_RUNNER.equals(lib.getName())) {
               return true;
           }
       }
       return false;
    }

    /**
     * Return the set of instrumentation names for the Android project.
     *
     * @return array of instrumentation class names, possibly empty
     */
    @NonNull
    String[] getInstrumentationNames() {
        return mInstrumentationNames;
    }

    /**
     * Helper method to get the first instrumentation that can be used as a test runner.
     *
     * @return fully qualified instrumentation class name. <code>null</code> if no valid
     * instrumentation can be found.
     */
    @Nullable
    String getValidInstrumentationTestRunner() {
        for (String instrumentation : getInstrumentationNames()) {
            if (validateInstrumentationRunner(instrumentation) == INSTRUMENTATION_OK) {
                return instrumentation;
            }
        }
        return null;
    }

    /**
     * Helper method to determine if specified instrumentation can be used as a test runner
     *
     * @param instrumentation the instrumentation class name to validate. Assumes this
     *   instrumentation is one of {@link #getInstrumentationNames()}
     * @return <code>INSTRUMENTATION_OK</code> if valid, otherwise returns error message
     */
    String validateInstrumentationRunner(String instrumentation) {
        if (!mHasRunnerLibrary) {
            return String.format(LaunchMessages.InstrValidator_NoTestLibMsg_s,
                    AdtConstants.LIBRARY_TEST_RUNNER);
        }
        // check if this instrumentation is the standard test runner
        if (!instrumentation.equals(SdkConstants.CLASS_INSTRUMENTATION_RUNNER)) {
            // Ideally, we'd check if the class extends instrumentation test runner.
            // However, the Google Instrumentation Test Runner extends Google Instrumentation, and not a test runner,
            // so we just check that the super class is Instrumentation.
            String result = BaseProjectHelper.testClassForManifest(mJavaProject,
                    instrumentation, SdkConstants.CLASS_INSTRUMENTATION, true);
             if (result != BaseProjectHelper.TEST_CLASS_OK) {
                return String.format(
                        LaunchMessages.InstrValidator_WrongRunnerTypeMsg_s,
                        SdkConstants.CLASS_INSTRUMENTATION);
             }
        }
        return INSTRUMENTATION_OK;
    }
}