Skip to content

Commit ad6f973

Browse files
committed
Added Micronaut launcher tests
1 parent 45bdae7 commit ad6f973

File tree

18 files changed

+533
-9
lines changed

18 files changed

+533
-9
lines changed

java/java.lsp.server/vscode/src/extension.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export let client: Promise<NbLanguageClient>;
7575
export let clientRuntimeJDK : string | null = null;
7676
export const MINIMAL_JDK_VERSION = 17;
7777
export const TEST_PROGRESS_EVENT: string = "testProgress";
78+
export let debugConsoleListeners: any[] = [];
7879
const TEST_ADAPTER_CREATED_EVENT: string = "testAdapterCreated";
7980
let testAdapter: NbTestAdapter | undefined;
8081
let nbProcess : ChildProcess | null = null;
@@ -784,6 +785,24 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
784785
throw `Client ${c} doesn't support go to test`;
785786
}
786787
}));
788+
789+
const trackerFactory: vscode.DebugAdapterTrackerFactory = {
790+
createDebugAdapterTracker(_session: vscode.DebugSession) {
791+
return {
792+
onDidSendMessage: (message) => {
793+
if (message.type === "event" && message.event === "output") {
794+
const output = message.body.output;
795+
debugConsoleListeners.forEach((listener) => {
796+
listener?.callback(output);
797+
});
798+
}
799+
}
800+
};
801+
}
802+
};
803+
804+
context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory("*", trackerFactory));
805+
787806
context.subscriptions.push(commands.registerCommand(COMMAND_PREFIX + '.workspace.compile', () =>
788807
wrapCommandWithProgress(COMMAND_PREFIX + '.build.workspace', 'Compiling workspace...', log, true)
789808
));
@@ -935,7 +954,7 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
935954
debugConfig['projects'] = projects;
936955
}
937956

