OSDN Git Service

Automated import from //branches/cupcake/...@141778,141778
authorBrett Chabot <>
Wed, 25 Mar 2009 01:21:57 +0000 (18:21 -0700)
committerThe Android Open Source Project <initial-contribution@android.com>
Wed, 25 Mar 2009 01:21:57 +0000 (18:21 -0700)
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchShortcut.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java [new file with mode: 0644]

index a624b00..fa8e4b0 100755 (executable)
@@ -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 
+ * 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. 
+     * <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);
+            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 <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;
-    }
 }
index aa59a51..eb57482 100644 (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)
@@ -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 <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();
     }
index 30649e2..f06f7eb 100755 (executable)
 
 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 (file)
index 0000000..f22fc7c
--- /dev/null
@@ -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;
+    }
+}