Skip to content

Commit 4ae46c6

Browse files
CopilothanniavaleraHannia Valera
authored
Add backend tests for critical coverage gaps in expand.ts, proc.ts, and contextKeyExpr.ts (#4852)
* Add backend tests for expand.ts, proc.ts, and contextKeyExpr.ts - expand.test.ts: 23 tests for substituteAll(), getParentEnvSubstitutions(), errorHandlerHelper() - buildCmdStr.test.ts: 16 tests for buildCmdStr() command string construction - contextKeyExpr.test.ts: 69 tests for Parser, evaluation, serialization, and utility functions - All 187 backend tests pass, TypeScript compilation clean Agent-Logs-Url: https://github.com/microsoft/vscode-cmake-tools/sessions/f669e0ca-6ea1-4eae-9eb6-2c78ee6377c9 Co-authored-by: hanniavalera <[email protected]> * Clarify didReplacement test comment per code review feedback Agent-Logs-Url: https://github.com/microsoft/vscode-cmake-tools/sessions/f669e0ca-6ea1-4eae-9eb6-2c78ee6377c9 Co-authored-by: hanniavalera <[email protected]> * no need for changelog as it is mainly tests --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: hanniavalera <[email protected]> Co-authored-by: Hannia Valera <[email protected]>
1 parent 7db0ad4 commit 4ae46c6

3 files changed

Lines changed: 880 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { expect } from 'chai';
2+
3+
/**
4+
* Tests for the buildCmdStr() function from src/proc.ts.
5+
*
6+
* This function constructs a human-readable command string from a command and
7+
* its arguments, quoting any arguments that contain whitespace or special characters.
8+
* It is used for logging executed commands to the output panel.
9+
*
10+
* The function is mirrored here because proc.ts transitively depends on 'vscode',
11+
* which cannot be imported in backend tests.
12+
*/
13+
14+
// --- Mirror of proc.buildCmdStr ---
15+
function buildCmdStr(command: string, args?: string[]): string {
16+
let cmdarr = [command];
17+
if (args) {
18+
cmdarr = cmdarr.concat(args);
19+
}
20+
return cmdarr.map(a => /[ \n\r\f;\t]/.test(a) ? `"${a}"` : a).join(' ');
21+
}
22+
23+
suite('[buildCmdStr]', () => {
24+
25+
test('Command with no arguments', () => {
26+
const result = buildCmdStr('cmake');
27+
expect(result).to.equal('cmake');
28+
});
29+
30+
test('Command with simple arguments', () => {
31+
const result = buildCmdStr('cmake', ['--build', '.', '--target', 'all']);
32+
expect(result).to.equal('cmake --build . --target all');
33+
});
34+
35+
test('Argument with spaces is quoted', () => {
36+
const result = buildCmdStr('cmake', ['-S', '/path with spaces/src']);
37+
expect(result).to.equal('cmake -S "/path with spaces/src"');
38+
});
39+
40+
test('Command itself with spaces is quoted', () => {
41+
const result = buildCmdStr('/Program Files/CMake/bin/cmake', ['--version']);
42+
expect(result).to.equal('"/Program Files/CMake/bin/cmake" --version');
43+
});
44+
45+
test('Argument with tab is quoted', () => {
46+
const result = buildCmdStr('cmake', ['-DVAR=value\twith\ttabs']);
47+
expect(result).to.equal('cmake "-DVAR=value\twith\ttabs"');
48+
});
49+
50+
test('Argument with newline is quoted', () => {
51+
const result = buildCmdStr('cmake', ['-DVAR=line1\nline2']);
52+
expect(result).to.equal('cmake "-DVAR=line1\nline2"');
53+
});
54+
55+
test('Argument with carriage return is quoted', () => {
56+
const result = buildCmdStr('cmake', ['-DVAR=line1\rline2']);
57+
expect(result).to.equal('cmake "-DVAR=line1\rline2"');
58+
});
59+
60+
test('Argument with form feed is quoted', () => {
61+
const result = buildCmdStr('cmake', ['-DVAR=value\fmore']);
62+
expect(result).to.equal('cmake "-DVAR=value\fmore"');
63+
});
64+
65+
test('Argument with semicolon is quoted', () => {
66+
const result = buildCmdStr('cmake', ['-DCMAKE_PREFIX_PATH=/a;/b;/c']);
67+
expect(result).to.equal('cmake "-DCMAKE_PREFIX_PATH=/a;/b;/c"');
68+
});
69+
70+
test('Mixed quoted and unquoted arguments', () => {
71+
const result = buildCmdStr('cmake', ['--build', '/path with space', '--config', 'Release']);
72+
expect(result).to.equal('cmake --build "/path with space" --config Release');
73+
});
74+
75+
test('Empty arguments list', () => {
76+
const result = buildCmdStr('cmake', []);
77+
expect(result).to.equal('cmake');
78+
});
79+
80+
test('Undefined arguments', () => {
81+
const result = buildCmdStr('cmake', undefined);
82+
expect(result).to.equal('cmake');
83+
});
84+
85+
test('Multiple CMake-style define arguments', () => {
86+
const result = buildCmdStr('cmake', [
87+
'-DCMAKE_BUILD_TYPE=Debug',
88+
'-DCMAKE_INSTALL_PREFIX=/usr/local',
89+
'-DBUILD_SHARED_LIBS=ON'
90+
]);
91+
expect(result).to.equal('cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS=ON');
92+
});
93+
94+
test('Windows path with backslashes is not quoted (no special chars)', () => {
95+
const result = buildCmdStr('C:\\CMake\\bin\\cmake.exe', ['--version']);
96+
expect(result).to.equal('C:\\CMake\\bin\\cmake.exe --version');
97+
});
98+
99+
test('Argument that is just a space is quoted', () => {
100+
const result = buildCmdStr('echo', [' ']);
101+
expect(result).to.equal('echo " "');
102+
});
103+
104+
test('Arguments preserving cmake --install pattern', () => {
105+
const result = buildCmdStr('cmake', ['--install', '/build/dir', '--config', 'Release', '--prefix', '/opt/install path']);
106+
expect(result).to.equal('cmake --install /build/dir --config Release --prefix "/opt/install path"');
107+
});
108+
});

0 commit comments

Comments
 (0)