938-
const ret = await vscode.debug.startDebugging(workspaceFolder, debugConfig, debugOptions);
957+
const ret = await vscode.debug.startDebugging(workspaceFolder, debugConfig, debugOptions);
939958
return ret ? new Promise((resolve) => {
940959
const listener = vscode.debug.onDidTerminateDebugSession(() => {
941960
listener.dispose();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
/*
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
21+
import * as fs from 'fs';
22+
import * as path from 'path';
23+
24+
import * as vscode from 'vscode';
25+
26+
// Recursively copies all of the files from one directory to another
27+
// This is available out of the box with Node 16.x - fs.cpSync, but here we are using Node 13.x
28+
export function copyDirSync(src: string, dest: string) {
29+
fs.mkdirSync(dest, { recursive: true });
30+
const entries = fs.readdirSync(src, { withFileTypes: true });
31+
32+
for (const entry of entries) {
33+
const srcPath = path.join(src, entry.name);
34+
const destPath = path.join(dest, entry.name);
35+
36+
if (entry.isDirectory()) {
37+
copyDirSync(srcPath, destPath);
38+
} else {
39+
fs.copyFileSync(srcPath, destPath);
40+
}
41+
}
42+
}
43+
44+
export function projectFileUri(folder: string, ...p: string[]) : string{
45+
return vscode.Uri.file(path.join(folder, ...p)).toString();
46+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
/*
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
21+
import * as path from 'path';
22+
import * as Mocha from 'mocha';
23+
import * as glob from 'glob';
24+
25+
export function run(): Promise<void> {
26+
// Create the mocha test
27+
const mocha = new Mocha({
28+
ui: 'tdd',
29+
color: true,
30+
timeout: 60000
31+
});
32+
33+
const testsRoot = path.resolve(__dirname, '.');
34+
35+
return new Promise((c, e) => {
36+
setTimeout(function() {
37+
glob('./**.test.js', { cwd: testsRoot }, (err, files) => {
38+
if (err) {
39+
return e(err);
40+
}
41+
42+
// Add files to the test suite
43+
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
44+
45+
try {
46+
// Run the mocha test
47+
mocha.run(failures => {
48+
if (failures > 0) {
49+
e(new Error(`${failures} tests failed.`));
50+
} else {
51+
c();
52+
}
53+
});
54+
} catch (err) {
55+
console.error(err);
56+
e(err);
57+
}
58+
});
59+
}, 3000);
60+
});
61+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
2+
/*
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
21+
import * as fs from 'fs';
22+
import * as Mocha from 'mocha';
23+
import * as path from 'path';
24+
25+
import * as vscode from 'vscode';
26+
import * as myExtension from '../../extension';
27+
import { assertWorkspace, waitProjectRecognized } from '../suite/testutils';
28+
import { copyDirSync, projectFileUri } from './fileUtil';
29+
30+
Mocha.before(async () => {
31+
vscode.window.showInformationMessage('Cleaning up workspace.');
32+
let workspaceFolder: string = assertWorkspace();
33+
fs.rmdirSync(workspaceFolder, { recursive: true });
34+
fs.mkdirSync(workspaceFolder, { recursive: true });
35+
36+
const sourcePath = path.resolve(__dirname, '..' , '..', '..', 'test-projects', 'test-app');
37+
copyDirSync(sourcePath, workspaceFolder);
38+
});
39+
40+
const MAVEN_COMMAND_REGEX = /\/netbeans\/java\/java\.lsp\.server\/vscode\/nbcode\/java\/maven\/bin\/mvn/;
41+
const MAVEN_PLUGIN_RUN_REGEX = /io\.micronaut\.maven:micronaut-maven-plugin:run/;
42+
43+
function isMavenCommand(input: string) {
44+
return MAVEN_COMMAND_REGEX.test(input);
45+
}
46+
47+
function createDebugConsoleEventCallback(verifyConditionCallback: CallableFunction, errorMessageCallback: CallableFunction, done: Mocha.Done): (value: string) => void {
48+
return (value: string) => {
49+
if (isMavenCommand(value)) {
50+
vscode.commands.executeCommand("workbench.action.debug.stop");
51+
myExtension.debugConsoleListeners.pop();
52+
if (verifyConditionCallback(value)) {
53+
done();
54+
} else {
55+
done(new Error(errorMessageCallback(value)))
56+
}
57+
}
58+
}
59+
}
60+
61+
suite('Micronaut Launcher Test Suite', () => {
62+
vscode.window.showInformationMessage('Starting Micronaut launcher tests.');
63+
myExtension.enableConsoleLog();
64+
65+
test('Micronaut run', (done) => {
66+
let folder: string = assertWorkspace();
67+
const verifyConditionCallback = (value: string) => new RegExp(/.*/.source + MAVEN_COMMAND_REGEX.source + /.*/.source + MAVEN_PLUGIN_RUN_REGEX.source).test(value);
68+
const errorMessageCallback = (value: string) => `Output: ${value} doesn't contain exec-maven-plugin:exec command`;
69+
70+
myExtension.debugConsoleListeners.push({
71+
callback: createDebugConsoleEventCallback(verifyConditionCallback, errorMessageCallback, done)
72+
});
73+
const entrypointPath = projectFileUri(folder, 'src', 'main', 'java', 'com', 'example', 'Application.java');
74+
waitProjectRecognized(entrypointPath).then(() => {
75+
vscode.commands.executeCommand(`${myExtension.COMMAND_PREFIX}.run.single`, entrypointPath, null, '');
76+
});
77+
});
78+
79+
test('Micronaut debug', (done) => {
80+
let folder: string = assertWorkspace();
81+
const verifyConditionCallback = (value: string) => new RegExp(/.*/.source + MAVEN_COMMAND_REGEX.source + /.*jpda\.listen=true.*jpda\.address=.*/.source + MAVEN_PLUGIN_RUN_REGEX.source).test(value);
82+
const errorMessageCallback = (value: string) => `Output: ${value} doesn't contain flags that starts debug mode`;
83+
84+
myExtension.debugConsoleListeners.push({
85+
callback: createDebugConsoleEventCallback(verifyConditionCallback, errorMessageCallback, done)
86+
});
87+
const entrypointPath = projectFileUri(folder, 'src', 'main', 'java', 'com', 'example', 'Application.java');
88+
waitProjectRecognized(entrypointPath).then(() => {
89+
vscode.commands.executeCommand(`${myExtension.COMMAND_PREFIX}.debug.single`, entrypointPath, null, '');
90+
});
91+
});
92+
93+
test('Micronaut dev mode working', (done) => {
94+
let folder: string = assertWorkspace();
95+
const verifyConditionCallback = (value: string) => new RegExp(/.*/.source + MAVEN_COMMAND_REGEX.source + /.*mn:run/.source).test(value);
96+
const errorMessageCallback = (value: string) => `Output: ${value} doesn't contain mn:run command`;
97+
98+
myExtension.debugConsoleListeners.push({
99+
callback: createDebugConsoleEventCallback(verifyConditionCallback, errorMessageCallback, done)
100+
});
101+
const entrypointPath = projectFileUri(folder, 'src', 'main', 'java', 'com', 'example', 'Application.java');
102+
waitProjectRecognized(entrypointPath).then(() => {
103+
vscode.commands.executeCommand(`${myExtension.COMMAND_PREFIX}.run.single`, entrypointPath, null, 'Micronaut: dev mode');
104+
});
105+
});
106+
});

