Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower requirements of pde.junit.runtime and simplify/clean-up its code #765

Merged
merged 2 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ui/org.eclipse.pde.junit.runtime/.classpath
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ org.eclipse.jdt.core.circularClasspath=error
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
Expand Down Expand Up @@ -103,7 +103,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=17
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
Expand Down
12 changes: 5 additions & 7 deletions ui/org.eclipse.pde.junit.runtime/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.pde.junit.runtime; singleton:=true
Bundle-Version: 3.7.200.qualifier
Bundle-Version: 3.8.0.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
Require-Bundle: org.eclipse.jdt.junit.runtime;bundle-version="[3.4.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
org.eclipse.ui;bundle-version="[3.7.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-RequiredExecutionEnvironment: JavaSE-1.8
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
Loading