Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Bundle-Localization: plugin
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.jdt.ls.core,
com.microsoft.java.test.plugin,
com.google.gson,
org.junit,
org.apache.commons.commons-io;bundle-version="2.12.0",
org.eclipse.core.resources,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<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.junit.JUNIT_CONTAINER/5"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>modular-junit</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module com.example.modular {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package p1;

import org.junit.jupiter.api.Test;

class FirstTest {
@Test
void testFirstPackage() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package p2;

import org.junit.jupiter.api.Test;

class SecondTest {
@Test
void testSecondPackage() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@
package com.microsoft.java.test.plugin.launchers;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.junit.Test;

import com.microsoft.java.test.plugin.AbstractProjectsManagerBasedTest;
import com.microsoft.java.test.plugin.model.Response;
import com.google.gson.Gson;

public class JUnitLaunchConfigurationDelegateTest extends AbstractProjectsManagerBasedTest {

Expand All @@ -39,4 +46,40 @@ public void testWorkingDirectoryForTestNgUnmanagedFolder() throws Exception {
assertEquals(0, response.getStatus());
assertTrue(response.getBody().workingDirectory.endsWith("simple"));
}

@Test
public void testAddOpensForAllSelectedPackagesInModularProject() throws Exception {
final IProject project = importProjects("modular-junit").get(0);
final IJavaProject javaProject = JavaCore.create(project);
final IType firstTest = javaProject.findType("p1.FirstTest");
final IType secondTest = javaProject.findType("p2.SecondTest");
assertNotNull(firstTest);
assertNotNull(secondTest);

final Map<String, Object> request = new LinkedHashMap<>();
request.put("projectName", javaProject.getElementName());
request.put("testLevel", 5);
request.put("testKind", 0);
request.put("testNames", Arrays.asList(
firstTest.getFullyQualifiedName(), secondTest.getFullyQualifiedName()));
request.put("testHandles", Arrays.asList(
firstTest.getHandleIdentifier(), secondTest.getHandleIdentifier()));

final Response<JUnitLaunchArguments> response = JUnitLaunchUtils.resolveLaunchArgument(
Arrays.asList(new Gson().toJson(request)), new NullProgressMonitor());

assertEquals(0, response.getStatus());
final List<String> vmArguments = Arrays.asList(response.getBody().vmArguments);
final String firstPackagePrefix = "com.example.modular/p1=";
final String firstPackageOpen = vmArguments.stream()
.filter(argument -> argument.startsWith(firstPackagePrefix))
.findFirst()
.orElseThrow(() -> new AssertionError("Missing --add-opens for p1"));
final String targets = firstPackageOpen.substring(firstPackagePrefix.length());
final String secondPackageOpen = "com.example.modular/p2=" + targets;
assertEquals("--add-opens", vmArguments.get(vmArguments.indexOf(firstPackageOpen) - 1));
assertTrue(vmArguments.contains(secondPackageOpen));
assertEquals("--add-opens", vmArguments.get(vmArguments.indexOf(secondPackageOpen) - 1));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.Launch;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
Expand Down Expand Up @@ -65,6 +68,30 @@ public JUnitLaunchConfigurationDelegate(Argument args) {
this.args = args;
}

@Override
protected IMember[] evaluateTests(ILaunchConfiguration configuration, IProgressMonitor monitor)
throws CoreException {
if (this.args.testLevel != TestLevel.CLASS || this.args.testNames == null ||
this.args.testNames.length < 2 || this.args.testHandles == null) {
return super.evaluateTests(configuration, monitor);
}
if (this.args.testHandles.length != this.args.testNames.length) {
throw new CoreException(new Status(IStatus.ERROR, JUnitPlugin.PLUGIN_ID,
"Cannot resolve all selected test classes. Refresh the Test Explorer and retry."));
}

final List<IMember> testTypes = new ArrayList<>();
for (final String handle : this.args.testHandles) {
final IJavaElement element = JavaCore.create(handle);
if (!(element instanceof IType) || !element.exists()) {
throw new CoreException(new Status(IStatus.ERROR, JUnitPlugin.PLUGIN_ID,
"Cannot resolve a selected test class. Refresh the Test Explorer and retry."));
}
testTypes.add((IType) element);
}
return testTypes.toArray(new IMember[testTypes.size()]);
}

public Response<JUnitLaunchArguments> getJUnitLaunchArguments(ILaunchConfiguration configuration, String mode,
IProgressMonitor monitor) {
final ILaunch launch = new Launch(configuration, mode, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class Argument {
public TestLevel testLevel;
public TestKind testKind;
public String[] testNames;
public String[] testHandles;
public String uniqueId;
}
}
22 changes: 21 additions & 1 deletion src/utils/launchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ async function getLaunchArguments(testContext: IRunTestContext): Promise<IJUnitL
testLevel,
testContext.kind,
getTestNames(testContext),
getTestHandles(testContext),
uniqueId
);
}
Expand All @@ -118,13 +119,32 @@ function getTestNames(testContext: IRunTestContext): string[] {
}).filter(Boolean) as string[];
}

async function resolveJUnitLaunchArguments(projectName: string, testLevel: TestLevel, testKind: TestKind, testNames: string[], uniqueId: string | undefined): Promise<IJUnitLaunchArguments> {
function getTestHandles(testContext: IRunTestContext): string[] {
if (dataCache.get(testContext.testItems[0])?.testLevel !== TestLevel.Class ||
testContext.testItems.length < 2) {
return [];
}

const handles: (string | undefined)[] = testContext.testItems.map((item: TestItem) => {
return dataCache.get(item)?.jdtHandler;
});
if (handles.some((handle: string | undefined) => !handle)) {
const error: Error = new Error('Failed to resolve all selected test classes. Refresh the Test Explorer and retry.');
sendError(error);
throw error;
}
return handles as string[];
}

async function resolveJUnitLaunchArguments(projectName: string, testLevel: TestLevel, testKind: TestKind,
testNames: string[], testHandles: string[], uniqueId: string | undefined): Promise<IJUnitLaunchArguments> {
const argument: Response<IJUnitLaunchArguments> | undefined = await executeJavaLanguageServerCommand<Response<IJUnitLaunchArguments>>(
JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({
projectName,
testLevel,
testKind,
testNames,
testHandles,
uniqueId
}),
);
Expand Down
Loading