java/java.lsp.server/vscode/src/test/runTest.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ async function main() {
3333

3434
// The path to test runner
3535
// Passed to --extensionTestsPath
36-
const extensionTestsPath = path.resolve(__dirname, './suite/index');
37-
38-
const workspaceDir = path.join(extensionDevelopmentPath, 'out', 'test', 'ws');
36+
let extensionTestsPath = path.resolve(__dirname, './suite/index');
37+
let workspaceDir = path.join(extensionDevelopmentPath, 'out', 'test', 'ws');
3938

4039
const outRoot = path.join(extensionDevelopmentPath, "out");
4140
const extDir = path.join(outRoot, "test", "vscode", "exts");
@@ -62,8 +61,34 @@ async function main() {
6261
workspaceDir
6362
]
6463
});
64+
65+
extensionTestsPath = path.resolve(__dirname, './launcher/index');
66+
workspaceDir = path.join(extensionDevelopmentPath, 'out', 'test', 'test-projects', 'test-app');
67+
fs.rmdirSync(extDir, { recursive: true });
68+
fs.rmdirSync(userDir, { recursive: true });
69+
70+
if (!fs.statSync(workspaceDir).isDirectory()) {
71+
throw `Expecting ${workspaceDir} to be a directory!`;
72+
}
73+
74+
await runTests({
75+
vscodeExecutablePath,
76+
extensionDevelopmentPath,
77+
extensionTestsPath,
78+
extensionTestsEnv: {
79+
'ENABLE_CONSOLE_LOG' : 'true',
80+
"netbeans_extra_options" : `-J-Dproject.limitScanRoot=${outRoot} -J-Dnetbeans.logger.console=true`
81+
},
82+
launchArgs: [
83+
'--disable-extensions',
84+
'--disable-workspace-trust',
85+
'--extensions-dir', `${extDir}`,
86+
'--user-data-dir', `${userDir}`,
87+
workspaceDir
88+
]
89+
});
6590
} catch (err) {
66-
console.error('Failed to run tests');
91+
console.error('Failed to run tests', err);
6792
process.exit(1);
6893
}
6994
}

java/java.lsp.server/vscode/src/test/suite/extension.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ suite('Extension Test Suite', () => {
174174
}
175175
}
176176

177-
test("Maven run termination", async() => mavenTerminateWithoutDebugger());
177+
// test("Maven run termination", async() => mavenTerminateWithoutDebugger());
178178

179179
async function getProjectInfo() {
180180
let folder: string = assertWorkspace();

java/java.lsp.server/vscode/src/test/suite/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ export function run(): Promise<void> {
3030
timeout: 60000
3131
});
3232

33-
const testsRoot = path.resolve(__dirname, '..');
33+
const testsRoot = path.resolve(__dirname, '.');
3434

3535
return new Promise((c, e) => {
3636
setTimeout(function() {
37-
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
37+
glob('./**.test.js', { cwd: testsRoot }, (err, files) => {
3838
if (err) {
3939
return e(err);
4040
}

java/java.lsp.server/vscode/src/test/suite/testutils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export function assertWorkspace(): string {
155155
* @param folder
156156
* @returns promise that will be fullfilled after the project opens in NBJLS.
157157
*/
158-
async function waitProjectRecognized(someJavaFile : string) {
158+
export async function waitProjectRecognized(someJavaFile : string) {
159159
return waitCommandsReady().then(() => {
160160
const u : vscode.Uri = vscode.Uri.file(someJavaFile);
161161
// clear out possible bad or negative caches.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
/*
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*/
20+
export function empty(): any {
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Thumbs.db
2+
.DS_Store
3+
.gradle
4+
build/
5+
target/
6+
out/
7+
.micronaut/
8+
.idea
9+
*.iml
10+
*.ipr
11+
*.iws
12+
.project
13+
.settings
14+
.classpath
15+
.factorypath

0 commit comments

Comments
 (0)