Skip to content

Commit

Permalink
Simplify/Clean-up code of o.e.pde.junit.runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell committed Sep 25, 2023
1 parent d6cee01 commit 25c5094
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 215 deletions.
2 changes: 0 additions & 2 deletions ui/org.eclipse.pde.junit.runtime/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ Bundle-Version: 3.7.200.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.jdt.junit.runtime;bundle-version="[3.5.0,4.0.0)",
org.junit;bundle-version="3.8.2",
org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)",
org.eclipse.ui;bundle-version="[3.2.0,4.0.0)";resolution:=optional
Export-Package: org.eclipse.pde.internal.junit.runtime;x-internal:=true
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-Activator: org.eclipse.pde.internal.junit.runtime.PDEJUnitRuntimePlugin
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.ui.testing;resolution:=optional
Automatic-Module-Name: org.eclipse.pde.junit.runtime
18 changes: 18 additions & 0 deletions ui/org.eclipse.pde.junit.runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
This PDE JUnit runtime is added to test-runtimes launched from an Eclipse workspace and allows JUnit tests to be run with an OSGi runtime.
It supports the following use cases:
1. Headless tests (no UI, no workbench)<br/>
Runs NonUIThreadTestApplication with no testable object
2. e4 UI tests (e4 UI, no workbench)<br/>
Runs NonUIThreadTestApplication with a testable object from e4 service
3. UI tests run in the non UI thread (UI, workbench)<br/>
Runs NonUIThreadTestApplication with a testable object from e4 service or PlatformUI
4. UI tests run in the UI thread (UI, workbench)<br/>
Runs UITestApplication with a testable object from e4 service or PlatformUI
5. Headless tests with no application (no UI, no workbench, no application)<br/>
Runs directly with no application

If no pde.junit.runtime is available in the Target-Platform the one from the running Eclipse is added to the test-runtime.
Of course users can target older Eclipse versions (which for example require older Java-versions),
which is why the requirements of this Plug-in should be as low as possible to make it resolve even in older runtimes.

