From a451f67177ef987a1c23313537697b4e249cf9b8 Mon Sep 17 00:00:00 2001 From: Brett Chabot <> Date: Tue, 24 Mar 2009 20:54:44 -0700 Subject: [PATCH] Automated import from //branches/master/...@141783,141783 --- .../junit/AndroidJUnitLaunchConfigDelegate.java | 138 +++++++------------- .../junit/AndroidJUnitLaunchConfigurationTab.java | 42 +++--- .../launch/junit/AndroidJUnitLaunchShortcut.java | 39 ++---- .../junit/InstrumentationRunnerValidator.java | 145 +++++++++++++++++++++ 4 files changed, 225 insertions(+), 139 deletions(-) create mode 100644 eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java index a624b0001..fa8e4b01a 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java @@ -32,23 +32,21 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry; /** - * Run configuration that can execute JUnit tests on an Android platform + * Run configuration that can execute JUnit tests on an Android platform. *
- * Will deploy apps on target Android platform by reusing functionality from ADT - * LaunchConfigDelegate, and then run JUnits tests by reusing functionality from JDT + * Will deploy apps on target Android platform by reusing functionality from ADT + * LaunchConfigDelegate, and then run JUnits tests by reusing functionality from JDT * JUnitLaunchConfigDelegate. */ -@SuppressWarnings("restriction") //$NON-NLS-1$ +@SuppressWarnings("restriction") public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate { - /** Launch config attribute that stores instrumentation runner */ + /** Launch config attribute that stores instrumentation runner. */ static final String ATTR_INSTR_NAME = AdtPlugin.PLUGIN_ID + ".instrumentation"; //$NON-NLS-1$ - static final String INSTRUMENTATION_OK = null; private static final String EMPTY_STRING = ""; //$NON-NLS-1$ @Override @@ -58,7 +56,7 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate { IFile applicationPackage, AndroidManifestParser manifestParser) { String testPackage = manifestParser.getPackage(); - String runner = getRunnerFromConfig(configuration); + String runner = getRunner(project, configuration, manifestParser); if (runner == null) { AdtPlugin.displayError("Android Launch", "An instrumention test runner is not specified!"); @@ -72,14 +70,51 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate { manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(), junitLaunch, config, androidLaunch, monitor); } - - private String getRunnerFromConfig(ILaunchConfiguration configuration) { - String runner = EMPTY_STRING; + + /** + * Gets a instrumentation runner for the launch. + * + * If a runner is stored in the givenconfiguration
, will return that.
+ * Otherwise, will try to find the first valid runner for the project.
+ * If a runner can still not be found, will return null
.
+ *
+ * @param project the {@link IProject} for the app
+ * @param configuration the {@link ILaunchConfiguration} for the launch
+ * @param manifestParser the {@link AndroidManifestParser} for the project
+ *
+ * @return null
if no instrumentation runner can be found, otherwise return
+ * the fully qualified runner name.
+ */
+ private String getRunner(IProject project, ILaunchConfiguration configuration,
+ AndroidManifestParser manifestParser) {
try {
- runner = configuration.getAttribute(ATTR_INSTR_NAME, EMPTY_STRING);
+ String runner = getRunnerFromConfig(configuration);
+ if (runner != null) {
+ return runner;
+ }
+ final InstrumentationRunnerValidator instrFinder = new InstrumentationRunnerValidator(
+ BaseProjectHelper.getJavaProject(project), manifestParser);
+ runner = instrFinder.getValidInstrumentationTestRunner();
+ if (runner != null) {
+ AdtPlugin.printErrorToConsole(project,
+ String.format("Warning: No instrumentation runner found for the launch, " +
+ "using %1$s", runner));
+ return runner;
+ }
+ AdtPlugin.printErrorToConsole(project,
+ String.format("ERROR: Application does not specify a %1$s instrumentation or does not declare uses-library %2$s",
+ AndroidConstants.CLASS_INSTRUMENTATION_RUNNER,
+ AndroidConstants.LIBRARY_TEST_RUNNER));
+ return null;
} catch (CoreException e) {
- AdtPlugin.log(e, "Error when retrieving instrumentation info from launch config"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error when retrieving instrumentation info"); //$NON-NLS-1$
}
+ return null;
+
+ }
+
+ private String getRunnerFromConfig(ILaunchConfiguration configuration) throws CoreException {
+ String runner = configuration.getAttribute(ATTR_INSTR_NAME, EMPTY_STRING);
if (runner.length() < 1) {
return null;
}
@@ -87,31 +122,6 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
}
/**
- * Helper method to return the set of instrumentations for the Android project
- *
- * @param project the {@link IProject} to get instrumentations for
- * @return null if error occurred parsing instrumentations, otherwise returns array of
- * instrumentation class names
- */
- static String[] getInstrumentationsForProject(IProject project) {
- if (project != null) {
- try {
- // parse the manifest for the list of instrumentations
- AndroidManifestParser manifestParser = AndroidManifestParser.parse(
- BaseProjectHelper.getJavaProject(project), null /* errorListener */,
- true /* gatherData */, false /* markErrors */);
- if (manifestParser != null) {
- return manifestParser.getInstrumentations();
- }
- } catch (CoreException e) {
- AdtPlugin.log(e, "%s: Error parsing AndroidManifest.xml", //$NON-NLS-1$
- project.getName());
- }
- }
- return null;
- }
-
- /**
* Helper method to set JUnit-related attributes expected by JDT JUnit runner
*
* @param config the launch configuration to modify
@@ -121,56 +131,4 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND,
TestKindRegistry.JUNIT3_TEST_KIND_ID);
}
-
- /**
- * Helper method to determine if specified instrumentation can be used as a test runner
- *
- * @param project the {@link IJavaProject} to validate
- * @param instrumentation the instrumentation class name to validate
- * @return INSTRUMENTATION_OK
if valid, otherwise returns error message
- */
- static String validateInstrumentationRunner(IJavaProject project, String instrumentation) {
- AndroidManifestParser manifestParser;
- try {
- manifestParser = AndroidManifestParser.parse(
- project, null /* errorListener */,
- true /* gatherData */, false /* markErrors */);
- // check if this instrumentation is the standard test runner
- if (!instrumentation.equals(AndroidConstants.CLASS_INSTRUMENTATION_RUNNER)) {
- // check if it extends the standard test runner
- String result = BaseProjectHelper.testClassForManifest(project,
- instrumentation, AndroidConstants.CLASS_INSTRUMENTATION_RUNNER, true);
- if (result != BaseProjectHelper.TEST_CLASS_OK) {
- return String.format("The instrumentation runner must be of type %s",
- AndroidConstants.CLASS_INSTRUMENTATION_RUNNER);
- }
- }
- if (!hasTestRunnerLibrary(manifestParser)) {
- return String.format("%s does not not use the %s library",
- project.getProject().getName(), AndroidConstants.LIBRARY_TEST_RUNNER);
- }
- } catch (CoreException e) {
- String err = String.format("Error parsing AndroidManifest for %s",
- project.getProject().getName());
- AdtPlugin.log(e, err);
- return err;
- }
- return INSTRUMENTATION_OK;
- }
-
- /**
- * Helper method to determine if given manifest has a AndroidConstants.LIBRARY_TEST_RUNNER
- *
library reference
- *
- * @param manifestParser the {@link AndroidManifestParser} to search
- * @return true if test runner library found, false otherwise
- */
- static boolean hasTestRunnerLibrary(AndroidManifestParser manifestParser) {
- for (String lib : manifestParser.getUsesLibraries()) {
- if (lib.equals(AndroidConstants.LIBRARY_TEST_RUNNER)) {
- return true;
- }
- }
- return false;
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
index aa59a5157..eb5748269 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
@@ -118,7 +118,9 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
private Image mTabIcon = null;
private Combo mInstrumentationCombo;
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+ private static final String TAG = "AndroidJUnitLaunchConfigurationTab"; //$NON-NLS-1$
private String[] mInstrumentations = null;
+ private InstrumentationRunnerValidator mInstrValidator = null;
private ProjectChooserHelper mProjectChooserHelper;
/* (non-Javadoc)
@@ -349,7 +351,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
break;
}
}
- }
+ }
} catch (CoreException ce) {
// ignore
}
@@ -454,7 +456,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
mapResources(config);
} catch (CoreException e) {
// TODO: does the real error need to be extracted out of CoreException
- AdtPlugin.log(e, "Error occurred saving configuration");
+ AdtPlugin.log(e, "Error occurred saving configuration"); //$NON-NLS-1$
}
AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config);
@@ -486,7 +488,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
public Image getImage() {
// reuse icon from the Android App Launch config tab
if (mTabIcon == null) {
- mTabIcon= AdtPlugin.getImageLoader().loadImage(MainLaunchConfigTab.LAUNCH_TAB_IMAGE,
+ mTabIcon = AdtPlugin.getImageLoader().loadImage(MainLaunchConfigTab.LAUNCH_TAB_IMAGE,
null);
}
return mTabIcon;
@@ -514,7 +516,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
setErrorMessage(e.getMessage());
return;
} catch (InvocationTargetException e) {
- AdtPlugin.log(e.getTargetException(), "Error finding test types");
+ AdtPlugin.log(e.getTargetException(), "Error finding test types"); //$NON-NLS-1$
return;
} finally {
mTestRadioButton.setSelection(radioSetting[0]);
@@ -675,10 +677,10 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
return;
}
} catch (CoreException e) {
- AdtPlugin.log(e, "validatePage failed");
+ AdtPlugin.log(e, "validatePage failed"); //$NON-NLS-1$
}
- validateInstrumentation(javaProject);
+ validateInstrumentation();
}
private void validateJavaProject(IJavaProject javaProject) {
@@ -688,19 +690,14 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
}
}
- private void validateInstrumentation(IJavaProject javaProject) {
- if (mInstrumentations == null || mInstrumentations.length < 1) {
- setErrorMessage("Specified project has no defined instrumentations");
- return;
- }
+ private void validateInstrumentation() {
String instrumentation = getSelectedInstrumentation();
if (instrumentation == null) {
- setErrorMessage("Instrumentation not specified");
+ setErrorMessage("Instrumentation runner not specified");
return;
}
- String result = AndroidJUnitLaunchConfigDelegate.validateInstrumentationRunner(
- javaProject, instrumentation);
- if (result != AndroidJUnitLaunchConfigDelegate.INSTRUMENTATION_OK) {
+ String result = mInstrValidator.validateInstrumentationRunner(instrumentation);
+ if (result != InstrumentationRunnerValidator.INSTRUMENTATION_OK) {
setErrorMessage(result);
return;
}
@@ -949,14 +946,15 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
/**
* Loads the UI with the instrumentations of the specified project, and stores the
- * activities in mActivities
.
- *
- * First activity is selected by default if present.
+ * instrumentations in mInstrumentations
.
*
* @param project the {@link IProject} to load the instrumentations from.
*/
private void loadInstrumentations(IProject project) {
- mInstrumentations = AndroidJUnitLaunchConfigDelegate.getInstrumentationsForProject(project);
+ try {
+ mInstrValidator = new InstrumentationRunnerValidator(project);
+ mInstrumentations = (mInstrValidator == null ? null :
+ mInstrValidator.getInstrumentations());
if (mInstrumentations != null) {
mInstrumentationCombo.removeAll();
for (String instrumentation : mInstrumentations) {
@@ -966,9 +964,13 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
// config object.
return;
}
-
+ } catch (CoreException e) {
+ AdtPlugin.logAndPrintError(e, TAG, "ERROR: Failed to get instrumentations for %1$s",
+ project.getName());
+ }
// if we reach this point, either project is null, or we got an exception during
// the parsing. In either case, we empty the instrumentation list.
+ mInstrValidator = null;
mInstrumentations = null;
mInstrumentationCombo.removeAll();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchShortcut.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchShortcut.java
index 30649e2e8..f06f7eb4c 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchShortcut.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchShortcut.java
@@ -16,10 +16,6 @@
package com.android.ide.eclipse.adt.launch.junit;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jdt.core.IJavaElement;
@@ -43,33 +39,18 @@ public class AndroidJUnitLaunchShortcut extends JUnitLaunchShortcut {
protected ILaunchConfigurationWorkingCopy createLaunchConfiguration(IJavaElement element)
throws CoreException {
ILaunchConfigurationWorkingCopy config = super.createLaunchConfiguration(element);
- IProject project = element.getResource().getProject();
- String[] instrumentations =
- AndroidJUnitLaunchConfigDelegate.getInstrumentationsForProject(project);
- boolean runnerFound = false;
- if (instrumentations != null) {
- // just pick the first valid runner
- for (String instr : instrumentations) {
- if (AndroidJUnitLaunchConfigDelegate.validateInstrumentationRunner(
- element.getJavaProject(), instr) ==
- AndroidJUnitLaunchConfigDelegate.INSTRUMENTATION_OK) {
-
- config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME,
- instr);
- runnerFound = true;
- break;
- }
- }
- }
- if (!runnerFound) {
- // TODO: put this in a string properties
- String msg = String.format("ERROR: Application does not specify a %s instrumentation or does not declare uses-library %s",
- AndroidConstants.CLASS_INSTRUMENTATION_RUNNER,
- AndroidConstants.LIBRARY_TEST_RUNNER);
- AdtPlugin.printErrorToConsole(project, msg);
+ // just get first valid instrumentation runner
+ String instrumentation = new InstrumentationRunnerValidator(element.getJavaProject()).
+ getValidInstrumentationTestRunner();
+ if (instrumentation != null) {
+ config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME,
+ instrumentation);
}
- AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config);
+ // if a valid runner is not found, rely on launch delegate to log error.
+ // This method is called without explicit user action to launch Android JUnit, so avoid
+ // logging an error here.
+ AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config);
return config;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
new file mode 100644
index 000000000..f22fc7cda
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
@@ -0,0 +1,145 @@
+/*
+ * 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.launch.junit;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.common.project.AndroidManifestParser;
+import com.android.ide.eclipse.common.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[] mInstrumentations = 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;
+ try {
+ AndroidManifestParser manifestParser = AndroidManifestParser.parse(javaProject,
+ null /* errorListener */, true /* gatherData */, false /* markErrors */);
+ init(manifestParser);
+ } catch (CoreException e) {
+ AdtPlugin.printErrorToConsole(javaProject.getProject(), "ERROR: Failed to parse %1$s",
+ AndroidConstants.FN_ANDROID_MANIFEST);
+ }
+ }
+
+ /**
+ * 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 AndroidManifestParser}
+ *
+ * @param javaProject the {@link IJavaProject} for the Android project to validate
+ * @param manifestParser the {@link AndroidManifestParser} for the Android project
+ */
+ InstrumentationRunnerValidator(IJavaProject javaProject, AndroidManifestParser manifestParser) {
+ mJavaProject = javaProject;
+ init(manifestParser);
+ }
+
+ private void init(AndroidManifestParser manifestParser) {
+ mInstrumentations = manifestParser.getInstrumentations();
+ mHasRunnerLibrary = hasTestRunnerLibrary(manifestParser);
+ }
+
+ /**
+ * Helper method to determine if given manifest has a AndroidConstants.LIBRARY_TEST_RUNNER
+ *
library reference
+ *
+ * @param manifestParser the {@link AndroidManifestParser} to search
+ * @return true if test runner library found, false otherwise
+ */
+ private boolean hasTestRunnerLibrary(AndroidManifestParser manifestParser) {
+ for (String lib : manifestParser.getUsesLibraries()) {
+ if (lib.equals(AndroidConstants.LIBRARY_TEST_RUNNER)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return the set of instrumentations for the Android project.
+ *
+ * @return null
null if no valid
+ * instrumentation can be found.
+ */
+ String getValidInstrumentationTestRunner() {
+ for (String instrumentation : getInstrumentations()) {
+ 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 #getInstrumentations()}
+ * @return INSTRUMENTATION_OK
if valid, otherwise returns error message
+ */
+ String validateInstrumentationRunner(String instrumentation) {
+ if (!mHasRunnerLibrary) {
+ return String.format("The application does not declare uses-library %1$s",
+ AndroidConstants.LIBRARY_TEST_RUNNER);
+ }
+ // check if this instrumentation is the standard test runner
+ if (!instrumentation.equals(AndroidConstants.CLASS_INSTRUMENTATION_RUNNER)) {
+ // check if it extends the standard test runner
+ String result = BaseProjectHelper.testClassForManifest(mJavaProject,
+ instrumentation, AndroidConstants.CLASS_INSTRUMENTATION_RUNNER, true);
+ if (result != BaseProjectHelper.TEST_CLASS_OK) {
+ return String.format("The instrumentation runner must be of type %s",
+ AndroidConstants.CLASS_INSTRUMENTATION_RUNNER);
+ }
+ }
+ return INSTRUMENTATION_OK;
+ }
+}
--
2.11.0