From 044323fe27bc09716572e93fc4607e330bd1a858 Mon Sep 17 00:00:00 2001 From: eleanorjboyd Date: Mon, 9 Dec 2024 13:51:28 -0800 Subject: [PATCH] v2.3 --- src/client/testing/common/runner.ts | 129 ------ src/client/testing/common/types.ts | 5 - src/client/testing/serviceRegistry.ts | 4 - .../common/testItemUtilities.ts | 7 - .../testing/testController/common/utils.ts | 82 ---- .../testing/testController/utils.unit.test.ts | 404 +++++++++--------- 6 files changed, 202 insertions(+), 429 deletions(-) delete mode 100644 src/client/testing/common/runner.ts diff --git a/src/client/testing/common/runner.ts b/src/client/testing/common/runner.ts deleted file mode 100644 index b6e6f2fb3b24..000000000000 --- a/src/client/testing/common/runner.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { inject, injectable } from 'inversify'; -import * as path from 'path'; -import { ErrorUtils } from '../../common/errors/errorUtils'; -import { ModuleNotInstalledError } from '../../common/errors/moduleNotInstalledError'; -import { - IPythonExecutionFactory, - IPythonExecutionService, - IPythonToolExecutionService, - ObservableExecutionResult, - SpawnOptions, -} from '../../common/process/types'; -import { ExecutionInfo, IConfigurationService, IPythonSettings } from '../../common/types'; -import { IServiceContainer } from '../../ioc/types'; -import { TestProvider } from '../types'; -import { PYTEST_PROVIDER, UNITTEST_PROVIDER } from './constants'; -import { ITestRunner, ITestsHelper, Options } from './types'; - -@injectable() -export class TestRunner implements ITestRunner { - constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {} - public run(testProvider: TestProvider, options: Options): Promise { - return run(this.serviceContainer, testProvider, options); - } -} - -async function run(serviceContainer: IServiceContainer, testProvider: TestProvider, options: Options): Promise { - const testExecutablePath = getExecutablePath( - testProvider, - serviceContainer.get(IConfigurationService).getSettings(options.workspaceFolder), - ); - const moduleName = getTestModuleName(testProvider); - const spawnOptions = options as SpawnOptions; - let pythonExecutionServicePromise: Promise | undefined; - spawnOptions.mergeStdOutErr = typeof spawnOptions.mergeStdOutErr === 'boolean' ? spawnOptions.mergeStdOutErr : true; - - let promise: Promise>; - - // Since conda 4.4.0 we have found that running python code needs the environment activated. - // So if running an executable, there's no way we can activate, if its a module, then activate and run the module. - const testHelper = serviceContainer.get(ITestsHelper); - const executionInfo: ExecutionInfo = { - execPath: testExecutablePath, - args: options.args, - moduleName: testExecutablePath && testExecutablePath.length > 0 ? undefined : moduleName, - product: testHelper.parseProduct(testProvider), - }; - - if (testProvider === UNITTEST_PROVIDER) { - promise = serviceContainer - .get(IPythonExecutionFactory) - .createActivatedEnvironment({ resource: options.workspaceFolder }) - .then((executionService) => executionService.execObservable(options.args, { ...spawnOptions })); - } else if (typeof executionInfo.moduleName === 'string' && executionInfo.moduleName.length > 0) { - pythonExecutionServicePromise = serviceContainer - .get(IPythonExecutionFactory) - .createActivatedEnvironment({ resource: options.workspaceFolder }); - promise = pythonExecutionServicePromise.then((executionService) => - executionService.execModuleObservable(executionInfo.moduleName!, executionInfo.args, options), - ); - } else { - const pythonToolsExecutionService = serviceContainer.get( - IPythonToolExecutionService, - ); - promise = pythonToolsExecutionService.execObservable(executionInfo, spawnOptions, options.workspaceFolder); - } - - return promise.then((result) => { - return new Promise((resolve, reject) => { - let stdOut = ''; - let stdErr = ''; - result.out.subscribe( - (output) => { - stdOut += output.out; - // If the test runner python module is not installed we'll have something in stderr. - // Hence track that separately and check at the end. - if (output.source === 'stderr') { - stdErr += output.out; - } - if (options.outChannel) { - options.outChannel.append(output.out); - } - }, - reject, - async () => { - // If the test runner python module is not installed we'll have something in stderr. - if ( - moduleName && - pythonExecutionServicePromise && - ErrorUtils.outputHasModuleNotInstalledError(moduleName, stdErr) - ) { - const pythonExecutionService = await pythonExecutionServicePromise; - const isInstalled = await pythonExecutionService.isModuleInstalled(moduleName); - if (!isInstalled) { - return reject(new ModuleNotInstalledError(moduleName)); - } - } - resolve(stdOut); - }, - ); - }); - }); -} - -function getExecutablePath(testProvider: TestProvider, settings: IPythonSettings): string | undefined { - let testRunnerExecutablePath: string | undefined; - switch (testProvider) { - case PYTEST_PROVIDER: { - testRunnerExecutablePath = settings.testing.pytestPath; - break; - } - default: { - return undefined; - } - } - return path.basename(testRunnerExecutablePath) === testRunnerExecutablePath ? undefined : testRunnerExecutablePath; -} -function getTestModuleName(testProvider: TestProvider) { - switch (testProvider) { - case PYTEST_PROVIDER: { - return 'pytest'; - } - case UNITTEST_PROVIDER: { - return 'unittest'; - } - default: { - throw new Error(`Test provider '${testProvider}' not supported`); - } - } -} diff --git a/src/client/testing/common/types.ts b/src/client/testing/common/types.ts index 78acd632ccd1..8e59a69b78e5 100644 --- a/src/client/testing/common/types.ts +++ b/src/client/testing/common/types.ts @@ -100,8 +100,3 @@ export interface IUnitTestSocketServer extends Disposable { start(options?: { port?: number; host?: string }): Promise; stop(): void; } - -export const ITestRunner = Symbol('ITestRunner'); -export interface ITestRunner { - run(testProvider: TestProvider, options: Options): Promise; -} diff --git a/src/client/testing/serviceRegistry.ts b/src/client/testing/serviceRegistry.ts index 6a7b4b5a1640..0b309c0855b7 100644 --- a/src/client/testing/serviceRegistry.ts +++ b/src/client/testing/serviceRegistry.ts @@ -4,7 +4,6 @@ import { IExtensionActivationService } from '../activation/types'; import { IServiceManager } from '../ioc/types'; import { DebugLauncher } from './common/debugLauncher'; -import { TestRunner } from './common/runner'; import { TestConfigSettingsService } from './common/configSettingService'; import { TestsHelper } from './common/testUtils'; import { @@ -12,7 +11,6 @@ import { ITestConfigurationManagerFactory, ITestConfigurationService, ITestDebugLauncher, - ITestRunner, ITestsHelper, IUnitTestSocketServer, } from './common/types'; @@ -29,8 +27,6 @@ export function registerTypes(serviceManager: IServiceManager) { serviceManager.add(ITestsHelper, TestsHelper); serviceManager.add(IUnitTestSocketServer, UnitTestSocketServer); - serviceManager.add(ITestRunner, TestRunner); - serviceManager.addSingleton(ITestConfigurationService, UnitTestConfigurationService); serviceManager.addSingleton(ITestingService, TestingService); diff --git a/src/client/testing/testController/common/testItemUtilities.ts b/src/client/testing/testController/common/testItemUtilities.ts index 8b8b59051ec4..43624bba2527 100644 --- a/src/client/testing/testController/common/testItemUtilities.ts +++ b/src/client/testing/testController/common/testItemUtilities.ts @@ -498,13 +498,6 @@ export async function updateTestItemFromRawData( item.busy = false; } -export function getUri(node: TestItem): Uri | undefined { - if (!node.uri && node.parent) { - return getUri(node.parent); - } - return node.uri; -} - export function getTestCaseNodes(testNode: TestItem, collection: TestItem[] = []): TestItem[] { if (!testNode.canResolveChildren && testNode.tags.length > 0) { collection.push(testNode); diff --git a/src/client/testing/testController/common/utils.ts b/src/client/testing/testController/common/utils.ts index 496c23a5c9aa..34d09fecb479 100644 --- a/src/client/testing/testController/common/utils.ts +++ b/src/client/testing/testController/common/utils.ts @@ -19,34 +19,12 @@ import { Deferred, createDeferred } from '../../../common/utils/async'; import { createReaderPipe, generateRandomPipeName } from '../../../common/pipes/namedPipes'; import { EXTENSION_ROOT_DIR } from '../../../constants'; -export function fixLogLines(content: string): string { - const lines = content.split(/\r?\n/g); - return `${lines.join('\r\n')}\r\n`; -} export function fixLogLinesNoTrailing(content: string): string { const lines = content.split(/\r?\n/g); return `${lines.join('\r\n')}`; } -export interface IJSONRPCData { - extractedJSON: string; - remainingRawData: string; -} - -export interface ParsedRPCHeadersAndData { - headers: Map; - remainingRawData: string; -} -export interface ExtractOutput { - uuid: string | undefined; - cleanedJsonData: string | undefined; - remainingRawData: string; -} - -export const JSONRPC_UUID_HEADER = 'Request-uuid'; -export const JSONRPC_CONTENT_LENGTH_HEADER = 'Content-Length'; -export const JSONRPC_CONTENT_TYPE_HEADER = 'Content-Type'; export const MESSAGE_ON_TESTING_OUTPUT_MOVE = 'Starting now, all test run output will be sent to the Test Result panel,' + ' while test discovery output will be sent to the "Python" output channel instead of the "Python Test Log" channel.' + @@ -58,66 +36,6 @@ export function createTestingDeferred(): Deferred { } -export function parseJsonRPCHeadersAndData(rawData: string): ParsedRPCHeadersAndData { - /** - * Parses the provided raw data to extract JSON-RPC specific headers and remaining data. - * - * This function aims to extract specific JSON-RPC headers (like UUID, content length, - * and content type) from the provided raw string data. Headers are expected to be - * delimited by newlines and the format should be "key:value". The function stops parsing - * once it encounters an empty line, and the rest of the data after this line is treated - * as the remaining raw data. - * - * @param {string} rawData - The raw string containing headers and possibly other data. - * @returns {ParsedRPCHeadersAndData} An object containing the parsed headers as a map and the - * remaining raw data after the headers. - */ - const lines = rawData.split('\n'); - let remainingRawData = ''; - const headerMap = new Map(); - for (let i = 0; i < lines.length; i += 1) { - const line = lines[i]; - if (line === '') { - remainingRawData = lines.slice(i + 1).join('\n'); - break; - } - const [key, value] = line.split(':'); - if (value && value.trim()) { - if ([JSONRPC_UUID_HEADER, JSONRPC_CONTENT_LENGTH_HEADER, JSONRPC_CONTENT_TYPE_HEADER].includes(key)) { - headerMap.set(key.trim(), value.trim()); - } - } - } - - return { - headers: headerMap, - remainingRawData, - }; -} - -export function ExtractJsonRPCData(payloadLength: string | undefined, rawData: string): IJSONRPCData { - /** - * Extracts JSON-RPC content based on provided headers and raw data. - * - * This function uses the `Content-Length` header from the provided headers map - * to determine how much of the rawData string represents the actual JSON content. - * After extracting the expected content, it also returns any remaining data - * that comes after the extracted content as remaining raw data. - * - * @param {string | undefined} payloadLength - The value of the `Content-Length` header. - * @param {string} rawData - The raw string data from which the JSON content will be extracted. - * - * @returns {IJSONRPCContent} An object containing the extracted JSON content and any remaining raw data. - */ - const length = parseInt(payloadLength ?? '0', 10); - const data = rawData.slice(0, length); - const remainingRawData = rawData.slice(length); - return { - extractedJSON: data, - remainingRawData, - }; -} - interface ExecutionResultMessage extends Message { params: ExecutionTestPayload; } diff --git a/src/test/testing/testController/utils.unit.test.ts b/src/test/testing/testController/utils.unit.test.ts index dbf8b8249b9c..b871d18348e2 100644 --- a/src/test/testing/testController/utils.unit.test.ts +++ b/src/test/testing/testController/utils.unit.test.ts @@ -1,202 +1,202 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import * as assert from 'assert'; -import { - JSONRPC_CONTENT_LENGTH_HEADER, - JSONRPC_CONTENT_TYPE_HEADER, - JSONRPC_UUID_HEADER, - ExtractJsonRPCData, - parseJsonRPCHeadersAndData, - splitTestNameWithRegex, - argKeyExists, - addValueIfKeyNotExist, -} from '../../../client/testing/testController/common/utils'; - -suite('Test Controller Utils: JSON RPC', () => { - test('Empty raw data string', async () => { - const rawDataString = ''; - - const output = parseJsonRPCHeadersAndData(rawDataString); - assert.deepStrictEqual(output.headers.size, 0); - assert.deepStrictEqual(output.remainingRawData, ''); - }); - - test('Valid data empty JSON', async () => { - const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: 2\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n{}`; - - const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); - assert.deepStrictEqual(rpcHeaders.headers.size, 3); - assert.deepStrictEqual(rpcHeaders.remainingRawData, '{}'); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, '{}'); - }); - - test('Valid data NO JSON', async () => { - const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: 0\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n`; - - const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); - assert.deepStrictEqual(rpcHeaders.headers.size, 3); - assert.deepStrictEqual(rpcHeaders.remainingRawData, ''); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, ''); - }); - - test('Valid data with full JSON', async () => { - // this is just some random JSON - const json = - '{"jsonrpc": "2.0", "method": "initialize", "params": {"processId": 1234, "rootPath": "/home/user/project", "rootUri": "file:///home/user/project", "capabilities": {}}, "id": 0}'; - const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: ${json.length}\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n${json}`; - - const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); - assert.deepStrictEqual(rpcHeaders.headers.size, 3); - assert.deepStrictEqual(rpcHeaders.remainingRawData, json); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, json); - }); - - test('Valid data with multiple JSON', async () => { - const json = - '{"jsonrpc": "2.0", "method": "initialize", "params": {"processId": 1234, "rootPath": "/home/user/project", "rootUri": "file:///home/user/project", "capabilities": {}}, "id": 0}'; - const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: ${json.length}\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n${json}`; - const rawDataString2 = rawDataString + rawDataString; - - const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString2); - assert.deepStrictEqual(rpcHeaders.headers.size, 3); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, json); - assert.deepStrictEqual(rpcContent.remainingRawData, rawDataString); - }); - - test('Valid constant', async () => { - const data = `{"cwd": "/Users/eleanorboyd/testingFiles/inc_dec_example", "status": "success", "result": {"test_dup_class.test_a.TestSomething.test_a": {"test": "test_dup_class.test_a.TestSomething.test_a", "outcome": "success", "message": "None", "traceback": null, "subtest": null}}}`; - const secondPayload = `Content-Length: 270 -Content-Type: application/json -Request-uuid: 496c86b1-608f-4886-9436-ec00538e144c - -${data}`; - const payload = `Content-Length: 270 -Content-Type: application/json -Request-uuid: 496c86b1-608f-4886-9436-ec00538e144c - -${data}${secondPayload}`; - - const rpcHeaders = parseJsonRPCHeadersAndData(payload); - assert.deepStrictEqual(rpcHeaders.headers.size, 3); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, data); - assert.deepStrictEqual(rpcContent.remainingRawData, secondPayload); - }); - test('Valid content length as only header with carriage return', async () => { - const payload = `Content-Length: 7 - `; - - const rpcHeaders = parseJsonRPCHeadersAndData(payload); - assert.deepStrictEqual(rpcHeaders.headers.size, 1); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, ''); - assert.deepStrictEqual(rpcContent.remainingRawData, ''); - }); - test('Valid content length header with no value', async () => { - const payload = `Content-Length:`; - - const rpcHeaders = parseJsonRPCHeadersAndData(payload); - const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); - assert.deepStrictEqual(rpcContent.extractedJSON, ''); - assert.deepStrictEqual(rpcContent.remainingRawData, ''); - }); - - suite('Test Controller Utils: Other', () => { - interface TestCase { - name: string; - input: string; - expectedParent: string; - expectedSubtest: string; - } - - const testCases: Array = [ - { - name: 'Single parameter, named', - input: 'test_package.ClassName.test_method (param=value)', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '(param=value)', - }, - { - name: 'Single parameter, unnamed', - input: 'test_package.ClassName.test_method [value]', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '[value]', - }, - { - name: 'Multiple parameters, named', - input: 'test_package.ClassName.test_method (param1=value1, param2=value2)', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '(param1=value1, param2=value2)', - }, - { - name: 'Multiple parameters, unnamed', - input: 'test_package.ClassName.test_method [value1, value2]', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '[value1, value2]', - }, - { - name: 'Names with special characters', - input: 'test_package.ClassName.test_method (param1=value/1, param2=value+2)', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '(param1=value/1, param2=value+2)', - }, - { - name: 'Names with spaces', - input: 'test_package.ClassName.test_method ["a b c d"]', - expectedParent: 'test_package.ClassName.test_method', - expectedSubtest: '["a b c d"]', - }, - ]; - - testCases.forEach((testCase) => { - test(`splitTestNameWithRegex: ${testCase.name}`, () => { - const splitResult = splitTestNameWithRegex(testCase.input); - assert.deepStrictEqual(splitResult, [testCase.expectedParent, testCase.expectedSubtest]); - }); - }); - }); - suite('Test Controller Utils: Args Mapping', () => { - suite('addValueIfKeyNotExist', () => { - test('should add key-value pair if key does not exist', () => { - const args = ['key1=value1', 'key2=value2']; - const result = addValueIfKeyNotExist(args, 'key3', 'value3'); - assert.deepEqual(result, ['key1=value1', 'key2=value2', 'key3=value3']); - }); - - test('should not add key-value pair if key already exists', () => { - const args = ['key1=value1', 'key2=value2']; - const result = addValueIfKeyNotExist(args, 'key1', 'value3'); - assert.deepEqual(result, ['key1=value1', 'key2=value2']); - }); - test('should not add key-value pair if key exists as a solo element', () => { - const args = ['key1=value1', 'key2']; - const result = addValueIfKeyNotExist(args, 'key2', 'yellow'); - assert.deepEqual(result, ['key1=value1', 'key2']); - }); - test('add just key if value is null', () => { - const args = ['key1=value1', 'key2']; - const result = addValueIfKeyNotExist(args, 'key3', null); - assert.deepEqual(result, ['key1=value1', 'key2', 'key3']); - }); - }); - - suite('argKeyExists', () => { - test('should return true if key exists', () => { - const args = ['key1=value1', 'key2=value2']; - const result = argKeyExists(args, 'key1'); - assert.deepEqual(result, true); - }); - - test('should return false if key does not exist', () => { - const args = ['key1=value1', 'key2=value2']; - const result = argKeyExists(args, 'key3'); - assert.deepEqual(result, false); - }); - }); - }); -}); +// // Copyright (c) Microsoft Corporation. All rights reserved. +// // Licensed under the MIT License. + +// import * as assert from 'assert'; +// import { +// JSONRPC_CONTENT_LENGTH_HEADER, +// JSONRPC_CONTENT_TYPE_HEADER, +// JSONRPC_UUID_HEADER, +// ExtractJsonRPCData, +// parseJsonRPCHeadersAndData, +// splitTestNameWithRegex, +// argKeyExists, +// addValueIfKeyNotExist, +// } from '../../../client/testing/testController/common/utils'; + +// suite('Test Controller Utils: JSON RPC', () => { +// test('Empty raw data string', async () => { +// const rawDataString = ''; + +// const output = parseJsonRPCHeadersAndData(rawDataString); +// assert.deepStrictEqual(output.headers.size, 0); +// assert.deepStrictEqual(output.remainingRawData, ''); +// }); + +// test('Valid data empty JSON', async () => { +// const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: 2\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n{}`; + +// const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); +// assert.deepStrictEqual(rpcHeaders.headers.size, 3); +// assert.deepStrictEqual(rpcHeaders.remainingRawData, '{}'); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, '{}'); +// }); + +// test('Valid data NO JSON', async () => { +// const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: 0\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n`; + +// const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); +// assert.deepStrictEqual(rpcHeaders.headers.size, 3); +// assert.deepStrictEqual(rpcHeaders.remainingRawData, ''); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, ''); +// }); + +// test('Valid data with full JSON', async () => { +// // this is just some random JSON +// const json = +// '{"jsonrpc": "2.0", "method": "initialize", "params": {"processId": 1234, "rootPath": "/home/user/project", "rootUri": "file:///home/user/project", "capabilities": {}}, "id": 0}'; +// const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: ${json.length}\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n${json}`; + +// const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString); +// assert.deepStrictEqual(rpcHeaders.headers.size, 3); +// assert.deepStrictEqual(rpcHeaders.remainingRawData, json); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, json); +// }); + +// test('Valid data with multiple JSON', async () => { +// const json = +// '{"jsonrpc": "2.0", "method": "initialize", "params": {"processId": 1234, "rootPath": "/home/user/project", "rootUri": "file:///home/user/project", "capabilities": {}}, "id": 0}'; +// const rawDataString = `${JSONRPC_CONTENT_LENGTH_HEADER}: ${json.length}\n${JSONRPC_CONTENT_TYPE_HEADER}: application/json\n${JSONRPC_UUID_HEADER}: 1234\n\n${json}`; +// const rawDataString2 = rawDataString + rawDataString; + +// const rpcHeaders = parseJsonRPCHeadersAndData(rawDataString2); +// assert.deepStrictEqual(rpcHeaders.headers.size, 3); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, json); +// assert.deepStrictEqual(rpcContent.remainingRawData, rawDataString); +// }); + +// test('Valid constant', async () => { +// const data = `{"cwd": "/Users/eleanorboyd/testingFiles/inc_dec_example", "status": "success", "result": {"test_dup_class.test_a.TestSomething.test_a": {"test": "test_dup_class.test_a.TestSomething.test_a", "outcome": "success", "message": "None", "traceback": null, "subtest": null}}}`; +// const secondPayload = `Content-Length: 270 +// Content-Type: application/json +// Request-uuid: 496c86b1-608f-4886-9436-ec00538e144c + +// ${data}`; +// const payload = `Content-Length: 270 +// Content-Type: application/json +// Request-uuid: 496c86b1-608f-4886-9436-ec00538e144c + +// ${data}${secondPayload}`; + +// const rpcHeaders = parseJsonRPCHeadersAndData(payload); +// assert.deepStrictEqual(rpcHeaders.headers.size, 3); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, data); +// assert.deepStrictEqual(rpcContent.remainingRawData, secondPayload); +// }); +// test('Valid content length as only header with carriage return', async () => { +// const payload = `Content-Length: 7 +// `; + +// const rpcHeaders = parseJsonRPCHeadersAndData(payload); +// assert.deepStrictEqual(rpcHeaders.headers.size, 1); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, ''); +// assert.deepStrictEqual(rpcContent.remainingRawData, ''); +// }); +// test('Valid content length header with no value', async () => { +// const payload = `Content-Length:`; + +// const rpcHeaders = parseJsonRPCHeadersAndData(payload); +// const rpcContent = ExtractJsonRPCData(rpcHeaders.headers.get('Content-Length'), rpcHeaders.remainingRawData); +// assert.deepStrictEqual(rpcContent.extractedJSON, ''); +// assert.deepStrictEqual(rpcContent.remainingRawData, ''); +// }); + +// suite('Test Controller Utils: Other', () => { +// interface TestCase { +// name: string; +// input: string; +// expectedParent: string; +// expectedSubtest: string; +// } + +// const testCases: Array = [ +// { +// name: 'Single parameter, named', +// input: 'test_package.ClassName.test_method (param=value)', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '(param=value)', +// }, +// { +// name: 'Single parameter, unnamed', +// input: 'test_package.ClassName.test_method [value]', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '[value]', +// }, +// { +// name: 'Multiple parameters, named', +// input: 'test_package.ClassName.test_method (param1=value1, param2=value2)', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '(param1=value1, param2=value2)', +// }, +// { +// name: 'Multiple parameters, unnamed', +// input: 'test_package.ClassName.test_method [value1, value2]', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '[value1, value2]', +// }, +// { +// name: 'Names with special characters', +// input: 'test_package.ClassName.test_method (param1=value/1, param2=value+2)', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '(param1=value/1, param2=value+2)', +// }, +// { +// name: 'Names with spaces', +// input: 'test_package.ClassName.test_method ["a b c d"]', +// expectedParent: 'test_package.ClassName.test_method', +// expectedSubtest: '["a b c d"]', +// }, +// ]; + +// testCases.forEach((testCase) => { +// test(`splitTestNameWithRegex: ${testCase.name}`, () => { +// const splitResult = splitTestNameWithRegex(testCase.input); +// assert.deepStrictEqual(splitResult, [testCase.expectedParent, testCase.expectedSubtest]); +// }); +// }); +// }); +// suite('Test Controller Utils: Args Mapping', () => { +// suite('addValueIfKeyNotExist', () => { +// test('should add key-value pair if key does not exist', () => { +// const args = ['key1=value1', 'key2=value2']; +// const result = addValueIfKeyNotExist(args, 'key3', 'value3'); +// assert.deepEqual(result, ['key1=value1', 'key2=value2', 'key3=value3']); +// }); + +// test('should not add key-value pair if key already exists', () => { +// const args = ['key1=value1', 'key2=value2']; +// const result = addValueIfKeyNotExist(args, 'key1', 'value3'); +// assert.deepEqual(result, ['key1=value1', 'key2=value2']); +// }); +// test('should not add key-value pair if key exists as a solo element', () => { +// const args = ['key1=value1', 'key2']; +// const result = addValueIfKeyNotExist(args, 'key2', 'yellow'); +// assert.deepEqual(result, ['key1=value1', 'key2']); +// }); +// test('add just key if value is null', () => { +// const args = ['key1=value1', 'key2']; +// const result = addValueIfKeyNotExist(args, 'key3', null); +// assert.deepEqual(result, ['key1=value1', 'key2', 'key3']); +// }); +// }); + +// suite('argKeyExists', () => { +// test('should return true if key exists', () => { +// const args = ['key1=value1', 'key2=value2']; +// const result = argKeyExists(args, 'key1'); +// assert.deepEqual(result, true); +// }); + +// test('should return false if key does not exist', () => { +// const args = ['key1=value1', 'key2=value2']; +// const result = argKeyExists(args, 'key3'); +// assert.deepEqual(result, false); +// }); +// }); +// }); +// });