1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php 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.ide.eclipse.adt.internal.launch.junit; 17 18 import com.android.SdkConstants; 19 import com.android.annotations.NonNull; 20 import com.android.annotations.Nullable; 21 import com.android.ide.common.xml.ManifestData; 22 import com.android.ide.common.xml.ManifestData.Instrumentation; 23 import com.android.ide.common.xml.ManifestData.UsesLibrary; 24 import com.android.ide.eclipse.adt.AdtConstants; 25 import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; 26 import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; 27 import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 28 29 import org.eclipse.core.resources.IProject; 30 import org.eclipse.core.runtime.CoreException; 31 import org.eclipse.jdt.core.IJavaProject; 32 33 /** 34 * Provides validation for Android instrumentation test runner 35 */ 36 class InstrumentationRunnerValidator { 37 private final IJavaProject mJavaProject; 38 private String[] mInstrumentationNames = null; 39 private boolean mHasRunnerLibrary = false; 40 41 static final String INSTRUMENTATION_OK = null; 42 43 /** 44 * Initializes the InstrumentationRunnerValidator. 45 * 46 * @param javaProject the {@link IJavaProject} for the Android project to validate 47 */ 48 InstrumentationRunnerValidator(IJavaProject javaProject) { 49 mJavaProject = javaProject; 50 ManifestData manifestData = AndroidManifestHelper.parseForData(javaProject.getProject()); 51 init(manifestData); 52 } 53 54 /** 55 * Initializes the InstrumentationRunnerValidator. 56 * 57 * @param project the {@link IProject} for the Android project to validate 58 * @throws CoreException if a fatal error occurred in initialization 59 */ 60 InstrumentationRunnerValidator(IProject project) throws CoreException { 61 this(BaseProjectHelper.getJavaProject(project)); 62 } 63 64 /** 65 * Initializes the InstrumentationRunnerValidator with an existing {@link AndroidManifestHelper} 66 * 67 * @param javaProject the {@link IJavaProject} for the Android project to validate 68 * @param manifestData the {@link ManifestData} for the Android project 69 */ 70 InstrumentationRunnerValidator(IJavaProject javaProject, ManifestData manifestData) { 71 mJavaProject = javaProject; 72 init(manifestData); 73 } 74 75 private void init(ManifestData manifestData) { 76 if (manifestData == null) { 77 mInstrumentationNames = new String[0]; 78 mHasRunnerLibrary = false; 79 return; 80 } 81 82 Instrumentation[] instrumentations = manifestData.getInstrumentations(); 83 mInstrumentationNames = new String[instrumentations.length]; 84 for (int i = 0; i < instrumentations.length; i++) { 85 mInstrumentationNames[i] = instrumentations[i].getName(); 86 } 87 mHasRunnerLibrary = hasTestRunnerLibrary(manifestData); 88 } 89 90 /** 91 * Helper method to determine if given manifest has a <code>SdkConstants.LIBRARY_TEST_RUNNER 92 * </code> library reference 93 * 94 * @param manifestParser the {@link ManifestData} to search 95 * @return true if test runner library found, false otherwise 96 */ 97 private boolean hasTestRunnerLibrary(ManifestData manifestData) { 98 for (UsesLibrary lib : manifestData.getUsesLibraries()) { 99 if (AdtConstants.LIBRARY_TEST_RUNNER.equals(lib.getName())) { 100 return true; 101 } 102 } 103 return false; 104 } 105 106 /** 107 * Return the set of instrumentation names for the Android project. 108 * 109 * @return array of instrumentation class names, possibly empty 110 */ 111 @NonNull 112 String[] getInstrumentationNames() { 113 return mInstrumentationNames; 114 } 115 116 /** 117 * Helper method to get the first instrumentation that can be used as a test runner. 118 * 119 * @return fully qualified instrumentation class name. <code>null</code> if no valid 120 * instrumentation can be found. 121 */ 122 @Nullable 123 String getValidInstrumentationTestRunner() { 124 for (String instrumentation : getInstrumentationNames()) { 125 if (validateInstrumentationRunner(instrumentation) == INSTRUMENTATION_OK) { 126 return instrumentation; 127 } 128 } 129 return null; 130 } 131 132 /** 133 * Helper method to determine if specified instrumentation can be used as a test runner 134 * 135 * @param instrumentation the instrumentation class name to validate. Assumes this 136 * instrumentation is one of {@link #getInstrumentationNames()} 137 * @return <code>INSTRUMENTATION_OK</code> if valid, otherwise returns error message 138 */ 139 String validateInstrumentationRunner(String instrumentation) { 140 if (!mHasRunnerLibrary) { 141 return String.format(LaunchMessages.InstrValidator_NoTestLibMsg_s, 142 AdtConstants.LIBRARY_TEST_RUNNER); 143 } 144 // check if this instrumentation is the standard test runner 145 if (!instrumentation.equals(SdkConstants.CLASS_INSTRUMENTATION_RUNNER)) { 146 // Ideally, we'd check if the class extends instrumentation test runner. 147 // However, the Google Instrumentation Test Runner extends Google Instrumentation, and not a test runner, 148 // so we just check that the super class is Instrumentation. 149 String result = BaseProjectHelper.testClassForManifest(mJavaProject, 150 instrumentation, SdkConstants.CLASS_INSTRUMENTATION, true); 151 if (result != BaseProjectHelper.TEST_CLASS_OK) { 152 return String.format( 153 LaunchMessages.InstrValidator_WrongRunnerTypeMsg_s, 154 SdkConstants.CLASS_INSTRUMENTATION); 155 } 156 } 157 return INSTRUMENTATION_OK; 158 } 159 } 160