github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/json/buffer_test.gno (about)

     1  package json
     2  
     3  import (
     4  	"testing"
     5  )
     6  
     7  func 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  
    50  func 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  
    78  func 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  
   113  func 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  
   179  func 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  
   216  func 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  
   247  func TestBufferSkipAny(t *testing.T) {
   248  	tests := []struct {
   249  		name    string
   250  		buffer  *buffer
   251  		s       map[byte]bool
   252  		wantErr bool
   253  	}{
   254  		{
   255  			name:    "Skip any valid byte",
   256  			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
   257  			s:       map[byte]bool{'e': true, 'o': true},
   258  			wantErr: false,
   259  		},
   260  		{
   261  			name:    "Skip any to EOF",
   262  			buffer:  &buffer{data: []byte("test"), length: 4, index: 0},
   263  			s:       map[byte]bool{'x': true, 'y': true},
   264  			wantErr: true,
   265  		},
   266  	}
   267  
   268  	for _, tt := range tests {
   269  		t.Run(tt.name, func(t *testing.T) {
   270  			err := tt.buffer.skipAny(tt.s)
   271  			if (err != nil) != tt.wantErr {
   272  				t.Errorf("buffer.skipAny() error = %v, wantErr %v", err, tt.wantErr)
   273  			}
   274  		})
   275  	}
   276  }
   277  
   278  func TestSkipToNextSignificantToken(t *testing.T) {
   279  	tests := []struct {
   280  		name     string
   281  		input    []byte
   282  		expected int
   283  	}{
   284  		{"No significant chars", []byte("abc"), 3},
   285  		{"One significant char at start", []byte(".abc"), 0},
   286  		{"Significant char in middle", []byte("ab.c"), 2},
   287  		{"Multiple significant chars", []byte("a$.c"), 1},
   288  		{"Significant char at end", []byte("abc$"), 3},
   289  		{"Only significant chars", []byte("$."), 0},
   290  		{"Empty string", []byte(""), 0},
   291  	}
   292  
   293  	for _, tt := range tests {
   294  		t.Run(tt.name, func(t *testing.T) {
   295  			b := newBuffer(tt.input)
   296  			b.skipToNextSignificantToken()
   297  			if b.index != tt.expected {
   298  				t.Errorf("after skipToNextSignificantToken(), got index = %v, want %v", b.index, tt.expected)
   299  			}
   300  		})
   301  	}
   302  }
   303  
   304  func mockBuffer(s string) *buffer {
   305  	return newBuffer([]byte(s))
   306  }
   307  
   308  func TestSkipAndReturnIndex(t *testing.T) {
   309  	tests := []struct {
   310  		name     string
   311  		input    string
   312  		expected int
   313  	}{
   314  		{"StartOfString", "", 0},
   315  		{"MiddleOfString", "abcdef", 1},
   316  		{"EndOfString", "abc", 1},
   317  	}
   318  
   319  	for _, tt := range tests {
   320  		t.Run(tt.name, func(t *testing.T) {
   321  			buf := mockBuffer(tt.input)
   322  			got, err := buf.skipAndReturnIndex()
   323  			if err != nil && tt.input != "" { // Expect no error unless input is empty
   324  				t.Errorf("skipAndReturnIndex() error = %v", err)
   325  			}
   326  			if got != tt.expected {
   327  				t.Errorf("skipAndReturnIndex() = %v, want %v", got, tt.expected)
   328  			}
   329  		})
   330  	}
   331  }
   332  
   333  func TestSkipUntil(t *testing.T) {
   334  	tests := []struct {
   335  		name     string
   336  		input    string
   337  		tokens   map[byte]bool
   338  		expected int
   339  	}{
   340  		{"SkipToToken", "abcdefg", map[byte]bool{'c': true}, 2},
   341  		{"SkipToEnd", "abcdefg", map[byte]bool{'h': true}, 7},
   342  		{"SkipNone", "abcdefg", map[byte]bool{'a': true}, 0},
   343  	}
   344  
   345  	for _, tt := range tests {
   346  		t.Run(tt.name, func(t *testing.T) {
   347  			buf := mockBuffer(tt.input)
   348  			got, err := buf.skipUntil(tt.tokens)
   349  			if err != nil && got != len(tt.input) { // Expect error only if reached end without finding token
   350  				t.Errorf("skipUntil() error = %v", err)
   351  			}
   352  			if got != tt.expected {
   353  				t.Errorf("skipUntil() = %v, want %v", got, tt.expected)
   354  			}
   355  		})
   356  	}
   357  }
   358  
   359  func TestSliceFromIndices(t *testing.T) {
   360  	tests := []struct {
   361  		name     string
   362  		input    string
   363  		start    int
   364  		end      int
   365  		expected string
   366  	}{
   367  		{"FullString", "abcdefg", 0, 7, "abcdefg"},
   368  		{"Substring", "abcdefg", 2, 5, "cde"},
   369  		{"OutOfBounds", "abcdefg", 5, 10, "fg"},
   370  	}
   371  
   372  	for _, tt := range tests {
   373  		t.Run(tt.name, func(t *testing.T) {
   374  			buf := mockBuffer(tt.input)
   375  			got := buf.sliceFromIndices(tt.start, tt.end)
   376  			if string(got) != tt.expected {
   377  				t.Errorf("sliceFromIndices() = %v, want %v", string(got), tt.expected)
   378  			}
   379  		})
   380  	}
   381  }
   382  
   383  func TestBufferToken(t *testing.T) {
   384  	tests := []struct {
   385  		name  string
   386  		path  string
   387  		index int
   388  		isErr bool
   389  	}{
   390  		{
   391  			name:  "Simple valid path",
   392  			path:  "@.length",
   393  			index: 8,
   394  			isErr: false,
   395  		},
   396  		{
   397  			name:  "Path with array expr",
   398  			path:  "@['foo'].0.bar",
   399  			index: 14,
   400  			isErr: false,
   401  		},
   402  		{
   403  			name:  "Path with array expr and simple fomula",
   404  			path:  "@['foo'].[(@.length - 1)].*",
   405  			index: 27,
   406  			isErr: false,
   407  		},
   408  		{
   409  			name:  "Path with filter expr",
   410  			path:  "@['foo'].[?(@.bar == 1 & @.baz < @.length)].*",
   411  			index: 45,
   412  			isErr: false,
   413  		},
   414  		{
   415  			name:  "addition of foo and bar",
   416  			path:  "@.foo+@.bar",
   417  			index: 11,
   418  			isErr: false,
   419  		},
   420  		{
   421  			name:  "logical AND of foo and bar",
   422  			path:  "@.foo && @.bar",
   423  			index: 14,
   424  			isErr: false,
   425  		},
   426  		{
   427  			name:  "logical OR of foo and bar",
   428  			path:  "@.foo || @.bar",
   429  			index: 14,
   430  			isErr: false,
   431  		},
   432  		{
   433  			name:  "accessing third element of foo",
   434  			path:  "@.foo,3",
   435  			index: 7,
   436  			isErr: false,
   437  		},
   438  		{
   439  			name:  "accessing last element of array",
   440  			path:  "@.length-1",
   441  			index: 10,
   442  			isErr: false,
   443  		},
   444  		{
   445  			name:  "number 1",
   446  			path:  "1",
   447  			index: 1,
   448  			isErr: false,
   449  		},
   450  		{
   451  			name:  "float",
   452  			path:  "3.1e4",
   453  			index: 5,
   454  			isErr: false,
   455  		},
   456  		{
   457  			name:  "float with minus",
   458  			path:  "3.1e-4",
   459  			index: 6,
   460  			isErr: false,
   461  		},
   462  		{
   463  			name:  "float with plus",
   464  			path:  "3.1e+4",
   465  			index: 6,
   466  			isErr: false,
   467  		},
   468  		{
   469  			name:  "negative number",
   470  			path:  "-12345",
   471  			index: 6,
   472  			isErr: false,
   473  		},
   474  		{
   475  			name:  "negative float",
   476  			path:  "-3.1e4",
   477  			index: 6,
   478  			isErr: false,
   479  		},
   480  		{
   481  			name:  "negative float with minus",
   482  			path:  "-3.1e-4",
   483  			index: 7,
   484  			isErr: false,
   485  		},
   486  		{
   487  			name:  "negative float with plus",
   488  			path:  "-3.1e+4",
   489  			index: 7,
   490  			isErr: false,
   491  		},
   492  		{
   493  			name:  "string number",
   494  			path:  "'12345'",
   495  			index: 7,
   496  			isErr: false,
   497  		},
   498  		{
   499  			name:  "string with backslash",
   500  			path:  "'foo \\'bar '",
   501  			index: 12,
   502  			isErr: false,
   503  		},
   504  		{
   505  			name:  "string with inner double quotes",
   506  			path:  "'foo \"bar \"'",
   507  			index: 12,
   508  			isErr: false,
   509  		},
   510  		{
   511  			name:  "parenthesis 1",
   512  			path:  "(@abc)",
   513  			index: 6,
   514  			isErr: false,
   515  		},
   516  		{
   517  			name:  "parenthesis 2",
   518  			path:  "[()]",
   519  			index: 4,
   520  			isErr: false,
   521  		},
   522  		{
   523  			name:  "parenthesis mismatch",
   524  			path:  "[(])",
   525  			index: 2,
   526  			isErr: true,
   527  		},
   528  		{
   529  			name:  "parenthesis mismatch 2",
   530  			path:  "(",
   531  			index: 1,
   532  			isErr: true,
   533  		},
   534  		{
   535  			name:  "parenthesis mismatch 3",
   536  			path:  "())]",
   537  			index: 2,
   538  			isErr: true,
   539  		},
   540  		{
   541  			name:  "bracket mismatch",
   542  			path:  "[()",
   543  			index: 3,
   544  			isErr: true,
   545  		},
   546  		{
   547  			name:  "bracket mismatch 2",
   548  			path:  "()]",
   549  			index: 2,
   550  			isErr: true,
   551  		},
   552  		{
   553  			name:  "path does not close bracket",
   554  			path:  "@.foo[)",
   555  			index: 6,
   556  			isErr: false,
   557  		},
   558  	}
   559  
   560  	for _, tt := range tests {
   561  		t.Run(tt.name, func(t *testing.T) {
   562  			buf := newBuffer([]byte(tt.path))
   563  
   564  			err := buf.pathToken()
   565  			if tt.isErr {
   566  				if err == nil {
   567  					t.Errorf("Expected an error for path `%s`, but got none", tt.path)
   568  				}
   569  			}
   570  
   571  			if err == nil && tt.isErr {
   572  				t.Errorf("Expected an error for path `%s`, but got none", tt.path)
   573  			}
   574  
   575  			if buf.index != tt.index {
   576  				t.Errorf("Expected final index %d, got %d (token: `%s`) for path `%s`", tt.index, buf.index, string(buf.data[buf.index]), tt.path)
   577  			}
   578  		})
   579  	}
   580  }
   581  
   582  func TestBufferFirst(t *testing.T) {
   583  	tests := []struct {
   584  		name     string
   585  		data     []byte
   586  		expected byte
   587  	}{
   588  		{
   589  			name:     "Valid first byte",
   590  			data:     []byte("test"),
   591  			expected: 't',
   592  		},
   593  		{
   594  			name:     "Empty buffer",
   595  			data:     []byte(""),
   596  			expected: 0,
   597  		},
   598  		{
   599  			name:     "Whitespace buffer",
   600  			data:     []byte("   "),
   601  			expected: 0,
   602  		},
   603  		{
   604  			name:     "whitespace in middle",
   605  			data:     []byte("hello world"),
   606  			expected: 'h',
   607  		},
   608  	}
   609  
   610  	for _, tt := range tests {
   611  		t.Run(tt.name, func(t *testing.T) {
   612  			b := newBuffer(tt.data)
   613  
   614  			got, err := b.first()
   615  			if err != nil && tt.expected != 0 {
   616  				t.Errorf("Unexpected error: %v", err)
   617  			}
   618  
   619  			if got != tt.expected {
   620  				t.Errorf("Expected first byte to be %q, got %q", tt.expected, got)
   621  			}
   622  		})
   623  	}
   624  }