diff --git a/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchConfigurationDelegate.java b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchConfigurationDelegate.java index 2d8e7d31..1e250e98 100644 --- a/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchConfigurationDelegate.java +++ b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchConfigurationDelegate.java @@ -12,6 +12,7 @@ package com.microsoft.java.test.plugin.launchers; import com.microsoft.java.test.plugin.launchers.JUnitLaunchUtils.Argument; +import com.microsoft.java.test.plugin.model.Response; import com.microsoft.java.test.plugin.model.TestKind; import com.microsoft.java.test.plugin.model.TestLevel; import com.microsoft.java.test.plugin.util.JUnitPlugin; @@ -65,8 +66,8 @@ public JUnitLaunchConfigurationDelegate(Argument args) { this.args = args; } - public JUnitLaunchArguments getJUnitLaunchArguments(ILaunchConfiguration configuration, String mode, - IProgressMonitor monitor) throws CoreException { + public Response getJUnitLaunchArguments(ILaunchConfiguration configuration, String mode, + IProgressMonitor monitor) { final ILaunch launch = new Launch(configuration, mode, null); // TODO: Make the getVMRunnerConfiguration() in super class protected. @@ -87,12 +88,12 @@ public JUnitLaunchArguments getJUnitLaunchArguments(ILaunchConfiguration configu launchArguments.vmArguments = getVmArguments(config); launchArguments.programArguments = parseParameters(config.getProgramArguments()); - - return launchArguments; + return new Response<>(launchArguments, null); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | - InvocationTargetException e) { + InvocationTargetException | CoreException e) { JUnitPlugin.logException("failed to resolve the classpath.", e); - return null; + final String msg = e.getCause() != null ? e.getCause().getMessage() : e.getMessage(); + return new Response<>(null, msg); } } diff --git a/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchUtils.java b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchUtils.java index 640c903b..f40413c7 100644 --- a/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchUtils.java +++ b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/launchers/JUnitLaunchUtils.java @@ -13,6 +13,7 @@ import com.google.gson.Gson; import com.microsoft.java.test.plugin.launchers.JUnitLaunchConfigurationDelegate.JUnitLaunchArguments; +import com.microsoft.java.test.plugin.model.Response; import com.microsoft.java.test.plugin.model.TestKind; import com.microsoft.java.test.plugin.model.TestLevel; import com.microsoft.java.test.plugin.util.JUnitPlugin; @@ -60,7 +61,7 @@ private JUnitLaunchUtils() {} * @throws URISyntaxException * @throws CoreException */ - public static JUnitLaunchArguments resolveLaunchArgument(List arguments, IProgressMonitor monitor) + public static Response resolveLaunchArgument(List arguments, IProgressMonitor monitor) throws URISyntaxException, CoreException { final Gson gson = new Gson(); final Argument args = gson.fromJson((String) arguments.get(0), Argument.class); @@ -109,7 +110,7 @@ public static void addOverrideDependencies(List vmArgs, String dependenc } } - private static JUnitLaunchArguments resolveTestNGLaunchArguments(ILaunchConfiguration configuration, + private static Response resolveTestNGLaunchArguments(ILaunchConfiguration configuration, IJavaProject javaProject, JUnitLaunchConfigurationDelegate delegate) throws CoreException { final IRuntimeClasspathEntry[] unresolved = JavaRuntime.computeUnresolvedRuntimeClasspath(configuration); final IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveRuntimeClasspath(unresolved, configuration); @@ -154,7 +155,7 @@ private static JUnitLaunchArguments resolveTestNGLaunchArguments(ILaunchConfigur addOverrideDependencies(vmArgs, delegate.getModuleCLIOptions(configuration)); launchArguments.vmArguments = vmArgs.toArray(new String[vmArgs.size()]); - return launchArguments; + return new Response<>(launchArguments, null); } /** diff --git a/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/model/Response.java b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/model/Response.java new file mode 100644 index 00000000..0d9037bf --- /dev/null +++ b/java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/model/Response.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2023 Microsoft Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Microsoft Corporation - initial API and implementation + *******************************************************************************/ + +package com.microsoft.java.test.plugin.model; + +public class Response { + + public static final int OK = 0; + public static final int ERROR = 1; + + private T body; + private int status; + private String errorMessage; + + public Response(T body, String errorMessage) { + this.body = body; + if (errorMessage == null) { + this.status = OK; + } else { + this.errorMessage = errorMessage; + this.status = ERROR; + } + } + + public T getBody() { + return body; + } + + public void setBody(T body) { + this.body = body; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/src/controller/testController.ts b/src/controller/testController.ts index 64850e02..81478e67 100644 --- a/src/controller/testController.ts +++ b/src/controller/testController.ts @@ -229,6 +229,9 @@ export const runTests: (request: TestRunRequest, option: IRunOption) => any = in resolvedConfiguration.__progressId = option.progressReporter?.getId(); delegatedToDebugger = true; await runner.run(resolvedConfiguration, token, option.progressReporter); + } catch(error) { + window.showErrorMessage(error.message || 'Failed to run tests.'); + option.progressReporter?.done(); } finally { await runner.tearDown(); } diff --git a/src/runners/baseRunner/BaseRunner.ts b/src/runners/baseRunner/BaseRunner.ts index 191cd8b5..1b8cd699 100644 --- a/src/runners/baseRunner/BaseRunner.ts +++ b/src/runners/baseRunner/BaseRunner.ts @@ -156,3 +156,9 @@ export interface IJUnitLaunchArguments { vmArguments: string[]; programArguments: string[]; } + +export interface Response { + body: T | undefined; + status: number; + errorMessage: string | undefined; +} diff --git a/src/utils/launchUtils.ts b/src/utils/launchUtils.ts index 074e8312..92c94545 100644 --- a/src/utils/launchUtils.ts +++ b/src/utils/launchUtils.ts @@ -9,7 +9,7 @@ import { dataCache } from '../controller/testItemDataCache'; import { extensionContext } from '../extension'; import { IExecutionConfig } from '../runConfigs'; import { BaseRunner } from '../runners/baseRunner/BaseRunner'; -import { IJUnitLaunchArguments } from '../runners/baseRunner/BaseRunner'; +import { IJUnitLaunchArguments, Response } from '../runners/baseRunner/BaseRunner'; import { IRunTestContext, TestKind, TestLevel } from '../types'; import { executeJavaLanguageServerCommand } from './commandUtils'; @@ -121,7 +121,7 @@ function getTestNames(testContext: IRunTestContext): string[] { } async function resolveJUnitLaunchArguments(projectName: string, testLevel: TestLevel, testKind: TestKind, testNames: string[], uniqueId: string | undefined): Promise { - const argument: IJUnitLaunchArguments | undefined = await executeJavaLanguageServerCommand( + const argument: Response | undefined = await executeJavaLanguageServerCommand>( JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({ projectName, testLevel, @@ -131,13 +131,13 @@ async function resolveJUnitLaunchArguments(projectName: string, testLevel: TestL }), ); - if (!argument) { - const error: Error = new Error('Failed to parse the JUnit launch arguments'); + if (!argument?.body || argument.errorMessage) { + const error: Error = new Error(argument?.errorMessage || 'Failed to parse the JUnit launch arguments'); sendError(error); throw error; } - return argument; + return argument.body; } /** diff --git a/test/suite/launchUtils.test.ts b/test/suite/launchUtils.test.ts index b21caa73..b06ca3f4 100644 --- a/test/suite/launchUtils.test.ts +++ b/test/suite/launchUtils.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { JavaTestRunnerDelegateCommands } from "../../src/constants"; -import { IJUnitLaunchArguments } from "../../src/runners/baseRunner/BaseRunner"; +import { IJUnitLaunchArguments, Response } from "../../src/runners/baseRunner/BaseRunner"; import { TestKind, TestLevel } from "../../src/types"; import { executeJavaLanguageServerCommand } from "../../src/utils/commandUtils"; import { setupTestEnv } from "./utils"; @@ -20,7 +20,7 @@ suite('LaunchUtils Tests', () => { }); test('Resolve JUnit 5 parameterized test 1', async () => { - const argument: IJUnitLaunchArguments | undefined = await executeJavaLanguageServerCommand( + const argument: Response | undefined = await executeJavaLanguageServerCommand>( JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({ projectName: 'junit', testLevel: TestLevel.Method, @@ -29,13 +29,13 @@ suite('LaunchUtils Tests', () => { }) ); assert.strictEqual( - argument?.programArguments[argument?.programArguments.length - 1], + argument?.body?.programArguments[argument?.body?.programArguments.length - 1], 'junit5.ParameterizedAnnotationTest:canRunWithComment(java.lang.String,java.lang.Boolean)' ); }); test('Resolve JUnit 5 parameterized test 2', async () => { - const argument: IJUnitLaunchArguments | undefined = await executeJavaLanguageServerCommand( + const argument: Response | undefined = await executeJavaLanguageServerCommand>( JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({ projectName: 'junit', testLevel: TestLevel.Method, @@ -44,13 +44,13 @@ suite('LaunchUtils Tests', () => { }) ); assert.strictEqual( - argument?.programArguments[argument?.programArguments.length - 1], + argument?.body?.programArguments[argument?.body?.programArguments.length - 1], 'junit5.ParameterizedAnnotationTest:equal(int,int)' ); }); test('Resolve JUnit 5 parameterized test 3', async () => { - const argument: IJUnitLaunchArguments | undefined = await executeJavaLanguageServerCommand( + const argument: Response | undefined = await executeJavaLanguageServerCommand>( JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({ projectName: 'junit', testLevel: TestLevel.Method, @@ -59,13 +59,13 @@ suite('LaunchUtils Tests', () => { }) ); assert.strictEqual( - argument?.programArguments[argument?.programArguments.length - 1], + argument?.body?.programArguments[argument?.body?.programArguments.length - 1], 'junit5.ParameterizedAnnotationTest:canRunWithGenericTypedParameter(java.util.List)' ); }); test('Resolve JUnit 5 parameterized test 4', async () => { - const argument: IJUnitLaunchArguments | undefined = await executeJavaLanguageServerCommand( + const argument: Response | undefined = await executeJavaLanguageServerCommand>( JavaTestRunnerDelegateCommands.RESOLVE_JUNIT_ARGUMENT, JSON.stringify({ projectName: 'junit', testLevel: TestLevel.Method, @@ -74,7 +74,7 @@ suite('LaunchUtils Tests', () => { }) ); assert.strictEqual( - argument?.programArguments[argument?.programArguments.length - 1], + argument?.body?.programArguments[argument?.body?.programArguments.length - 1], 'junit5.ParameterizedAnnotationTest:testCheckUser(junit5.ParameterizedAnnotationTest$User)' ); });