@@ -6,7 +6,7 @@ import { IExtensionContext } from '../../extension/common/types';
66import { registerNoConfigDebug as registerNoConfigDebug } from '../../extension/noConfigDebugInit' ;
77import * as TypeMoq from 'typemoq' ;
88import * as sinon from 'sinon' ;
9- import { DebugConfiguration , DebugSessionOptions , RelativePattern , Uri , workspace } from 'vscode' ;
9+ import { DebugConfiguration , DebugSessionOptions , RelativePattern , Uri , env , workspace } from 'vscode' ;
1010import * as utils from '../../extension/utils' ;
1111import { assert } from 'console' ;
1212import * as fs from 'fs' ;
@@ -22,6 +22,9 @@ suite('setup for no-config debug scenario', function () {
2222 let DEBUGPY_ADAPTER_ENDPOINTS = 'DEBUGPY_ADAPTER_ENDPOINTS' ;
2323 let BUNDLED_DEBUGPY_PATH = 'BUNDLED_DEBUGPY_PATH' ;
2424 let workspaceUriStub : sinon . SinonStub ;
25+ let sessionIdStub : sinon . SinonStub ;
26+ let stableWorkspaceHash : string ;
27+ let workspacePath : string ;
2528
2629 const testDataDir = path . join ( __dirname , 'testData' ) ;
2730 const testFilePath = path . join ( testDataDir , 'debuggerAdapterEndpoint.txt' ) ;
@@ -34,19 +37,28 @@ suite('setup for no-config debug scenario', function () {
3437 noConfigScriptsDir = path . join ( context . object . extensionPath , 'bundled/scripts/noConfigScripts' ) ;
3538 bundledDebugPath = path . join ( context . object . extensionPath , 'bundled/libs/debugpy' ) ;
3639
40+ sessionIdStub = sinon . stub ( env , 'sessionId' ) . value ( 'test-session' ) ;
41+ workspacePath = os . tmpdir ( ) ;
42+
3743 // Stub crypto.randomBytes with proper typing
3844 let randomBytesStub = sinon . stub ( crypto , 'randomBytes' ) ;
3945 // Provide a valid Buffer object
4046 randomBytesStub . callsFake ( ( _size : number ) => Buffer . from ( '1234567899' , 'hex' ) ) ;
4147
42- workspaceUriStub = sinon . stub ( workspace , 'workspaceFolders' ) . value ( [ { uri : Uri . parse ( os . tmpdir ( ) ) } ] ) ;
48+ workspaceUriStub = sinon . stub ( workspace , 'workspaceFolders' ) . value ( [ { uri : Uri . parse ( workspacePath ) } ] ) ;
49+
50+ const hash = crypto . createHash ( 'sha256' ) ;
51+ hash . update ( workspacePath . toString ( ) ) ;
52+ hash . update ( 'test-session' ) ;
53+ stableWorkspaceHash = hash . digest ( 'hex' ) . slice ( 0 , 16 ) ;
4354 } catch ( error ) {
4455 console . error ( 'Error in setup:' , error ) ;
4556 }
4657 } ) ;
4758 teardown ( ( ) => {
4859 sinon . restore ( ) ;
4960 workspaceUriStub . restore ( ) ;
61+ sessionIdStub . restore ( ) ;
5062 } ) ;
5163
5264 test ( 'should add environment variables for DEBUGPY_ADAPTER_ENDPOINTS, BUNDLED_DEBUGPY_PATH, and PATH' , async ( ) => {
@@ -59,7 +71,10 @@ suite('setup for no-config debug scenario', function () {
5971 . setup ( ( x ) => x . replace ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) )
6072 . callback ( ( key , value ) => {
6173 if ( key === DEBUGPY_ADAPTER_ENDPOINTS ) {
62- assert ( value . includes ( 'endpoint-' ) ) ;
74+ assert (
75+ value ===
76+ path . join ( context . object . extensionPath , '.noConfigDebugAdapterEndpoints' , stableWorkspaceHash ) ,
77+ ) ;
6378 } else if ( key === BUNDLED_DEBUGPY_PATH ) {
6479 assert ( value === bundledDebugPath ) ;
6580 } else if ( key === 'PYDEVD_DISABLE_FILE_VALIDATION' ) {
@@ -194,7 +209,7 @@ suite('setup for no-config debug scenario', function () {
194209 // Assert
195210 sinon . assert . calledOnce ( createFileSystemWatcherFunct ) ;
196211 const expectedPattern = new RelativePattern (
197- path . join ( os . tmpdir ( ) , '.noConfigDebugAdapterEndpoints' ) ,
212+ path . join ( os . tmpdir ( ) , '.noConfigDebugAdapterEndpoints' , stableWorkspaceHash ) ,
198213 '**/*.txt' ,
199214 ) ;
200215 sinon . assert . calledWith ( createFileSystemWatcherFunct , expectedPattern ) ;
@@ -261,26 +276,33 @@ suite('setup for no-config debug scenario', function () {
261276 sinon . assert . calledWith ( debugStub , undefined , expectedConfig , optionsExpected ) ;
262277 } ) ;
263278
264- test ( 'should check if tempFilePath exists when debuggerAdapterEndpointFolder exists' , async ( ) => {
279+ test ( 'should clear existing endpoint files when debuggerAdapterEndpointFolder exists' , async ( ) => {
265280 // Arrange
266281 const environmentVariableCollectionMock = TypeMoq . Mock . ofType < any > ( ) ;
267282 context . setup ( ( c ) => c . environmentVariableCollection ) . returns ( ( ) => environmentVariableCollectionMock . object ) ;
268283
269- const fsExistsSyncStub = sinon . stub ( fs , 'existsSync' ) . returns ( true ) ;
284+ const endpointFolderPath = path . join ( os . tmpdir ( ) , '.noConfigDebugAdapterEndpoints' , stableWorkspaceHash ) ;
285+ const fsExistsSyncStub = sinon . stub ( fs , 'existsSync' ) . callsFake ( ( p ) => p === endpointFolderPath ) ;
286+ const fakeDirent = { isFile : ( ) => true , name : Buffer . from ( 'old.txt' ) } as unknown as fs . Dirent < Buffer > ;
287+ const fsReaddirSyncStub = sinon
288+ . stub ( fs , 'readdirSync' )
289+ . callsFake ( ( dirPath : fs . PathLike , options ?: any ) => {
290+ assert ( dirPath === endpointFolderPath ) ;
291+ assert ( options ?. withFileTypes === true ) ;
292+ return [ fakeDirent ] as unknown as fs . Dirent < Buffer > [ ] ;
293+ } ) ;
270294 const fsUnlinkSyncStub = sinon . stub ( fs , 'unlinkSync' ) ;
271295
272296 // Act
273297 await registerNoConfigDebug ( context . object . environmentVariableCollection , context . object . extensionPath ) ;
274298
275299 // Assert
276- sinon . assert . calledWith (
277- fsExistsSyncStub ,
278- sinon . match ( ( value : any ) => value . includes ( 'endpoint-' ) ) ,
279- ) ;
280- sinon . assert . calledOnce ( fsUnlinkSyncStub ) ;
300+ sinon . assert . calledWith ( fsExistsSyncStub , endpointFolderPath ) ;
301+ sinon . assert . calledWith ( fsUnlinkSyncStub , path . join ( endpointFolderPath , 'old.txt' ) ) ;
281302
282303 // Cleanup
283304 fsExistsSyncStub . restore ( ) ;
305+ fsReaddirSyncStub . restore ( ) ;
284306 fsUnlinkSyncStub . restore ( ) ;
285307 } ) ;
286308} ) ;
0 commit comments