@@ -232,8 +232,31 @@ func TestServer_X11_EvictionLRU(t *testing.T) {
232
232
})
233
233
}
234
234
235
- // Create one more session which should evict the first (LRU) session and
236
- // therefore reuse the very first display/port.
235
+ // Connect X11 forwarding to the first session. This is used to test that
236
+ // connecting counts as a use of the display.
237
+ x11Chans := c .HandleChannelOpen ("x11" )
238
+ payload := "hello world"
239
+ go func () {
240
+ conn , err := inproc .Dial (ctx , testutil .NewAddr ("tcp" , fmt .Sprintf ("localhost:%d" , agentssh .X11StartPort + agentssh .X11DefaultDisplayOffset )))
241
+ assert .NoError (t , err )
242
+ _ , err = conn .Write ([]byte (payload ))
243
+ assert .NoError (t , err )
244
+ _ = conn .Close ()
245
+ }()
246
+
247
+ x11 := testutil .RequireReceive (ctx , t , x11Chans )
248
+ ch , reqs , err := x11 .Accept ()
249
+ require .NoError (t , err )
250
+ go gossh .DiscardRequests (reqs )
251
+ got := make ([]byte , len (payload ))
252
+ _ , err = ch .Read (got )
253
+ require .NoError (t , err )
254
+ assert .Equal (t , payload , string (got ))
255
+ _ = ch .Close ()
256
+
257
+ // Create one more session which should evict a session and reuse the display.
258
+ // The first session was used to connect X11 forwarding, so it should not be evicted.
259
+ // Therefore, the second session should be evicted and its display reused.
237
260
extraSess , err := c .NewSession ()
238
261
require .NoError (t , err )
239
262
@@ -271,17 +294,34 @@ func TestServer_X11_EvictionLRU(t *testing.T) {
271
294
require .NoError (t , sc .Err ())
272
295
}
273
296
274
- // The display number should have wrapped around to the starting value.
275
- assert .Equal (t , agentssh .X11DefaultDisplayOffset , newDisplayNumber , "expected display number to be reused after eviction" )
297
+ // The display number reused should correspond to the SECOND session (display offset 12)
298
+ expectedDisplay := agentssh .X11DefaultDisplayOffset + 2 // +1 was blocked port
299
+ assert .Equal (t , expectedDisplay , newDisplayNumber , "second session should have been evicted and its display reused" )
276
300
277
- // validate that the first session was torn down.
278
- _ , err = sessions [0 ].stdin .Write ([]byte ("echo DISPLAY=$DISPLAY\n " ))
301
+ // First session should still be alive: send cmd and read output.
302
+ msgFirst := "still-alive"
303
+ _ , err = sessions [0 ].stdin .Write ([]byte ("echo " + msgFirst + "\n " ))
304
+ require .NoError (t , err )
305
+ for sessions [0 ].scanner .Scan () {
306
+ line := strings .TrimSpace (sessions [0 ].scanner .Text ())
307
+ if strings .Contains (line , msgFirst ) {
308
+ break
309
+ }
310
+ }
311
+ require .NoError (t , sessions [0 ].scanner .Err ())
312
+
313
+ // Second session should now be closed.
314
+ _ , err = sessions [1 ].stdin .Write ([]byte ("echo dead\n " ))
279
315
require .ErrorIs (t , err , io .EOF )
280
- err = sessions [0 ].sess .Wait ()
316
+ err = sessions [1 ].sess .Wait ()
281
317
require .Error (t , err )
282
318
283
319
// Cleanup.
284
- for _ , sh := range sessions [1 :] {
320
+ for i , sh := range sessions {
321
+ if i == 1 {
322
+ // already closed
323
+ continue
324
+ }
285
325
err = sh .stdin .Close ()
286
326
require .NoError (t , err )
287
327
err = sh .sess .Wait ()
0 commit comments