buffer_test.gno

11.56 Kb ยท 593 lines
  1package json
  2
  3import (
  4	"testing"
  5)
  6
  7func TestBufferCurrent(t *testing.T) {
  8	tests := []struct {
  9		name     string
 10		buffer   *buffer
 11		expected byte
 12		wantErr  bool
 13	}{
 14		{
 15			name: "Valid current byte",
 16			buffer: &buffer{
 17				data:   []byte("test"),
 18				length: 4,
 19				index:  1,
 20			},
 21			expected: 'e',
 22			wantErr:  false,
 23		},
 24		{
 25			name: "EOF",
 26			buffer: &buffer{
 27				data:   []byte("test"),
 28				length: 4,
 29				index:  4,
 30			},
 31			expected: 0,
 32			wantErr:  true,
 33		},
 34	}
 35
 36	for _, tt := range tests {
 37		t.Run(tt.name, func(t *testing.T) {
 38			got, err := tt.buffer.current()
 39			if (err != nil) != tt.wantErr {
 40				t.Errorf("buffer.current() error = %v, wantErr %v", err, tt.wantErr)
 41				return
 42			}
 43			if got != tt.expected {
 44				t.Errorf("buffer.current() = %v, want %v", got, tt.expected)
 45			}
 46		})
 47	}
 48}
 49
 50func TestBufferStep(t *testing.T) {
 51	tests := []struct {
 52		name    string
 53		buffer  *buffer
 54		wantErr bool
 55	}{
 56		{
 57			name:    "Valid step",
 58			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
 59			wantErr: false,
 60		},
 61		{
 62			name:    "EOF error",
 63			buffer:  &buffer{data: []byte("test"), length: 4, index: 3},
 64			wantErr: true,
 65		},
 66	}
 67
 68	for _, tt := range tests {
 69		t.Run(tt.name, func(t *testing.T) {
 70			err := tt.buffer.step()
 71			if (err != nil) != tt.wantErr {
 72				t.Errorf("buffer.step() error = %v, wantErr %v", err, tt.wantErr)
 73			}
 74		})
 75	}
 76}
 77
 78func TestBufferNext(t *testing.T) {
 79	tests := []struct {
 80		name    string
 81		buffer  *buffer
 82		want    byte
 83		wantErr bool
 84	}{
 85		{
 86			name:    "Valid next byte",
 87			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
 88			want:    'e',
 89			wantErr: false,
 90		},
 91		{
 92			name:    "EOF error",
 93			buffer:  &buffer{data: []byte("test"), length: 4, index: 3},
 94			want:    0,
 95			wantErr: true,
 96		},
 97	}
 98
 99	for _, tt := range tests {
100		t.Run(tt.name, func(t *testing.T) {
101			got, err := tt.buffer.next()
102			if (err != nil) != tt.wantErr {
103				t.Errorf("buffer.next() error = %v, wantErr %v", err, tt.wantErr)
104				return
105			}
106			if got != tt.want {
107				t.Errorf("buffer.next() = %v, want %v", got, tt.want)
108			}
109		})
110	}
111}
112
113func TestBufferSlice(t *testing.T) {
114	tests := []struct {
115		name    string
116		buffer  *buffer
117		pos     int
118		want    []byte
119		wantErr bool
120	}{
121		{
122			name:    "Valid slice -- 0 characters",
123			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
124			pos:     0,
125			want:    nil,
126			wantErr: false,
127		},
128		{
129			name:    "Valid slice -- 1 character",
130			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
131			pos:     1,
132			want:    []byte("t"),
133			wantErr: false,
134		},
135		{
136			name:    "Valid slice -- 2 characters",
137			buffer:  &buffer{data: []byte("test"), length: 4, index: 1},
138			pos:     2,
139			want:    []byte("es"),
140			wantErr: false,
141		},
142		{
143			name:    "Valid slice -- 3 characters",
144			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
145			pos:     3,
146			want:    []byte("tes"),
147			wantErr: false,
148		},
149		{
150			name:    "Valid slice -- 4 characters",
151			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
152			pos:     4,
153			want:    []byte("test"),
154			wantErr: false,
155		},
156		{
157			name:    "EOF error",
158			buffer:  &buffer{data: []byte("test"), length: 4, index: 3},
159			pos:     2,
160			want:    nil,
161			wantErr: true,
162		},
163	}
164
165	for _, tt := range tests {
166		t.Run(tt.name, func(t *testing.T) {
167			got, err := tt.buffer.slice(tt.pos)
168			if (err != nil) != tt.wantErr {
169				t.Errorf("buffer.slice() error = %v, wantErr %v", err, tt.wantErr)
170				return
171			}
172			if string(got) != string(tt.want) {
173				t.Errorf("buffer.slice() = %v, want %v", got, tt.want)
174			}
175		})
176	}
177}
178
179func TestBufferMove(t *testing.T) {
180	tests := []struct {
181		name    string
182		buffer  *buffer
183		pos     int
184		wantErr bool
185		wantIdx int
186	}{
187		{
188			name:    "Valid move",
189			buffer:  &buffer{data: []byte("test"), length: 4, index: 1},
190			pos:     2,
191			wantErr: false,
192			wantIdx: 3,
193		},
194		{
195			name:    "Move beyond length",
196			buffer:  &buffer{data: []byte("test"), length: 4, index: 1},
197			pos:     4,
198			wantErr: true,
199			wantIdx: 1,
200		},
201	}
202
203	for _, tt := range tests {
204		t.Run(tt.name, func(t *testing.T) {
205			err := tt.buffer.move(tt.pos)
206			if (err != nil) != tt.wantErr {
207				t.Errorf("buffer.move() error = %v, wantErr %v", err, tt.wantErr)
208			}
209			if tt.buffer.index != tt.wantIdx {
210				t.Errorf("buffer.move() index = %v, want %v", tt.buffer.index, tt.wantIdx)
211			}
212		})
213	}
214}
215
216func TestBufferSkip(t *testing.T) {
217	tests := []struct {
218		name    string
219		buffer  *buffer
220		b       byte
221		wantErr bool
222	}{
223		{
224			name:    "Skip byte",
225			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
226			b:       'e',
227			wantErr: false,
228		},
229		{
230			name:    "Skip to EOF",
231			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
232			b:       'x',
233			wantErr: true,
234		},
235	}
236
237	for _, tt := range tests {
238		t.Run(tt.name, func(t *testing.T) {
239			err := tt.buffer.skip(tt.b)
240			if (err != nil) != tt.wantErr {
241				t.Errorf("buffer.skip() error = %v, wantErr %v", err, tt.wantErr)
242			}
243		})
244	}
245}
246
247func TestSkipToNextSignificantToken(t *testing.T) {
248	tests := []struct {
249		name     string
250		input    []byte
251		expected int
252	}{
253		{"No significant chars", []byte("abc"), 3},
254		{"One significant char at start", []byte(".abc"), 0},
255		{"Significant char in middle", []byte("ab.c"), 2},
256		{"Multiple significant chars", []byte("a$.c"), 1},
257		{"Significant char at end", []byte("abc$"), 3},
258		{"Only significant chars", []byte("$."), 0},
259		{"Empty string", []byte(""), 0},
260	}
261
262	for _, tt := range tests {
263		t.Run(tt.name, func(t *testing.T) {
264			b := newBuffer(tt.input)
265			b.skipToNextSignificantToken()
266			if b.index != tt.expected {
267				t.Errorf("after skipToNextSignificantToken(), got index = %v, want %v", b.index, tt.expected)
268			}
269		})
270	}
271}
272
273func mockBuffer(s string) *buffer {
274	return newBuffer([]byte(s))
275}
276
277func TestSkipAndReturnIndex(t *testing.T) {
278	tests := []struct {
279		name     string
280		input    string
281		expected int
282	}{
283		{"StartOfString", "", 0},
284		{"MiddleOfString", "abcdef", 1},
285		{"EndOfString", "abc", 1},
286	}
287
288	for _, tt := range tests {
289		t.Run(tt.name, func(t *testing.T) {
290			buf := mockBuffer(tt.input)
291			got, err := buf.skipAndReturnIndex()
292			if err != nil && tt.input != "" { // Expect no error unless input is empty
293				t.Errorf("skipAndReturnIndex() error = %v", err)
294			}
295			if got != tt.expected {
296				t.Errorf("skipAndReturnIndex() = %v, want %v", got, tt.expected)
297			}
298		})
299	}
300}
301
302func TestSkipUntil(t *testing.T) {
303	tests := []struct {
304		name     string
305		input    string
306		tokens   map[byte]bool
307		expected int
308	}{
309		{"SkipToToken", "abcdefg", map[byte]bool{'c': true}, 2},
310		{"SkipToEnd", "abcdefg", map[byte]bool{'h': true}, 7},
311		{"SkipNone", "abcdefg", map[byte]bool{'a': true}, 0},
312	}
313
314	for _, tt := range tests {
315		t.Run(tt.name, func(t *testing.T) {
316			buf := mockBuffer(tt.input)
317			got, err := buf.skipUntil(tt.tokens)
318			if err != nil && got != len(tt.input) { // Expect error only if reached end without finding token
319				t.Errorf("skipUntil() error = %v", err)
320			}
321			if got != tt.expected {
322				t.Errorf("skipUntil() = %v, want %v", got, tt.expected)
323			}
324		})
325	}
326}
327
328func TestSliceFromIndices(t *testing.T) {
329	tests := []struct {
330		name     string
331		input    string
332		start    int
333		end      int
334		expected string
335	}{
336		{"FullString", "abcdefg", 0, 7, "abcdefg"},
337		{"Substring", "abcdefg", 2, 5, "cde"},
338		{"OutOfBounds", "abcdefg", 5, 10, "fg"},
339	}
340
341	for _, tt := range tests {
342		t.Run(tt.name, func(t *testing.T) {
343			buf := mockBuffer(tt.input)
344			got := buf.sliceFromIndices(tt.start, tt.end)
345			if string(got) != tt.expected {
346				t.Errorf("sliceFromIndices() = %v, want %v", string(got), tt.expected)
347			}
348		})
349	}
350}
351
352func TestBufferToken(t *testing.T) {
353	tests := []struct {
354		name  string
355		path  string
356		index int
357		isErr bool
358	}{
359		{
360			name:  "Simple valid path",
361			path:  "@.length",
362			index: 8,
363			isErr: false,
364		},
365		{
366			name:  "Path with array expr",
367			path:  "@['foo'].0.bar",
368			index: 14,
369			isErr: false,
370		},
371		{
372			name:  "Path with array expr and simple fomula",
373			path:  "@['foo'].[(@.length - 1)].*",
374			index: 27,
375			isErr: false,
376		},
377		{
378			name:  "Path with filter expr",
379			path:  "@['foo'].[?(@.bar == 1 & @.baz < @.length)].*",
380			index: 45,
381			isErr: false,
382		},
383		{
384			name:  "addition of foo and bar",
385			path:  "@.foo+@.bar",
386			index: 11,
387			isErr: false,
388		},
389		{
390			name:  "logical AND of foo and bar",
391			path:  "@.foo && @.bar",
392			index: 14,
393			isErr: false,
394		},
395		{
396			name:  "logical OR of foo and bar",
397			path:  "@.foo || @.bar",
398			index: 14,
399			isErr: false,
400		},
401		{
402			name:  "accessing third element of foo",
403			path:  "@.foo,3",
404			index: 7,
405			isErr: false,
406		},
407		{
408			name:  "accessing last element of array",
409			path:  "@.length-1",
410			index: 10,
411			isErr: false,
412		},
413		{
414			name:  "number 1",
415			path:  "1",
416			index: 1,
417			isErr: false,
418		},
419		{
420			name:  "float",
421			path:  "3.1e4",
422			index: 5,
423			isErr: false,
424		},
425		{
426			name:  "float with minus",
427			path:  "3.1e-4",
428			index: 6,
429			isErr: false,
430		},
431		{
432			name:  "float with plus",
433			path:  "3.1e+4",
434			index: 6,
435			isErr: false,
436		},
437		{
438			name:  "negative number",
439			path:  "-12345",
440			index: 6,
441			isErr: false,
442		},
443		{
444			name:  "negative float",
445			path:  "-3.1e4",
446			index: 6,
447			isErr: false,
448		},
449		{
450			name:  "negative float with minus",
451			path:  "-3.1e-4",
452			index: 7,
453			isErr: false,
454		},
455		{
456			name:  "negative float with plus",
457			path:  "-3.1e+4",
458			index: 7,
459			isErr: false,
460		},
461		{
462			name:  "string number",
463			path:  "'12345'",
464			index: 7,
465			isErr: false,
466		},
467		{
468			name:  "string with backslash",
469			path:  "'foo \\'bar '",
470			index: 12,
471			isErr: false,
472		},
473		{
474			name:  "string with inner double quotes",
475			path:  "'foo \"bar \"'",
476			index: 12,
477			isErr: false,
478		},
479		{
480			name:  "parenthesis 1",
481			path:  "(@abc)",
482			index: 6,
483			isErr: false,
484		},
485		{
486			name:  "parenthesis 2",
487			path:  "[()]",
488			index: 4,
489			isErr: false,
490		},
491		{
492			name:  "parenthesis mismatch",
493			path:  "[(])",
494			index: 2,
495			isErr: true,
496		},
497		{
498			name:  "parenthesis mismatch 2",
499			path:  "(",
500			index: 1,
501			isErr: true,
502		},
503		{
504			name:  "parenthesis mismatch 3",
505			path:  "())]",
506			index: 2,
507			isErr: true,
508		},
509		{
510			name:  "bracket mismatch",
511			path:  "[()",
512			index: 3,
513			isErr: true,
514		},
515		{
516			name:  "bracket mismatch 2",
517			path:  "()]",
518			index: 2,
519			isErr: true,
520		},
521		{
522			name:  "path does not close bracket",
523			path:  "@.foo[)",
524			index: 6,
525			isErr: false,
526		},
527	}
528
529	for _, tt := range tests {
530		t.Run(tt.name, func(t *testing.T) {
531			buf := newBuffer([]byte(tt.path))
532
533			err := buf.pathToken()
534			if tt.isErr {
535				if err == nil {
536					t.Errorf("Expected an error for path `%s`, but got none", tt.path)
537				}
538			}
539
540			if err == nil && tt.isErr {
541				t.Errorf("Expected an error for path `%s`, but got none", tt.path)
542			}
543
544			if buf.index != tt.index {
545				t.Errorf("Expected final index %d, got %d (token: `%s`) for path `%s`", tt.index, buf.index, string(buf.data[buf.index]), tt.path)
546			}
547		})
548	}
549}
550
551func TestBufferFirst(t *testing.T) {
552	tests := []struct {
553		name     string
554		data     []byte
555		expected byte
556	}{
557		{
558			name:     "Valid first byte",
559			data:     []byte("test"),
560			expected: 't',
561		},
562		{
563			name:     "Empty buffer",
564			data:     []byte(""),
565			expected: 0,
566		},
567		{
568			name:     "Whitespace buffer",
569			data:     []byte("   "),
570			expected: 0,
571		},
572		{
573			name:     "whitespace in middle",
574			data:     []byte("hello world"),
575			expected: 'h',
576		},
577	}
578
579	for _, tt := range tests {
580		t.Run(tt.name, func(t *testing.T) {
581			b := newBuffer(tt.data)
582
583			got, err := b.first()
584			if err != nil && tt.expected != 0 {
585				t.Errorf("Unexpected error: %v", err)
586			}
587
588			if got != tt.expected {
589				t.Errorf("Expected first byte to be %q, got %q", tt.expected, got)
590			}
591		})
592	}
593}