Automated import from //branches/master/...@141783,141783

This commit is contained in:
Brett Chabot
2009-03-24 20:54:44 -07:00
committed by The Android Open Source Project
parent 3e6efddf28
commit 6dc9883c6e
4 changed files with 225 additions and 139 deletions

View File

@@ -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.
* <p/>
* 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!");
@@ -73,44 +71,56 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
junitLaunch, config, androidLaunch, monitor);
}
private String getRunnerFromConfig(ILaunchConfiguration configuration) {
String runner = EMPTY_STRING;
/**
* Gets a instrumentation runner for the launch.
* <p/>
* If a runner is stored in the given <code>configuration</code>, 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 <code>null</code>.
*
* @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 <code>null</code> 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);
} catch (CoreException e) {
AdtPlugin.log(e, "Error when retrieving instrumentation info from launch config"); //$NON-NLS-1$
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"); //$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;
}
return runner;
}
/**
* 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
*
@@ -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 <code>INSTRUMENTATION_OK</code> 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 <code>AndroidConstants.LIBRARY_TEST_RUNNER
* </code> 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;
}
}

View File

@@ -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)
@@ -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 <code>mActivities</code>.
* <p/>
* First activity is selected by default if present.
* instrumentations in <code>mInstrumentations</code>.
*
* @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();
}

View File

@@ -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) {
// just get first valid instrumentation runner
String instrumentation = new InstrumentationRunnerValidator(element.getJavaProject()).
getValidInstrumentationTestRunner();
if (instrumentation != null) {
config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME,
instr);
runnerFound = true;
break;
instrumentation);
}
}
}
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);
}
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;
}
}

View File

@@ -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 <code>AndroidConstants.LIBRARY_TEST_RUNNER
* </code> 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 <code>null</code if error occurred parsing instrumentations, otherwise returns array
* of instrumentation class names
*/
String[] getInstrumentations() {
return mInstrumentations;
}
/**
* 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.
*/
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 <code>INSTRUMENTATION_OK</code> 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;
}
}