11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License.
3- import * as net from 'net' ;
43import * as path from 'path' ;
54import * as fs from 'fs' ;
65import * as os from 'os' ;
76import * as crypto from 'crypto' ;
87import { CancellationToken , Position , TestController , TestItem , Uri , Range , Disposable } from 'vscode' ;
98import { Message } from 'vscode-jsonrpc' ;
109import { traceError , traceInfo , traceLog , traceVerbose } from '../../../logging' ;
11- import { EnableTestAdapterRewrite } from '../../../common/experiments/groups' ;
12- import { IExperimentService } from '../../../common/types' ;
13- import { IServiceContainer } from '../../../ioc/types' ;
1410import { DebugTestTag , ErrorTestItemOptions , RunTestTag } from './testItemUtilities' ;
11+ import { IServiceContainer } from '../../../ioc/types' ;
1512import {
1613 DiscoveredTestItem ,
1714 DiscoveredTestNode ,
@@ -22,6 +19,8 @@ import {
2219import { Deferred , createDeferred } from '../../../common/utils/async' ;
2320import { createNamedPipeServer , generateRandomPipeName } from '../../../common/pipes/namedPipes' ;
2421import { EXTENSION_ROOT_DIR } from '../../../constants' ;
22+ import { IExperimentService } from '../../../common/types' ;
23+ import { EnableTestAdapterRewrite } from '../../../common/experiments/groups' ;
2524
2625export function fixLogLines ( content : string ) : string {
2726 const lines = content . split ( / \r ? \n / g) ;
@@ -117,6 +116,28 @@ export async function writeTestIdsFile(testIds: string[]): Promise<string> {
117116 return tempFileName ;
118117}
119118
119+ export function ExtractJsonRPCData ( payloadLength : string | undefined , rawData : string ) : IJSONRPCData {
120+ /**
121+ * Extracts JSON-RPC content based on provided headers and raw data.
122+ *
123+ * This function uses the `Content-Length` header from the provided headers map
124+ * to determine how much of the rawData string represents the actual JSON content.
125+ * After extracting the expected content, it also returns any remaining data
126+ * that comes after the extracted content as remaining raw data.
127+ *
128+ * @param {string | undefined } payloadLength - The value of the `Content-Length` header.
129+ * @param {string } rawData - The raw string data from which the JSON content will be extracted.
130+ *
131+ * @returns {IJSONRPCContent } An object containing the extracted JSON content and any remaining raw data.
132+ */
133+ const length = parseInt ( payloadLength ?? '0' , 10 ) ;
134+ const data = rawData . slice ( 0 , length ) ;
135+ const remainingRawData = rawData . slice ( length ) ;
136+ return {
137+ extractedJSON : data ,
138+ remainingRawData,
139+ } ;
140+ }
120141export async function startRunResultNamedPipe (
121142 dataReceivedCallback : ( payload : ExecutionTestPayload ) => void ,
122143 deferredTillServerClose : Deferred < void > ,
@@ -168,6 +189,47 @@ interface DiscoveryResultMessage extends Message {
168189 params : DiscoveredTestPayload ;
169190}
170191
192+ export function parseJsonRPCHeadersAndData ( rawData : string ) : ParsedRPCHeadersAndData {
193+ /**
194+ * Parses the provided raw data to extract JSON-RPC specific headers and remaining data.
195+ *
196+ * This function aims to extract specific JSON-RPC headers (like UUID, content length,
197+ * and content type) from the provided raw string data. Headers are expected to be
198+ * delimited by newlines and the format should be "key:value". The function stops parsing
199+ * once it encounters an empty line, and the rest of the data after this line is treated
200+ * as the remaining raw data.
201+ *
202+ * @param {string } rawData - The raw string containing headers and possibly other data.
203+ * @returns {ParsedRPCHeadersAndData } An object containing the parsed headers as a map and the
204+ * remaining raw data after the headers.
205+ */
206+ const lines = rawData . split ( '\n' ) ;
207+ let remainingRawData = '' ;
208+ const headerMap = new Map < string , string > ( ) ;
209+ for ( let i = 0 ; i < lines . length ; i += 1 ) {
210+ const line = lines [ i ] ;
211+ if ( line === '' ) {
212+ remainingRawData = lines . slice ( i + 1 ) . join ( '\n' ) ;
213+ break ;
214+ }
215+ const [ key , value ] = line . split ( ':' ) ;
216+ if ( value && value . trim ( ) ) {
217+ if ( [ JSONRPC_UUID_HEADER , JSONRPC_CONTENT_LENGTH_HEADER , JSONRPC_CONTENT_TYPE_HEADER ] . includes ( key ) ) {
218+ headerMap . set ( key . trim ( ) , value . trim ( ) ) ;
219+ }
220+ }
221+ }
222+
223+ return {
224+ headers : headerMap ,
225+ remainingRawData,
226+ } ;
227+ }
228+ export function pythonTestAdapterRewriteEnabled ( serviceContainer : IServiceContainer ) : boolean {
229+ const experiment = serviceContainer . get < IExperimentService > ( IExperimentService ) ;
230+ return experiment . inExperimentSync ( EnableTestAdapterRewrite . experiment ) ;
231+ }
232+
171233export async function startDiscoveryNamedPipe (
172234 callback : ( payload : DiscoveredTestPayload ) => void ,
173235 cancellationToken ?: CancellationToken ,
0 commit comments