...

Source file src/github.com/bytedance/sonic/ast/api_test.go

Documentation: github.com/bytedance/sonic/ast

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package ast
    18  
    19  import (
    20      `testing`
    21      `strings`
    22  
    23      `github.com/stretchr/testify/assert`
    24  )
    25  
    26  type Path = []interface{}
    27  
    28  type testGetApi struct {
    29      json      string
    30      path      Path
    31  }
    32  
    33  type checkError func(error) bool
    34  
    35  func isSyntaxError(err error) bool {
    36      if err == nil {
    37          return false
    38      }
    39      return strings.HasPrefix(err.Error(), `"Syntax error at index`)
    40  }
    41  
    42  func isEmptySource(err error) bool {
    43      if err == nil {
    44          return false
    45      }
    46      return strings.Contains(err.Error(), "no sources available")
    47  }
    48  
    49  func isErrNotExist(err error) bool {
    50      return err == ErrNotExist
    51  }
    52  
    53  func isErrUnsupportType(err error) bool {
    54      return err == ErrUnsupportType
    55  }
    56  
    57  func testSyntaxJson(t *testing.T, json string, path ...interface{}) {
    58      search := NewSearcher(json)
    59      _, err := search.GetByPath(path...)
    60      assert.True(t, isSyntaxError(err))
    61  }
    62  
    63  func TestGetFromEmptyJson(t *testing.T) {
    64      tests := []testGetApi {
    65          { "", nil },
    66          { "", Path{}},
    67          { "", Path{""}},
    68          { "", Path{0}},
    69          { "", Path{"", ""}},
    70      }
    71      for _, test := range tests {
    72          f := func(t *testing.T) {
    73              search := NewSearcher(test.json)
    74              _, err := search.GetByPath(test.path...)
    75              assert.True(t, isEmptySource(err))
    76          }
    77          t.Run(test.json, f)
    78      }
    79  }
    80  
    81  func TestGetFromSyntaxError(t *testing.T) {
    82      tests := []testGetApi {
    83          { " \r\n\f\t", Path{} },
    84          { "123.", Path{} },
    85          { "+124", Path{} },
    86          { "-", Path{} },
    87          { "-e123", Path{} },
    88          { "-1.e123", Path{} },
    89          { "-12e456.1", Path{} },
    90          { "-12e.1", Path{} },
    91          { "[", Path{} },
    92          { "{", Path{} },
    93          { "[}", Path{} },
    94          { "{]", Path{} },
    95          { "{,}", Path{} },
    96          { "[,]", Path{} },
    97          { "tru", Path{} },
    98          { "fals", Path{} },
    99          { "nul", Path{} },
   100          { `{"a":"`, Path{"a"} },
   101          { `{"`, Path{} },
   102          { `"`, Path{} },
   103          { `"\"`, Path{} },
   104          { `"\\\"`, Path{} },
   105          { `"hello`, Path{} },
   106          { `{{}}`, Path{} },
   107          { `{[]}`, Path{} },
   108          { `{:,}`, Path{} },
   109          { `{test:error}`, Path{} },
   110          { `{":true}`, Path{} },
   111          { `{"" false}`, Path{} },
   112          { `{ "" : "false }`, Path{} },
   113          { `{"":"",}`, Path{} },
   114          { `{ " test : true}`, Path{} },
   115          { `{ "test" : tru }`, Path{} },
   116          { `{ "test" : true , }`, Path{} },
   117          { `{ {"test" : true , } }`, Path{} },
   118          { `{"test":1. }`, Path{} },
   119          { `{"\\\""`, Path{} },
   120          { `{"\\\"":`, Path{} },
   121          { `{"\\\":",""}`, Path{} },
   122          { `[{]`, Path{} },
   123          { `[tru]`, Path{} },
   124          { `[-1.]`, Path{} },
   125          { `[[]`, Path{} },
   126          { `[[],`, Path{} },
   127          { `[ true , false , [ ]`, Path{} },
   128          { `[true, false, [],`, Path{} },
   129          { `[true, false, [],]`, Path{} },
   130          { `{"key": [true, false, []], "key2": {{}}`, Path{} },
   131      }
   132  
   133      for _, test := range tests {
   134          f := func(t *testing.T) {
   135              testSyntaxJson(t, test.json, test.path...)
   136              path := append(Path{"key"}, test.path...)
   137              testSyntaxJson(t, `{"key":` + test.json, path...)
   138              path  = append(Path{""}, test.path...)
   139              testSyntaxJson(t, `{"":` + test.json, path...)
   140              path  = append(Path{1}, test.path...)
   141              testSyntaxJson(t, `["",` + test.json, path...)
   142          }
   143          t.Run(test.json, f)
   144      }
   145  }
   146  
   147  // NOTE: GetByPath API not validate the undemanded fields for performance.
   148  func TestGetWithInvalidUndemandedField(t *testing.T) {
   149      type Any = interface{}
   150      tests := []struct {
   151          json string
   152          path Path
   153          exp  Any
   154      } {
   155          { "-0xyz", Path{}, Any(float64(-0))},
   156          { "-12e4xyz", Path{}, Any(float64(-12e4))},
   157          { "truex",  Path{}, Any(true)},
   158          { "false,", Path{}, Any(false)},
   159          { `{"a":{,xxx},"b":true}`, Path{"b"}, Any(true)},
   160          { `{"a":[,xxx],"b":true}`, Path{"b"}, Any(true)},
   161      }
   162  
   163      for _, test := range tests {
   164          f := func(t *testing.T) {
   165              search := NewSearcher(test.json)
   166              node, err := search.GetByPath(test.path...)
   167              assert.NoError(t, err)
   168              v, err := node.Interface()
   169              assert.NoError(t, err)
   170              assert.Equal(t, v, test.exp)
   171          }
   172          t.Run(test.json, f)
   173      }
   174  }
   175  
   176  func TestGet_InvalidPathType(t *testing.T) {
   177      assert.Panics(t, assert.PanicTestFunc(func() {
   178          data := `{"a":[{"b":true}]}`
   179          s := NewSearcher(data)
   180          s.GetByPath("a", true)
   181  
   182          s = NewSearcher(data)
   183          s.GetByPath("a", nil)
   184  
   185          s = NewSearcher(data)
   186          s.GetByPath("a", -1)
   187      }))
   188  }
   189  

View as plain text