feat - Set which encoding your test JVM will start with (#1735)

* Set which encoding your test JVM will start with

This patch adds a setting to the `java.test.config` object.

```jsonc
{
  "java.test.config": {
    "encoding": "ISO-8859-1",
  },
}
```
The aim here is to be able to seamlessly test code which cares
about the launch encoding of the JVM. Yes, such code is not good.
But sometimes you don't control your dependencies enough to fix
this.

Since the debug launcher already cares about the `encoding` member of the
config, the only thing required is to add the member, which is missing
from the launch configs generated by the test plugin.

```typescript
// In `configurationProvider.ts:` (vscode-java-debug)
// VS Code internal console uses UTF-8 to display output by default.
if (config.console === "internalConsole" && !config.encoding) {
    config.encoding = "UTF-8";
}
```

Fixes #1641

---------

Co-authored-by: Sheng Chen <sheche@microsoft.com>
Co-authored-by: Adrian Wilkins <adrian.wilkins.contractor@dvla.gov.uk>
This commit is contained in:
Adrian Wilkins 2024-10-21 02:54:33 +01:00 коммит произвёл GitHub
Родитель d00d92a6d3
Коммит 2612b25e39
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 113 добавлений и 56 удалений

Просмотреть файл

@ -55,18 +55,18 @@
"main": "./main.js",
"contributes": {
"javaExtensions": [
"./server/junit-jupiter-api_5.10.3.jar",
"./server/junit-jupiter-engine_5.10.3.jar",
"./server/junit-jupiter-migrationsupport_5.10.3.jar",
"./server/junit-jupiter-params_5.10.3.jar",
"./server/junit-platform-commons_1.10.3.jar",
"./server/junit-platform-engine_1.10.3.jar",
"./server/junit-platform-launcher_1.10.3.jar",
"./server/junit-platform-runner_1.10.3.jar",
"./server/junit-platform-suite-api_1.10.3.jar",
"./server/junit-platform-suite-commons_1.10.3.jar",
"./server/junit-platform-suite-engine_1.10.3.jar",
"./server/junit-vintage-engine_5.10.3.jar",
"./server/junit-jupiter-api_5.11.0.jar",
"./server/junit-jupiter-engine_5.11.0.jar",
"./server/junit-jupiter-migrationsupport_5.11.0.jar",
"./server/junit-jupiter-params_5.11.0.jar",
"./server/junit-platform-commons_1.11.0.jar",
"./server/junit-platform-engine_1.11.0.jar",
"./server/junit-platform-launcher_1.11.0.jar",
"./server/junit-platform-runner_1.11.0.jar",
"./server/junit-platform-suite-api_1.11.0.jar",
"./server/junit-platform-suite-commons_1.11.0.jar",
"./server/junit-platform-suite-engine_1.11.0.jar",
"./server/junit-vintage-engine_5.11.0.jar",
"./server/org.apiguardian.api_1.1.2.jar",
"./server/org.eclipse.jdt.junit4.runtime_1.3.100.v20231214-1952.jar",
"./server/org.eclipse.jdt.junit5.runtime_1.1.300.v20231214-1952.jar",
@ -254,6 +254,11 @@
"markdownDescription": "%configuration.java.test.config.javaExec.description%",
"default": ""
},
"encoding": {
"type": "string",
"description": "%configuration.java.test.config.encoding.description%",
"default": ""
},
"vmArgs": {
"type": "array",
"items": {
@ -409,7 +414,12 @@
"markdownDescription": "%configuration.java.test.config.javaExec.description%",
"default": ""
},
"vmargs": {
"encoding": {
"type": "string",
"description": "%configuration.java.test.config.encoding.description%",
"default": ""
},
"vmArgs": {
"type": "array",
"items": {
"type": "string"

Просмотреть файл

@ -21,6 +21,7 @@
"configuration.java.test.config.modulePaths.runtime.description": "The modulepaths within 'runtime' scope of current project.",
"configuration.java.test.config.modulePaths.test.description": "The modulepaths within 'test' scope of current project.",
"configuration.java.test.config.modulePaths.exclude.description": "The path after '!' will be excluded from the modulePaths.",
"configuration.java.test.config.encoding.description": "The 'file.encoding' setting for the test JVM. Only set this if you have to test code that relies on the default encoding being something other than UTF-8.",
"configuration.java.test.config.vmArgs.description": "Specify the extra options and system properties for the JVM.",
"configuration.java.test.config.args.description": "Specify the command line arguments which will be passed to the test runner.",
"configuration.java.test.config.env.description": "Specify the extra environment variables when running the tests.",

Просмотреть файл

@ -279,6 +279,12 @@ export interface IExecutionConfig {
*/
javaExec?: string;
/**
* the default encoding the JVM will start with. If undefined, this will be UTF-8.
* @since 0.43.0
*/
encoding?: string;
/**
* the extra options and system properties for the JVM.
* @since 0.14.0
@ -353,4 +359,4 @@ export interface IExecutionConfig {
* @since 0.41.0
*/
when?: string
}
}

Просмотреть файл

@ -18,68 +18,51 @@ export async function resolveLaunchConfigurationForRunner(runner: BaseRunner, te
if (config && config.vmArgs) {
launchArguments.vmArguments.push(...config.vmArgs.filter(Boolean));
} else if (config && (config as any).vmargs) { // to support the deprecated property name.
launchArguments.vmArguments.push(...(config as any).vmargs.filter(Boolean));
sendInfo('', {'deprecatedPropertyUsed': 'vmargs'});
}
let debugConfiguration: DebugConfiguration;
let debugConfiguration: DebugConfiguration = {
name: `Launch Java Tests - ${testContext.testItems[0].label}`,
type: 'java',
request: 'launch',
projectName: launchArguments.projectName,
cwd: config && config.workingDirectory ? config.workingDirectory : launchArguments.workingDirectory,
modulePaths: [
...config?.modulePaths || [],
...launchArguments.modulepath || [],
],
encoding: config?.encoding,
vmArgs: launchArguments.vmArguments,
env: config?.env,
envFile: config?.envFile,
noDebug: !testContext.isDebug,
sourcePaths: config?.sourcePaths,
preLaunchTask: config?.preLaunchTask,
postDebugTask: config?.postDebugTask,
javaExec: config?.javaExec,
};
if (testContext.kind === TestKind.TestNG) {
debugConfiguration = {
name: `Launch Java Tests - ${testContext.testItems[0].label}`,
type: 'java',
request: 'launch',
debugConfiguration = Object.assign(debugConfiguration, {
mainClass: 'com.microsoft.java.test.runner.Launcher',
projectName: launchArguments.projectName,
cwd: config && config.workingDirectory ? config.workingDirectory : launchArguments.workingDirectory,
classPaths: [
...config?.classPaths || [],
...launchArguments.classpath || [],
path.join(extensionContext.extensionPath, 'server', 'com.microsoft.java.test.runner-jar-with-dependencies.jar'),
],
modulePaths: [
...config?.modulePaths || [],
...launchArguments.modulepath || [],
],
args: runner.getApplicationArgs(config),
vmArgs: launchArguments.vmArguments,
env: config?.env,
envFile: config?.envFile,
noDebug: !testContext.isDebug,
sourcePaths: config?.sourcePaths,
preLaunchTask: config?.preLaunchTask,
postDebugTask: config?.postDebugTask,
javaExec: config?.javaExec,
};
});
} else {
debugConfiguration = {
name: `Launch Java Tests - ${testContext.testItems[0].label}`,
type: 'java',
request: 'launch',
debugConfiguration = Object.assign(debugConfiguration, {
mainClass: launchArguments.mainClass,
projectName: launchArguments.projectName,
cwd: config && config.workingDirectory ? config.workingDirectory : launchArguments.workingDirectory,
classPaths: [
...config?.classPaths || [],
...launchArguments.classpath || [],
],
modulePaths: [
...config?.modulePaths || [],
...launchArguments.modulepath || [],
],
args: [
...launchArguments.programArguments,
...(testContext.kind === TestKind.JUnit5 ? parseTags(config) : [])
],
vmArgs: launchArguments.vmArguments,
env: config?.env,
envFile: config?.envFile,
noDebug: !testContext.isDebug,
sourcePaths: config?.sourcePaths,
preLaunchTask: config?.preLaunchTask,
postDebugTask: config?.postDebugTask,
javaExec: config?.javaExec,
};
});
}
if (testContext.profile?.kind === TestRunProfileKind.Coverage) {

Просмотреть файл

@ -4,6 +4,7 @@
'use strict';
import * as assert from 'assert';
import { TestController, TestRunRequest, tests, workspace } from 'vscode';
import { JUnitRunner } from '../../src/runners/junitRunner/JunitRunner';
import { resolveLaunchConfigurationForRunner } from '../../src/utils/launchUtils';
@ -70,4 +71,40 @@ suite('JUnit Runner Analyzer Tests', () => {
assert.strictEqual(configuration.classPaths[1], "/foo/bar.jar");
assert.strictEqual(configuration.javaExec, "/usr/bin/java");
});
test("test launch encoding", async() => {
const testItem = generateTestItem(testController, 'junit@junit4.TestEncoding#latin1IsSet', TestKind.JUnit, undefined, '=junit/src\\/test\\/java=/optional=/true=/=/maven.pomderived=/true=/=/test=/true=/<junit4{TestAnnotation.java[TestEncoding~latin1IsSet');
const testRunRequest = new TestRunRequest([testItem], []);
const testRun = testController.createTestRun(testRunRequest);
const runnerContext: IRunTestContext = {
isDebug: false,
kind: TestKind.JUnit,
projectName: 'junit',
testItems: [testItem],
testRun: testRun,
workspaceFolder: workspace.workspaceFolders?.[0]!,
};
const junitRunner = new JUnitRunner(runnerContext);
const configuration = await resolveLaunchConfigurationForRunner(junitRunner, runnerContext, {
classPaths: [
"/a/b/c.jar",
"/foo/bar.jar"
],
env: {
test: "test",
},
envFile: "${workspaceFolder}/.env",
encoding: "ISO-8859-1",
javaExec: "/usr/bin/java",
modulePaths: [
"/test/module.jar",
],
postDebugTask: "test",
preLaunchTask: "test",
sourcePaths: [
"/a/b/c.jar"
]
});
assert.strictEqual(configuration.encoding, "ISO-8859-1");
});
});

Просмотреть файл

@ -0,0 +1,20 @@
package junit4;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import java.nio.charset.Charset;
/**
* The test case in this class will fail unless you set `java.test.config : encoding` to ISO-8859-1
*/
public class TestEncoding {
@Test
public void latin1IsSet() {
assertEquals(
"ISO-8859-1",
Charset.defaultCharset().name()
);
}
}