From f8a4e7d41a3465b0a07906da9bf78d5dc97bbf60 Mon Sep 17 00:00:00 2001 From: Arthurvroum Date: Wed, 8 Apr 2026 06:37:53 +0200 Subject: [PATCH 1/4] test: add command validation and vs code integration tests --- .gitignore | 1 + src/test/command.test.ts | 30 ++++++++++++++++++++++++++++++ src/test/extension.test.ts | 30 ++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 src/test/command.test.ts diff --git a/.gitignore b/.gitignore index 08012c4..614af59 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ ccoretrace-sarif-tscancode.json Thumbs.db # test.vscode-test/ +.vscode-test/ diff --git a/src/test/command.test.ts b/src/test/command.test.ts new file mode 100644 index 0000000..c7bc098 --- /dev/null +++ b/src/test/command.test.ts @@ -0,0 +1,30 @@ +import * as assert from 'assert'; +import { parseAndValidateParams } from '../ctrace/CommandBuilder'; + +suite('CommandBuilder Test Suite', () => { + test('Validates safe parameters correctly', () => { + const result = parseAndValidateParams('--entry-points=main --log-level=debug --all'); + assert.deepStrictEqual(result, ['--entry-points=main', '--log-level=debug', '--all']); + }); + + test('Throws on malicious shell injections', () => { + const maliciousPayloads = [ + '--flag && rm -rf /', + '-I path; ls -la', + '--out=$(whoami)', + '--test `cat /etc/passwd`', + '--option | grep root' + ]; + + for (const payload of maliciousPayloads) { + assert.throws(() => { + parseAndValidateParams(payload); + }, /Unsafe CLI/, `Failed to block payload: ${payload}`); + } + }); + + test('Handles empty or whitespace-only params', () => { + assert.deepStrictEqual(parseAndValidateParams(''), []); + assert.deepStrictEqual(parseAndValidateParams(' '), []); + }); +}); diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 2077b4a..2e433ad 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,9 +1,31 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; -suite('Extension Test Suite', () => { - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); +suite('Extension Activation & Integration Test Suite', () => { + + test('Extension should be present', () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + assert.ok(extension, 'Extension not found. Check the publisher.name in package.json.'); + }); + + test('Extension should activate successfully', async () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + if (extension) { + // Will throw if activation fails (e.g. fs access errors, dependency crashes) + await extension.activate(); + assert.strictEqual(extension.isActive, true, 'Extension failed to switch to active state.'); + } + }); + + test('Extension executes commands without throwing instantly', async () => { + const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); + await extension?.activate(); + + // This will grab all registered commands in vscode + const commands = await vscode.commands.getCommands(true); + + assert.ok(commands.includes('ctrace.runAnalysis'), 'Command ctrace.runAnalysis is missing'); + assert.ok(commands.includes('ctrace.runWorkspaceAnalysis'), 'Command ctrace.runWorkspaceAnalysis is missing'); + assert.ok(commands.includes('ctrace.clearAnalysisCache'), 'Command ctrace.clearAnalysisCache is missing'); }); }); From 01c9f0df3250bb867e5d63d21152546767dda4b0 Mon Sep 17 00:00:00 2001 From: Arthurvroum Date: Wed, 8 Apr 2026 06:45:57 +0200 Subject: [PATCH 2/4] test: assert extension existence and add publish workflow --- .github/workflows/publish.yml | 33 +++++++++++++++++++++++++++++++++ src/test/extension.test.ts | 13 +++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ccd0e16 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,33 @@ +name: Publish to VS Code Marketplace + +on: + push: + tags: + - 'v*' # Se déclenche uniquement quand on pousse un tag, ex: git tag v0.1.1 && git push --tags + +jobs: + publish: + name: Publish Extension + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.x + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run Tests + run: xvfb-run -a npm test + + - name: Publish Pre-release (Beta) + uses: liximomo/vsceaction@v1 + with: + args: publish --pre-release + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 2e433ad..69d0b9b 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -10,16 +10,17 @@ suite('Extension Activation & Integration Test Suite', () => { test('Extension should activate successfully', async () => { const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); - if (extension) { - // Will throw if activation fails (e.g. fs access errors, dependency crashes) - await extension.activate(); - assert.strictEqual(extension.isActive, true, 'Extension failed to switch to active state.'); - } + assert.ok(extension, 'Extension not found. Cannot activate.'); + + // Will throw if activation fails (e.g. fs access errors, dependency crashes) + await extension.activate(); + assert.strictEqual(extension.isActive, true, 'Extension failed to switch to active state.'); }); test('Extension executes commands without throwing instantly', async () => { const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); - await extension?.activate(); + assert.ok(extension, 'Extension not found. Cannot check commands.'); + await extension.activate(); // This will grab all registered commands in vscode const commands = await vscode.commands.getCommands(true); From d0ecc9efa19c9cd40e9640b65329ed546c0a92c6 Mon Sep 17 00:00:00 2001 From: Arthurvroum Date: Wed, 8 Apr 2026 06:46:48 +0200 Subject: [PATCH 3/4] test: rename command registration test to reflect actual assertions --- src/test/extension.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 69d0b9b..65afe6b 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -17,7 +17,7 @@ suite('Extension Activation & Integration Test Suite', () => { assert.strictEqual(extension.isActive, true, 'Extension failed to switch to active state.'); }); - test('Extension executes commands without throwing instantly', async () => { + test('Extension registers all expected commands', async () => { const extension = vscode.extensions.getExtension('CoreTrace.ctrace-audit'); assert.ok(extension, 'Extension not found. Cannot check commands.'); await extension.activate(); From 02898fedb305096031c8569e0c482c74d44aac56 Mon Sep 17 00:00:00 2001 From: Arthurvroum Date: Wed, 8 Apr 2026 06:47:32 +0200 Subject: [PATCH 4/4] test: drop internal flag from getCommands() array for performance and reliability --- src/test/extension.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 65afe6b..c0eb35a 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -23,7 +23,7 @@ suite('Extension Activation & Integration Test Suite', () => { await extension.activate(); // This will grab all registered commands in vscode - const commands = await vscode.commands.getCommands(true); + const commands = await vscode.commands.getCommands(); assert.ok(commands.includes('ctrace.runAnalysis'), 'Command ctrace.runAnalysis is missing'); assert.ok(commands.includes('ctrace.runWorkspaceAnalysis'), 'Command ctrace.runWorkspaceAnalysis is missing');