If changes are made, one should ensure that the requirement's lower-bounds specified in the MANIFEST.MF are still valid.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018 IBM Corporation and others.
* Copyright (c) 2018, 2023 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -36,8 +36,9 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
for (Bundle temp : bundleList) {
try {
Class<?> c = temp.loadClass(name);
if (c != null)
if (c != null) {
return c;
}
} catch (ClassNotFoundException e) {
}
}
Expand All @@ -46,9 +47,8 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {

@Override
protected URL findResource(String name) {
URL url = null;
for (Bundle temp : bundleList) {
url = temp.getResource(name);
URL url = temp.getResource(name);
if (url != null) {
try {
return FileLocator.resolve(url);
Expand All @@ -57,7 +57,7 @@ protected URL findResource(String name) {
}
}
}
return url;
return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2015 EclipseSource Corporation and others.
* Copyright (c) 2009, 2023 EclipseSource Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,14 +13,19 @@
*******************************************************************************/
package org.eclipse.pde.internal.junit.runtime;

import java.util.Objects;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.junit.Assert;
import org.eclipse.ui.testing.TestableObject;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;

/**
* A Workbench that runs a test suite specified in the
Expand All @@ -32,27 +37,23 @@ public class NonUIThreadTestApplication implements IApplication {

protected IApplication fApplication;
protected Object fTestHarness;
protected boolean runInUIThreadAndRequirePlatformUI = false;
protected String defaultApplicationId = DEFAULT_HEADLESSAPP;

@Override
public Object start(IApplicationContext context) throws Exception {
String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);

String appId = getApplicationToRun(args);
IApplication app = getApplication(appId);
Assert.assertNotNull(app);
IApplication app = Objects.requireNonNull(getApplication(appId));

if (!DEFAULT_HEADLESSAPP.equals(appId)) {
if (runInUIThreadAndRequirePlatformUI || !DEFAULT_HEADLESSAPP.equals(appId)) {
// this means we are running a different application, which potentially can be UI application;
// non-ui thread test app can also mean we are running UI tests but outside the UI thread;
// this is a pattern used by SWT bot and worked before; we continue to support this
// (see bug 340906 for details)
installPlatformUITestHarness();
}

return runApp(app, context);
}

protected Object runApp(IApplication app, IApplicationContext context) throws Exception {
fApplication = app;
return fApplication.start(context);
}
Expand All @@ -66,27 +67,53 @@ protected Object runApp(IApplication app, IApplicationContext context) throws Ex
*
* @throws Exception
*/
private void installPlatformUITestHarness() throws Exception {
Object testableObject = PDEJUnitRuntimePlugin.getDefault().getTestableObject();
private void installPlatformUITestHarness() throws ReflectiveOperationException {
Object testableObject = getRegisteredTestableObject();
if (testableObject == null) {
try {
try { // If the service doesn't return a testable object ask PlatformUI directly
Class<?> platformUIClass = Class.forName("org.eclipse.ui.PlatformUI", true, getClass().getClassLoader()); //$NON-NLS-1$
testableObject = platformUIClass.getMethod("getTestableObject").invoke(null); //$NON-NLS-1$
} catch (ClassNotFoundException e) {
// PlatformUI is not available
} catch (ClassNotFoundException e) { // PlatformUI is not available
if (runInUIThreadAndRequirePlatformUI) {
throw e;
}
}
}
if (testableObject != null) {
fTestHarness = new PlatformUITestHarness(testableObject, true);
fTestHarness = new PlatformUITestHarness(testableObject, !runInUIThreadAndRequirePlatformUI);
}
}

/**
* Returns a {@link TestableObject} provided by a TestableObject service or {@code null} if no implementation can be found.
* The TestableObject is used to hook tests into the application lifecycle.
* <p>
* It is recommended the testable object is obtained via service instead Workbench#getWorkbenchTestable() to avoid
* the tests having a dependency on the Workbench.
* </p>
* @return TestableObject provided via service or {@code null}
*/
private static Object getRegisteredTestableObject() {
BundleContext context = FrameworkUtil.getBundle(NonUIThreadTestApplication.class).getBundleContext();
ServiceReference<?> reference = context.getServiceReference("org.eclipse.ui.testing.TestableObject"); //$NON-NLS-1$
if (reference != null) {
try {
return context.getService(reference);
} finally {
context.ungetService(reference);
}
}
return null;
}

@Override
public void stop() {
if (fApplication != null)
if (fApplication != null) {
fApplication.stop();
if (fTestHarness != null)
}
if (fTestHarness != null) {
fTestHarness = null;
}
}

/*
Expand All @@ -98,8 +125,7 @@ private IApplication getApplication(String appId) throws CoreException {
// If no application is specified, the 3.0 default workbench application
// is returned.
IExtension extension = Platform.getExtensionRegistry().getExtension(Platform.PI_RUNTIME, Platform.PT_APPLICATIONS, appId);

Assert.assertNotNull(extension);
Objects.requireNonNull(extension);

// If the extension does not have the correct grammar, return null.
// Otherwise, return the application object.
Expand All @@ -108,8 +134,9 @@ private IApplication getApplication(String appId) throws CoreException {
IConfigurationElement[] runs = elements[0].getChildren("run"); //$NON-NLS-1$
if (runs.length > 0) {
Object runnable = runs[0].createExecutableExtension("class"); //$NON-NLS-1$
if (runnable instanceof IApplication)
if (runnable instanceof IApplication) {
return (IApplication) runnable;
}
}
}
return null;
Expand All @@ -125,18 +152,12 @@ private IApplication getApplication(String appId) throws CoreException {
*
*/
private String getApplicationToRun(String[] args) {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-testApplication") && i < args.length - 1) //$NON-NLS-1$
return args[i + 1];
String testApp = RemotePluginTestRunner.getArgumentValue(args, "-testApplication"); //$NON-NLS-1$
if (testApp != null) {
return testApp;
}
IProduct product = Platform.getProduct();
if (product != null)
return product.getApplication();
return getDefaultApplicationId();
}

protected String getDefaultApplicationId() {
return DEFAULT_HEADLESSAPP;
return product != null ? product.getApplication() : defaultApplicationId;
}

}

This file was deleted.

Loading

0 comments on commit 25c5094

Please sign in to comment.