test(vt): cover ECH row damage
- commit
- bc06f3f2793f898db7dba800b18c81f964b347ab
- author
- brice · · 2026-08-03 07:46 UTC
- parent
- a6c1ffe
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +15 -9
M pkg/vt/screen_csi_test.go +15 -9
| @@ -614,6 +614,7 @@ func TestEraseCharacters(t *testing.T) { | |||
| 614 | 614 | tests := []struct { | |
| 615 | 615 | name string | |
| 616 | 616 | width int | |
| 617 | + | row int | |
| 617 | 618 | initial string | |
| 618 | 619 | seq string | |
| 619 | 620 | wantRow string | |
| @@ -623,38 +624,42 @@ func TestEraseCharacters(t *testing.T) { | |||
| 623 | 624 | { | |
| 624 | 625 | name: "explicit count", | |
| 625 | 626 | width: 50, | |
| 627 | + | row: 1, | |
| 626 | 628 | initial: ` // scroll-method "on-button-down"`, | |
| 627 | - | seq: "\x1b[1;19Hbutton 273\x1b[13X", | |
| 629 | + | seq: "\x1b[19Gbutton 273\x1b[13X", | |
| 628 | 630 | wantRow: " // scroll-button 273", | |
| 629 | 631 | wantCol: 28, | |
| 630 | 632 | wantDamage: []renderer.Damage{ | |
| 631 | - | {Kind: renderer.DamageText, X: 18, Y: 0, Width: 10, Height: 1, Count: 1}, | |
| 632 | - | {Kind: renderer.DamageClear, X: 28, Y: 0, Width: 13, Height: 1, Count: 1}, | |
| 633 | + | {Kind: renderer.DamageText, X: 18, Y: 1, Width: 10, Height: 1, Count: 1}, | |
| 634 | + | {Kind: renderer.DamageClear, X: 28, Y: 1, Width: 13, Height: 1, Count: 1}, | |
| 633 | 635 | }, | |
| 634 | 636 | }, | |
| 635 | 637 | { | |
| 636 | 638 | name: "omitted count erases exactly one cell", | |
| 637 | 639 | width: 6, | |
| 640 | + | row: 1, | |
| 638 | 641 | initial: "abcdef", | |
| 639 | - | seq: "\x1b[1;3H\x1b[X", | |
| 642 | + | seq: "\x1b[3G\x1b[X", | |
| 640 | 643 | wantRow: "ab def", | |
| 641 | 644 | wantCol: 2, | |
| 642 | - | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 2, Y: 0, Width: 1, Height: 1, Count: 1}}, | |
| 645 | + | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 2, Y: 1, Width: 1, Height: 1, Count: 1}}, | |
| 643 | 646 | }, | |
| 644 | 647 | { | |
| 645 | 648 | name: "maximum count clips to screen edge", | |
| 646 | 649 | width: 6, | |
| 650 | + | row: 1, | |
| 647 | 651 | initial: "abcdef", | |
| 648 | - | seq: "\x1b[1;4H\x1b[" + maxInt + "X", | |
| 652 | + | seq: "\x1b[4G\x1b[" + maxInt + "X", | |
| 649 | 653 | wantRow: "abc", | |
| 650 | 654 | wantCol: 3, | |
| 651 | - | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 3, Y: 0, Width: 3, Height: 1, Count: 1}}, | |
| 655 | + | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 3, Y: 1, Width: 3, Height: 1, Count: 1}}, | |
| 652 | 656 | }, | |
| 653 | 657 | } | |
| 654 | 658 | ||
| 655 | 659 | for _, tt := range tests { | |
| 656 | 660 | t.Run(tt.name, func(t *testing.T) { | |
| 657 | - | s := NewScreen(tt.width, 1) | |
| 661 | + | s := NewScreen(tt.width, 2) | |
| 662 | + | s.Write([]byte("\x1b[2;1H")) | |
| 658 | 663 | s.Write([]byte(tt.initial)) | |
| 659 | 664 | s.ClearDamage() | |
| 660 | 665 | s.Write([]byte(tt.seq)) | |
| @@ -664,8 +669,9 @@ func TestEraseCharacters(t *testing.T) { | |||
| 664 | 669 | if x < len(tt.wantRow) { | |
| 665 | 670 | want = rune(tt.wantRow[x]) | |
| 666 | 671 | } | |
| 667 | - | require.Equal(t, want, cellAt(s, x, 0).Rune, "cell(%d,0)", x) | |
| 672 | + | require.Equal(t, want, cellAt(s, x, tt.row).Rune, "cell(%d,%d)", x, tt.row) | |
| 668 | 673 | } | |
| 674 | + | require.Equal(t, tt.row, s.Row) | |
| 669 | 675 | require.Equal(t, tt.wantCol, s.Col) | |
| 670 | 676 | require.Equal(t, tt.wantDamage, s.Damage()) | |
| 671 | 677 | }) | |
| @@ -614,6 +614,7 @@ func TestEraseCharacters(t *testing.T) { | |||||
| 614 | tests := []struct { | 614 | tests := []struct { | ||
| 615 | name string | 615 | name string | ||
| 616 | width int | 616 | width int | ||
| 617 | + | row int | |||
| 617 | initial string | 618 | initial string | ||
| 618 | seq string | 619 | seq string | ||
| 619 | wantRow string | 620 | wantRow string | ||
| @@ -623,38 +624,42 @@ func TestEraseCharacters(t *testing.T) { | |||||
| 623 | { | 624 | { | ||
| 624 | name: "explicit count", | 625 | name: "explicit count", | ||
| 625 | width: 50, | 626 | width: 50, | ||
| 627 | + | row: 1, | |||
| 626 | initial: ` // scroll-method "on-button-down"`, | 628 | initial: ` // scroll-method "on-button-down"`, | ||
| 627 | - | seq: "\x1b[1;19Hbutton 273\x1b[13X", | 629 | + | seq: "\x1b[19Gbutton 273\x1b[13X", |
| 628 | wantRow: " // scroll-button 273", | 630 | wantRow: " // scroll-button 273", | ||
| 629 | wantCol: 28, | 631 | wantCol: 28, | ||
| 630 | wantDamage: []renderer.Damage{ | 632 | wantDamage: []renderer.Damage{ | ||
| 631 | - | {Kind: renderer.DamageText, X: 18, Y: 0, Width: 10, Height: 1, Count: 1}, | 633 | + | {Kind: renderer.DamageText, X: 18, Y: 1, Width: 10, Height: 1, Count: 1}, |
| 632 | - | {Kind: renderer.DamageClear, X: 28, Y: 0, Width: 13, Height: 1, Count: 1}, | 634 | + | {Kind: renderer.DamageClear, X: 28, Y: 1, Width: 13, Height: 1, Count: 1}, |
| 633 | }, | 635 | }, | ||
| 634 | }, | 636 | }, | ||
| 635 | { | 637 | { | ||
| 636 | name: "omitted count erases exactly one cell", | 638 | name: "omitted count erases exactly one cell", | ||
| 637 | width: 6, | 639 | width: 6, | ||
| 640 | + | row: 1, | |||
| 638 | initial: "abcdef", | 641 | initial: "abcdef", | ||
| 639 | - | seq: "\x1b[1;3H\x1b[X", | 642 | + | seq: "\x1b[3G\x1b[X", |
| 640 | wantRow: "ab def", | 643 | wantRow: "ab def", | ||
| 641 | wantCol: 2, | 644 | wantCol: 2, | ||
| 642 | - | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 2, Y: 0, Width: 1, Height: 1, Count: 1}}, | 645 | + | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 2, Y: 1, Width: 1, Height: 1, Count: 1}}, |
| 643 | }, | 646 | }, | ||
| 644 | { | 647 | { | ||
| 645 | name: "maximum count clips to screen edge", | 648 | name: "maximum count clips to screen edge", | ||
| 646 | width: 6, | 649 | width: 6, | ||
| 650 | + | row: 1, | |||
| 647 | initial: "abcdef", | 651 | initial: "abcdef", | ||
| 648 | - | seq: "\x1b[1;4H\x1b[" + maxInt + "X", | 652 | + | seq: "\x1b[4G\x1b[" + maxInt + "X", |
| 649 | wantRow: "abc", | 653 | wantRow: "abc", | ||
| 650 | wantCol: 3, | 654 | wantCol: 3, | ||
| 651 | - | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 3, Y: 0, Width: 3, Height: 1, Count: 1}}, | 655 | + | wantDamage: []renderer.Damage{{Kind: renderer.DamageClear, X: 3, Y: 1, Width: 3, Height: 1, Count: 1}}, |
| 652 | }, | 656 | }, | ||
| 653 | } | 657 | } | ||
| 654 | 658 | ||||
| 655 | for _, tt := range tests { | 659 | for _, tt := range tests { | ||
| 656 | t.Run(tt.name, func(t *testing.T) { | 660 | t.Run(tt.name, func(t *testing.T) { | ||
| 657 | - | s := NewScreen(tt.width, 1) | 661 | + | s := NewScreen(tt.width, 2) |
| 662 | + | s.Write([]byte("\x1b[2;1H")) | |||
| 658 | s.Write([]byte(tt.initial)) | 663 | s.Write([]byte(tt.initial)) | ||
| 659 | s.ClearDamage() | 664 | s.ClearDamage() | ||
| 660 | s.Write([]byte(tt.seq)) | 665 | s.Write([]byte(tt.seq)) | ||
| @@ -664,8 +669,9 @@ func TestEraseCharacters(t *testing.T) { | |||||
| 664 | if x < len(tt.wantRow) { | 669 | if x < len(tt.wantRow) { | ||
| 665 | want = rune(tt.wantRow[x]) | 670 | want = rune(tt.wantRow[x]) | ||
| 666 | } | 671 | } | ||
| 667 | - | require.Equal(t, want, cellAt(s, x, 0).Rune, "cell(%d,0)", x) | 672 | + | require.Equal(t, want, cellAt(s, x, tt.row).Rune, "cell(%d,%d)", x, tt.row) |
| 668 | } | 673 | } | ||
| 674 | + | require.Equal(t, tt.row, s.Row) | |||
| 669 | require.Equal(t, tt.wantCol, s.Col) | 675 | require.Equal(t, tt.wantCol, s.Col) | ||
| 670 | require.Equal(t, tt.wantDamage, s.Damage()) | 676 | require.Equal(t, tt.wantDamage, s.Damage()) | ||
| 671 | }) | 677 | }) | ||