@@ -184,5 +184,85 @@ describe("NativeSshHelper", () => {
184184 expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
185185 expect ( String ( fetchMock . mock . calls [ 0 ] [ 0 ] ) ) . toContain ( "linux-arm-gnueabihf" ) ;
186186 } ) ;
187+
188+ it . each ( [
189+ [ "win32" , "arm64" , "win32-arm64-msvc" ] ,
190+ [ "darwin" , "x64" , "darwin-x64" ] ,
191+ [ "linux" , "x64" , "linux-x64-gnu" ] ,
192+ [ "linux" , "arm64" , "linux-arm64-gnu" ] ,
193+ ] ) ( "should resolve the %s-%s triple (%s) when downloading" , async ( platform , arch , triple ) => {
194+ setPlatform ( platform , arch ) ;
195+ vi . spyOn ( fs , "existsSync" ) . mockReturnValue ( false ) ;
196+ vi . spyOn ( fs , "writeFileSync" ) . mockImplementation ( ( ) => undefined as never ) ;
197+ vi . spyOn ( fs , "mkdirSync" ) . mockImplementation ( ( ) => undefined as never ) ;
198+
199+ handleNativeSshSettings ( fakeContext ) ;
200+ await flush ( ) ;
201+
202+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
203+ expect ( String ( fetchMock . mock . calls [ 0 ] [ 0 ] ) ) . toContain ( triple ) ;
204+ } ) ;
205+
206+ it ( "should warn when the platform is supported but the architecture is not (arch lookup misses)" , async ( ) => {
207+ // Exercises the `NATIVE_TRIPLES[platform]?.[arch]` arch-miss branch (distinct from an
208+ // entirely unknown platform): win32 is known, but "mips" has no entry.
209+ setPlatform ( "win32" , "mips" ) ;
210+ const warnSpy = vi . spyOn ( vscode . window , "showWarningMessage" ) . mockReturnValue ( undefined ) ;
211+ vi . spyOn ( fs , "existsSync" ) . mockReturnValue ( false ) ;
212+
213+ handleNativeSshSettings ( fakeContext ) ;
214+ await flush ( ) ;
215+
216+ expect ( warnSpy ) . toHaveBeenCalledTimes ( 1 ) ;
217+ expect ( String ( warnSpy . mock . calls [ 0 ] [ 0 ] ) ) . toContain ( "No native SSH binary available for win32-mips" ) ;
218+ expect ( fetchMock ) . not . toHaveBeenCalled ( ) ;
219+ } ) ;
220+ } ) ;
221+
222+ describe ( "ensureNativeBinary timeout handling" , ( ) => {
223+ beforeEach ( ( ) => {
224+ mockFlag ( true ) ;
225+ vi . spyOn ( imperative . Logger , "getAppLogger" ) . mockReturnValue ( { info : vi . fn ( ) , error : vi . fn ( ) } as any ) ;
226+ setPlatform ( "darwin" , "arm64" ) ;
227+ vi . spyOn ( fs , "existsSync" ) . mockReturnValue ( false ) ;
228+ vi . spyOn ( fs , "writeFileSync" ) . mockImplementation ( ( ) => undefined as never ) ;
229+ vi . spyOn ( fs , "mkdirSync" ) . mockImplementation ( ( ) => undefined as never ) ;
230+ } ) ;
231+
232+ it ( "should clear the abort timeout after a successful fetch" , async ( ) => {
233+ fetchMock . mockResolvedValue ( { ok : true , status : 200 , arrayBuffer : ( ) => Promise . resolve ( new ArrayBuffer ( 4 ) ) } ) ;
234+ const clearTimeoutSpy = vi . spyOn ( globalThis , "clearTimeout" ) ;
235+
236+ handleNativeSshSettings ( fakeContext ) ;
237+ await flush ( ) ;
238+
239+ // The `finally { clearTimeout(timeoutId) }` arm must run on the success path.
240+ expect ( clearTimeoutSpy ) . toHaveBeenCalled ( ) ;
241+ } ) ;
242+
243+ it ( "should abort the request and surface an error when the timeout elapses" , async ( ) => {
244+ vi . useFakeTimers ( ) ;
245+ try {
246+ const abortSpy = vi . spyOn ( AbortController . prototype , "abort" ) ;
247+ // fetch only settles when its AbortSignal fires, so advancing the timer triggers the reject.
248+ fetchMock . mockImplementation (
249+ ( _url : string , opts : { signal : AbortSignal } ) =>
250+ new Promise ( ( _resolve , reject ) => {
251+ opts . signal . addEventListener ( "abort" , ( ) => reject ( new Error ( "The operation was aborted" ) ) ) ;
252+ } )
253+ ) ;
254+ const errorSpy = vi . spyOn ( vscode . window , "showErrorMessage" ) . mockReturnValue ( undefined ) ;
255+
256+ handleNativeSshSettings ( fakeContext ) ;
257+ // SSH_TIMEOUT is 60_000ms; advancing past it fires the controller.abort() callback.
258+ await vi . advanceTimersByTimeAsync ( 60_000 ) ;
259+
260+ expect ( abortSpy ) . toHaveBeenCalled ( ) ;
261+ expect ( errorSpy ) . toHaveBeenCalledTimes ( 1 ) ;
262+ expect ( String ( errorSpy . mock . calls [ 0 ] [ 0 ] ) ) . toContain ( "Failed to download native SSH binary" ) ;
263+ } finally {
264+ vi . useRealTimers ( ) ;
265+ }
266+ } ) ;
187267 } ) ;
188268} ) ;
0 commit comments