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