fork of go-gitdiff with jj support
1package gitdiff
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7 "math/rand"
8 "testing"
9)
10
11func TestLineReaderAt(t *testing.T) {
12 tests := map[string]struct {
13 InputLines int
14 Offset int64
15 Count int
16 Err bool
17 EOF bool
18 EOFCount int
19 }{
20 "readLines": {
21 InputLines: 32,
22 Offset: 0,
23 Count: 4,
24 },
25 "readLinesOffset": {
26 InputLines: 32,
27 Offset: 8,
28 Count: 4,
29 },
30 "readLinesLargeOffset": {
31 InputLines: 8192,
32 Offset: 4096,
33 Count: 64,
34 },
35 "readSingleLine": {
36 InputLines: 4,
37 Offset: 2,
38 Count: 1,
39 },
40 "readZeroLines": {
41 InputLines: 4,
42 Offset: 2,
43 Count: 0,
44 },
45 "readThroughEOF": {
46 InputLines: 16,
47 Offset: 12,
48 Count: 8,
49 EOF: true,
50 EOFCount: 4,
51 },
52 "emptyInput": {
53 InputLines: 0,
54 Offset: 0,
55 Count: 2,
56 EOF: true,
57 EOFCount: 0,
58 },
59 "offsetAfterEOF": {
60 InputLines: 8,
61 Offset: 10,
62 Count: 2,
63 EOF: true,
64 EOFCount: 0,
65 },
66 "offsetNegative": {
67 InputLines: 8,
68 Offset: -1,
69 Count: 2,
70 Err: true,
71 },
72 }
73
74 const lineTemplate = "generated test line %d\n"
75
76 for name, test := range tests {
77 t.Run(name, func(t *testing.T) {
78 var input bytes.Buffer
79 for i := 0; i < test.InputLines; i++ {
80 fmt.Fprintf(&input, lineTemplate, i)
81 }
82
83 output := make([][]byte, test.Count)
84 for i := 0; i < test.Count; i++ {
85 output[i] = []byte(fmt.Sprintf(lineTemplate, test.Offset+int64(i)))
86 }
87
88 r := &lineReaderAt{r: bytes.NewReader(input.Bytes())}
89 lines := make([][]byte, test.Count)
90
91 n, err := r.ReadLinesAt(lines, test.Offset)
92 if test.Err {
93 if err == nil {
94 t.Fatal("expected error reading lines, but got nil")
95 }
96 return
97 }
98 if err != nil && (!test.EOF || err != io.EOF) {
99 t.Fatalf("unexpected error reading lines: %v", err)
100 }
101
102 count := test.Count
103 if test.EOF {
104 count = test.EOFCount
105 }
106
107 if n != count {
108 t.Fatalf("incorrect number of lines read: expected %d, actual %d", count, n)
109 }
110 for i := 0; i < n; i++ {
111 if !bytes.Equal(output[i], lines[i]) {
112 t.Errorf("incorrect content in line %d:\nexpected: %q\nactual: %q", i, output[i], lines[i])
113 }
114 }
115 })
116 }
117}
118
119func TestCopyFrom(t *testing.T) {
120 tests := map[string]struct {
121 Bytes int64
122 Offset int64
123 }{
124 "copyAll": {
125 Bytes: byteBufferSize / 2,
126 },
127 "copyPartial": {
128 Bytes: byteBufferSize / 2,
129 Offset: byteBufferSize / 4,
130 },
131 "copyLarge": {
132 Bytes: 8 * byteBufferSize,
133 },
134 }
135
136 for name, test := range tests {
137 t.Run(name, func(t *testing.T) {
138 data := make([]byte, test.Bytes)
139 rand.Read(data)
140
141 var dst bytes.Buffer
142 n, err := copyFrom(&dst, bytes.NewReader(data), test.Offset)
143 if err != nil {
144 t.Fatalf("unexpected error copying data: %v", err)
145 }
146 if n != test.Bytes-test.Offset {
147 t.Fatalf("incorrect number of bytes copied: expected %d, actual %d", test.Bytes-test.Offset, n)
148 }
149
150 expected := data[test.Offset:]
151 if !bytes.Equal(expected, dst.Bytes()) {
152 t.Fatalf("incorrect data copied:\nexpected: %v\nactual: %v", expected, dst.Bytes())
153 }
154 })
155 }
156}
157
158func TestCopyLinesFrom(t *testing.T) {
159 tests := map[string]struct {
160 Lines int64
161 Offset int64
162 }{
163 "copyAll": {
164 Lines: lineBufferSize / 2,
165 },
166 "copyPartial": {
167 Lines: lineBufferSize / 2,
168 Offset: lineBufferSize / 4,
169 },
170 "copyLarge": {
171 Lines: 8 * lineBufferSize,
172 },
173 }
174
175 const lineLength = 128
176
177 for name, test := range tests {
178 t.Run(name, func(t *testing.T) {
179 data := make([]byte, test.Lines*lineLength)
180 for i := range data {
181 data[i] = byte(32 + rand.Intn(95)) // ascii letters, numbers, symbols
182 if i%lineLength == lineLength-1 {
183 data[i] = '\n'
184 }
185 }
186
187 var dst bytes.Buffer
188 n, err := copyLinesFrom(&dst, &lineReaderAt{r: bytes.NewReader(data)}, test.Offset)
189 if err != nil {
190 t.Fatalf("unexpected error copying data: %v", err)
191 }
192 if n != test.Lines-test.Offset {
193 t.Fatalf("incorrect number of lines copied: expected %d, actual %d", test.Lines-test.Offset, n)
194 }
195
196 expected := data[test.Offset*lineLength:]
197 if !bytes.Equal(expected, dst.Bytes()) {
198 t.Fatalf("incorrect data copied:\nexpected: %v\nactual: %v", expected, dst.Bytes())
199 }
200 })
201 }
202}