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 22, 2023
1 parent fcb15cb commit 76625c5
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 208 deletions.
1 change: 0 additions & 1 deletion ui/org.eclipse.pde.junit.runtime/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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
Expand Down
18 changes: 18 additions & 0 deletions ui/org.eclipse.pde.junit.runtime/readme.txt
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)
Runs NonUIThreadTestApplication with no testable object
2. e4 UI tests (e4 UI, no workbench)
Runs NonUIThreadTestApplication with a testable object from e4 service
3. UI tests run in the non UI thread (UI, workbench)
Runs NonUIThreadTestApplication with a testable object from e4 service or PlatformUI
4. UI tests run in the UI thread (UI, workbench)
Runs UITestApplication with a testable object from e4 service or PlatformUI
5. Headless tests with no application (no UI, no workbench, no application)
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,14 +37,14 @@ public class NonUIThreadTestApplication implements IApplication {

protected IApplication fApplication;
protected Object fTestHarness;
protected boolean requirePlatformUI = false;

@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)) {
// this means we are running a different application, which potentially can be UI application;
Expand All @@ -48,11 +53,6 @@ public Object start(IApplicationContext context) throws Exception {
// (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 +66,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 (requirePlatformUI) {
throw e;
}
}
}
if (testableObject != null) {
fTestHarness = new PlatformUITestHarness(testableObject, true);
}
}

/**
* 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 +124,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 +133,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,14 +151,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();
return product != null ? product.getApplication() : getDefaultApplicationId();
}

protected String getDefaultApplicationId() {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2011, 2015 Gunnar Wagenknecht and others.
* Copyright (c) 2011, 2023 Gunnar Wagenknecht and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the terms of the
Expand Down Expand Up @@ -47,7 +47,7 @@ public void runTests() {
if (fRunTestsInSeparateThread) {
// wrap into separate thread and run from there
final Thread testRunnerThread = new Thread(testsRunner, "Plug-in Tests Runner"); //$NON-NLS-1$
fTestableObject.runTest(() -> testRunnerThread.start());
fTestableObject.runTest(testRunnerThread::start);

// wait for tests to finish
// note, this has do be done outside #runTest method to not lock the UI
Expand Down
Loading

0 comments on commit 76625c5

Please sign in to comment.