284 lines
6.2 KiB
Go
284 lines
6.2 KiB
Go
package syntax
|
|
|
|
import "testing"
|
|
|
|
func TestMergeRanges(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input []lineRange
|
|
expected []lineRange
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "overlapping and unsorted ranges are merged",
|
|
input: []lineRange{{start: 5, end: 8}, {start: 1, end: 2}, {start: 2, end: 4}, {start: 10, end: 10}},
|
|
expected: []lineRange{{start: 1, end: 8}, {start: 10, end: 10}},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "adjacent ranges are merged",
|
|
input: []lineRange{{start: 0, end: 1}, {start: 2, end: 3}},
|
|
expected: []lineRange{{start: 0, end: 3}},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "empty input returns nil",
|
|
input: nil,
|
|
expected: nil,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := mergeRanges(tc.input)
|
|
|
|
if tc.wantErr {
|
|
t.Fatalf("unexpected wantErr=true for mergeRanges")
|
|
}
|
|
|
|
if len(got) != len(tc.expected) {
|
|
t.Fatalf("unexpected merged range count: got %d want %d", len(got), len(tc.expected))
|
|
}
|
|
for i := range got {
|
|
if got[i] != tc.expected[i] {
|
|
t.Fatalf("range %d mismatch: got %+v want %+v", i, got[i], tc.expected[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizedDirtyRanges(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args struct {
|
|
ranges []lineRange
|
|
lineCount int
|
|
}
|
|
expected []lineRange
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "clamps negative and overflowing ranges",
|
|
args: struct {
|
|
ranges []lineRange
|
|
lineCount int
|
|
}{
|
|
ranges: []lineRange{{start: -2, end: 1}, {start: 3, end: 99}},
|
|
lineCount: 5,
|
|
},
|
|
expected: []lineRange{{start: 0, end: 1}, {start: 3, end: 4}},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "drops invalid clamped ranges",
|
|
args: struct {
|
|
ranges []lineRange
|
|
lineCount int
|
|
}{
|
|
ranges: []lineRange{{start: 8, end: 9}},
|
|
lineCount: 5,
|
|
},
|
|
expected: nil,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "merges adjacent ranges after clamping",
|
|
args: struct {
|
|
ranges []lineRange
|
|
lineCount int
|
|
}{
|
|
ranges: []lineRange{{start: -3, end: 0}, {start: 1, end: 2}},
|
|
lineCount: 4,
|
|
},
|
|
expected: []lineRange{{start: 0, end: 2}},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := normalizedDirtyRanges(tc.args.ranges, tc.args.lineCount)
|
|
if tc.wantErr {
|
|
t.Fatalf("unexpected wantErr=true for normalizedDirtyRanges")
|
|
}
|
|
|
|
if len(got) != len(tc.expected) {
|
|
t.Fatalf("unexpected normalized range count: got %d want %d", len(got), len(tc.expected))
|
|
}
|
|
for i := range got {
|
|
if got[i] != tc.expected[i] {
|
|
t.Fatalf("range %d mismatch: got %+v want %+v", i, got[i], tc.expected[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestByteColToRuneIndexUTF8(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args struct {
|
|
line []byte
|
|
col int
|
|
}
|
|
expected int
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "zero column maps to first rune",
|
|
args: struct {
|
|
line []byte
|
|
col int
|
|
}{line: []byte("aéb"), col: 0},
|
|
expected: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "middle byte offset on multibyte rune",
|
|
args: struct {
|
|
line []byte
|
|
col int
|
|
}{line: []byte("aéb"), col: 1},
|
|
expected: 1,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "end of multibyte rune maps after rune",
|
|
args: struct {
|
|
line []byte
|
|
col int
|
|
}{line: []byte("aéb"), col: 3},
|
|
expected: 2,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "column at line end maps to rune length",
|
|
args: struct {
|
|
line []byte
|
|
col int
|
|
}{line: []byte("aéb"), col: len([]byte("aéb"))},
|
|
expected: 3,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := byteColToRuneIndex(tc.args.line, tc.args.col)
|
|
if tc.wantErr {
|
|
t.Fatalf("unexpected wantErr=true for byteColToRuneIndex")
|
|
}
|
|
if got != tc.expected {
|
|
t.Fatalf("unexpected rune index: got %d want %d", got, tc.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAddDirtyRangeNormalizesAndMerges(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args struct {
|
|
initial []lineRange
|
|
start int
|
|
end int
|
|
}
|
|
expected []lineRange
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "swaps start and end when reversed",
|
|
args: struct {
|
|
initial []lineRange
|
|
start int
|
|
end int
|
|
}{initial: nil, start: 7, end: 3},
|
|
expected: []lineRange{{start: 3, end: 7}},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "clamps negative values",
|
|
args: struct {
|
|
initial []lineRange
|
|
start int
|
|
end int
|
|
}{initial: nil, start: -5, end: -1},
|
|
expected: []lineRange{{start: 0, end: 0}},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "merges with existing adjacent range",
|
|
args: struct {
|
|
initial []lineRange
|
|
start int
|
|
end int
|
|
}{initial: []lineRange{{start: 1, end: 2}}, start: 3, end: 4},
|
|
expected: []lineRange{{start: 1, end: 4}},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
bc := &bufferCache{dirty: append([]lineRange{}, tc.args.initial...)}
|
|
addDirtyRange(bc, tc.args.start, tc.args.end)
|
|
if tc.wantErr {
|
|
t.Fatalf("unexpected wantErr=true for addDirtyRange")
|
|
}
|
|
if len(bc.dirty) != len(tc.expected) {
|
|
t.Fatalf("unexpected dirty range count: got %d want %d", len(bc.dirty), len(tc.expected))
|
|
}
|
|
for i := range bc.dirty {
|
|
if bc.dirty[i] != tc.expected[i] {
|
|
t.Fatalf("dirty range %d mismatch: got %+v want %+v", i, bc.dirty[i], tc.expected[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRowInRanges(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input struct {
|
|
row int
|
|
ranges []lineRange
|
|
}
|
|
expected bool
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "row inside range",
|
|
input: struct {
|
|
row int
|
|
ranges []lineRange
|
|
}{row: 3, ranges: []lineRange{{start: 1, end: 4}}},
|
|
expected: true,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "row outside all ranges",
|
|
input: struct {
|
|
row int
|
|
ranges []lineRange
|
|
}{row: 8, ranges: []lineRange{{start: 1, end: 4}, {start: 10, end: 12}}},
|
|
expected: false,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := rowInRanges(tc.input.row, tc.input.ranges)
|
|
if tc.wantErr {
|
|
t.Fatalf("unexpected wantErr=true for rowInRanges")
|
|
}
|
|
if got != tc.expected {
|
|
t.Fatalf("unexpected result: got %v want %v", got, tc.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|