aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java293
1 files changed, 293 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java
new file mode 100644
index 000000000..c773ab9ba
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java
@@ -0,0 +1,293 @@
+/*
+ * 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.ddmlib.IDevice;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.launch.DelayedLaunchInfo;
+import com.android.ide.eclipse.adt.internal.launch.IAndroidLaunchAction;
+import com.android.ide.eclipse.adt.internal.launch.LaunchMessages;
+import com.android.ide.eclipse.adt.internal.launch.junit.runtime.AndroidJUnitLaunchInfo;
+import com.android.ide.eclipse.adt.internal.launch.junit.runtime.RemoteAdtTestRunner;
+import com.google.common.base.Joiner;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate;
+import org.eclipse.jdt.launching.IVMRunner;
+import org.eclipse.jdt.launching.VMRunnerConfiguration;
+import org.eclipse.swt.widgets.Display;
+
+import java.util.Collection;
+
+/**
+ * A launch action that executes a instrumentation test run on an Android device.
+ */
+class AndroidJUnitLaunchAction implements IAndroidLaunchAction {
+ private static final Joiner JOINER = Joiner.on(',').skipNulls();
+ private final AndroidJUnitLaunchInfo mLaunchInfo;
+
+ /**
+ * Creates a AndroidJUnitLaunchAction.
+ *
+ * @param launchInfo the {@link AndroidJUnitLaunchInfo} for the JUnit run
+ */
+ public AndroidJUnitLaunchAction(AndroidJUnitLaunchInfo launchInfo) {
+ mLaunchInfo = launchInfo;
+ }
+
+ /**
+ * Launch a instrumentation test run on given Android devices.
+ * Reuses JDT JUnit launch delegate so results can be communicated back to JDT JUnit UI.
+ * <p/>
+ * Note: Must be executed on non-UI thread.
+ *
+ * @see IAndroidLaunchAction#doLaunchActions(DelayedLaunchInfo, IDevice)
+ */
+ @Override
+ public boolean doLaunchAction(DelayedLaunchInfo info, Collection<IDevice> devices) {
+ String msg = String.format(LaunchMessages.AndroidJUnitLaunchAction_LaunchInstr_2s,
+ mLaunchInfo.getRunner(), JOINER.join(devices));
+ AdtPlugin.printToConsole(info.getProject(), msg);
+
+ try {
+ mLaunchInfo.setDebugMode(info.isDebugMode());
+ mLaunchInfo.setDevices(devices);
+ JUnitLaunchDelegate junitDelegate = new JUnitLaunchDelegate(mLaunchInfo);
+ final String mode = info.isDebugMode() ? ILaunchManager.DEBUG_MODE :
+ ILaunchManager.RUN_MODE;
+
+ junitDelegate.launch(info.getLaunch().getLaunchConfiguration(), mode, info.getLaunch(),
+ info.getMonitor());
+
+ // TODO: need to add AMReceiver-type functionality somewhere
+ } catch (CoreException e) {
+ AdtPlugin.printErrorToConsole(info.getProject(),
+ LaunchMessages.AndroidJUnitLaunchAction_LaunchFail);
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getLaunchDescription() {
+ return String.format(LaunchMessages.AndroidJUnitLaunchAction_LaunchDesc_s,
+ mLaunchInfo.getRunner());
+ }
+
+ /**
+ * Extends the JDT JUnit launch delegate to allow for JUnit UI reuse.
+ */
+ private static class JUnitLaunchDelegate extends JUnitLaunchConfigurationDelegate {
+
+ private AndroidJUnitLaunchInfo mLaunchInfo;
+
+ public JUnitLaunchDelegate(AndroidJUnitLaunchInfo launchInfo) {
+ mLaunchInfo = launchInfo;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public synchronized void launch(ILaunchConfiguration configuration, String mode,
+ ILaunch launch, IProgressMonitor monitor) throws CoreException {
+ // TODO: is progress monitor adjustment needed here?
+ super.launch(configuration, mode, launch, monitor);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#verifyMainTypeName(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public String verifyMainTypeName(ILaunchConfiguration configuration) {
+ return "com.android.ide.eclipse.adt.junit.internal.runner.RemoteAndroidTestRunner"; //$NON-NLS-1$
+ }
+
+ /**
+ * Overrides parent to return a VM Runner implementation which launches a thread, rather
+ * than a separate VM process
+ */
+ @Override
+ public IVMRunner getVMRunner(ILaunchConfiguration configuration, String mode) {
+ return new VMTestRunner(mLaunchInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getLaunch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String)
+ */
+ @Override
+ public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) {
+ return mLaunchInfo.getLaunch();
+ }
+ }
+
+ /**
+ * Provides a VM runner implementation which starts a inline implementation of a launch process
+ */
+ private static class VMTestRunner implements IVMRunner {
+
+ private final AndroidJUnitLaunchInfo mJUnitInfo;
+
+ VMTestRunner(AndroidJUnitLaunchInfo info) {
+ mJUnitInfo = info;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws CoreException
+ */
+ @Override
+ public void run(final VMRunnerConfiguration config, ILaunch launch,
+ IProgressMonitor monitor) throws CoreException {
+
+ TestRunnerProcess runnerProcess =
+ new TestRunnerProcess(config, mJUnitInfo);
+ launch.addProcess(runnerProcess);
+ runnerProcess.run();
+ }
+ }
+
+ /**
+ * Launch process that executes the tests.
+ */
+ private static class TestRunnerProcess implements IProcess {
+
+ private final VMRunnerConfiguration mRunConfig;
+ private final AndroidJUnitLaunchInfo mJUnitInfo;
+ private RemoteAdtTestRunner mTestRunner = null;
+ private boolean mIsTerminated = false;
+
+ TestRunnerProcess(VMRunnerConfiguration runConfig, AndroidJUnitLaunchInfo info) {
+ mRunConfig = runConfig;
+ mJUnitInfo = info;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IProcess#getAttribute(java.lang.String)
+ */
+ @Override
+ public String getAttribute(String key) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.debug.core.model.IProcess#getExitValue()
+ */
+ @Override
+ public int getExitValue() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IProcess#getLabel()
+ */
+ @Override
+ public String getLabel() {
+ return mJUnitInfo.getLaunch().getLaunchMode();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IProcess#getLaunch()
+ */
+ @Override
+ public ILaunch getLaunch() {
+ return mJUnitInfo.getLaunch();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IProcess#getStreamsProxy()
+ */
+ @Override
+ public IStreamsProxy getStreamsProxy() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IProcess#setAttribute(java.lang.String,
+ * java.lang.String)
+ */
+ @Override
+ public void setAttribute(String key, String value) {
+ // ignore
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ @Override
+ public boolean canTerminate() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ @Override
+ public boolean isTerminated() {
+ return mIsTerminated;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ @Override
+ public void terminate() {
+ if (mTestRunner != null) {
+ mTestRunner.terminate();
+ }
+ mIsTerminated = true;
+ }
+
+ /**
+ * Launches a test runner that will communicate results back to JDT JUnit UI.
+ * <p/>
+ * Must be executed on a non-UI thread.
+ */
+ public void run() {
+ if (Display.getCurrent() != null) {
+ AdtPlugin.log(IStatus.ERROR, "Adt test runner executed on UI thread");
+ AdtPlugin.printErrorToConsole(mJUnitInfo.getProject(),
+ "Test launch failed due to internal error: Running tests on UI thread");
+ terminate();
+ return;
+ }
+ mTestRunner = new RemoteAdtTestRunner();
+ mTestRunner.runTests(mRunConfig.getProgramArguments(), mJUnitInfo);
+ }
+ }
+}
+