test(daemon): cover datagram output window coalescing
- commit
- 11057325a9035cf8dbf457e442282307542375e7
- author
- brice · · 2026-07-10 11:07 UTC
- parent
- e25b377
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +37 -0
M internal/usecase/daemon/output_state_sync_test.go +37 -0
| @@ -268,3 +268,40 @@ func TestFailedPaintSendRollsBackOutputState(t *testing.T) { | |||
| 268 | 268 | require.Zero(t, ac.output.next) | |
| 269 | 269 | require.Zero(t, ac.output.acked) | |
| 270 | 270 | } | |
| 271 | + | ||
| 272 | + | func TestDatagramWindowOneCoalescesPaintsUntilMsgAck(t *testing.T) { | |
| 273 | + | p, releasePTY := newBlockingPTY(t) | |
| 274 | + | defer releasePTY() | |
| 275 | + | d, sess, _, _ := newManualSessionWithPTYs(t, p) | |
| 276 | + | tr := newDatagramTestTransport() | |
| 277 | + | _, ac, err := d.route(ports.Hello{ | |
| 278 | + | Version: ports.ProtocolVersion, | |
| 279 | + | Intent: ports.IntentAttach, | |
| 280 | + | Name: sess.name, | |
| 281 | + | Size: domain.Size{Cols: 80, Rows: 24}, | |
| 282 | + | MaxOutputInFlight: 1, | |
| 283 | + | }, tr) | |
| 284 | + | require.NoError(t, err) | |
| 285 | + | ||
| 286 | + | pane := sess.tabs[0].focusedPane() | |
| 287 | + | pane.screen.Write([]byte("A")) | |
| 288 | + | d.paint(sess, ac, false) | |
| 289 | + | first := awaitFrame(t, tr.sends, ports.MsgOutput) | |
| 290 | + | firstOutput, err := ports.UnmarshalOutput(first.Payload) | |
| 291 | + | require.NoError(t, err) | |
| 292 | + | require.Equal(t, uint64(1), firstOutput.NewStateNum) | |
| 293 | + | for range 100 { | |
| 294 | + | pane.screen.Write([]byte("x")) | |
| 295 | + | d.paint(sess, ac, false) | |
| 296 | + | } | |
| 297 | + | requireNoOutputFrame(t, tr.sends) | |
| 298 | + | ||
| 299 | + | tr.recv <- ports.Frame{Type: ports.MsgAck, Payload: ports.MarshalAck(ports.Ack{AckedStateNum: firstOutput.NewStateNum})} | |
| 300 | + | require.NoError(t, tr.Close()) | |
| 301 | + | d.runConnLoop(ac) | |
| 302 | + | second := awaitFrame(t, tr.sends, ports.MsgOutput) | |
| 303 | + | secondOutput, err := ports.UnmarshalOutput(second.Payload) | |
| 304 | + | require.NoError(t, err) | |
| 305 | + | require.Equal(t, firstOutput.NewStateNum, secondOutput.BaseStateNum) | |
| 306 | + | require.Equal(t, uint64(2), secondOutput.NewStateNum) | |
| 307 | + | } | |
| @@ -268,3 +268,40 @@ func TestFailedPaintSendRollsBackOutputState(t *testing.T) { | |||||
| 268 | require.Zero(t, ac.output.next) | 268 | require.Zero(t, ac.output.next) | ||
| 269 | require.Zero(t, ac.output.acked) | 269 | require.Zero(t, ac.output.acked) | ||
| 270 | } | 270 | } | ||
| 271 | + | ||||
| 272 | + | func TestDatagramWindowOneCoalescesPaintsUntilMsgAck(t *testing.T) { | |||
| 273 | + | p, releasePTY := newBlockingPTY(t) | |||
| 274 | + | defer releasePTY() | |||
| 275 | + | d, sess, _, _ := newManualSessionWithPTYs(t, p) | |||
| 276 | + | tr := newDatagramTestTransport() | |||
| 277 | + | _, ac, err := d.route(ports.Hello{ | |||
| 278 | + | Version: ports.ProtocolVersion, | |||
| 279 | + | Intent: ports.IntentAttach, | |||
| 280 | + | Name: sess.name, | |||
| 281 | + | Size: domain.Size{Cols: 80, Rows: 24}, | |||
| 282 | + | MaxOutputInFlight: 1, | |||
| 283 | + | }, tr) | |||
| 284 | + | require.NoError(t, err) | |||
| 285 | + | ||||
| 286 | + | pane := sess.tabs[0].focusedPane() | |||
| 287 | + | pane.screen.Write([]byte("A")) | |||
| 288 | + | d.paint(sess, ac, false) | |||
| 289 | + | first := awaitFrame(t, tr.sends, ports.MsgOutput) | |||
| 290 | + | firstOutput, err := ports.UnmarshalOutput(first.Payload) | |||
| 291 | + | require.NoError(t, err) | |||
| 292 | + | require.Equal(t, uint64(1), firstOutput.NewStateNum) | |||
| 293 | + | for range 100 { | |||
| 294 | + | pane.screen.Write([]byte("x")) | |||
| 295 | + | d.paint(sess, ac, false) | |||
| 296 | + | } | |||
| 297 | + | requireNoOutputFrame(t, tr.sends) | |||
| 298 | + | ||||
| 299 | + | tr.recv <- ports.Frame{Type: ports.MsgAck, Payload: ports.MarshalAck(ports.Ack{AckedStateNum: firstOutput.NewStateNum})} | |||
| 300 | + | require.NoError(t, tr.Close()) | |||
| 301 | + | d.runConnLoop(ac) | |||
| 302 | + | second := awaitFrame(t, tr.sends, ports.MsgOutput) | |||
| 303 | + | secondOutput, err := ports.UnmarshalOutput(second.Payload) | |||
| 304 | + | require.NoError(t, err) | |||
| 305 | + | require.Equal(t, firstOutput.NewStateNum, secondOutput.BaseStateNum) | |||
| 306 | + | require.Equal(t, uint64(2), secondOutput.NewStateNum) | |||
| 307 | + | } | |||