github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/search_test.go (about)

     1  //go:build amd64 && go1.16 && !go1.22
     2  // +build amd64,go1.16,!go1.22
     3  
     4  /*
     5   * Copyright 2021 ByteDance Inc.
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package sonic
    21  
    22  import (
    23  	"bytes"
    24  	"encoding/hex"
    25  	"encoding/json"
    26  	"fmt"
    27  	"math/rand"
    28  	"reflect"
    29  	"strings"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/davecgh/go-spew/spew"
    34  	"github.com/goshafaq/sonic/ast"
    35  	"github.com/stretchr/testify/assert"
    36  )
    37  
    38  func Parse(src string) (*ast.Node, error) {
    39  	node, err := ast.NewParser(src).Parse()
    40  	if err != 0 {
    41  		return &node, fmt.Errorf("parsing error: %v", err)
    42  	}
    43  	return &node, nil
    44  }
    45  
    46  func assertCond(cond bool) {
    47  	if !cond {
    48  		panic("assertCond failed")
    49  	}
    50  }
    51  
    52  func TestExampleSearch(t *testing.T) {
    53  	data := []byte(` { "xx" : [] ,"yy" :{ }, "test" : [ true , 0.1 , "abc", ["h"], {"a":"bc"} ] } `)
    54  
    55  	node, e := Get(data, "test", 0)
    56  	x, _ := node.Bool()
    57  	if e != nil || x != true {
    58  		t.Fatalf("node: %v, err: %v", node, e)
    59  	}
    60  
    61  	node, e = Get(data, "test", 1)
    62  	a, _ := node.Float64()
    63  	if e != nil || a != 0.1 {
    64  		t.Fatalf("node: %v, err: %v", node, e)
    65  	}
    66  
    67  	node, e = Get(data, "test", 2)
    68  	b, _ := node.String()
    69  	if e != nil || b != "abc" {
    70  		t.Fatalf("node: %v, err: %v", node, e)
    71  	}
    72  
    73  	node, e = Get(data, "test", 3)
    74  	arr, _ := node.Array()
    75  	if e != nil || arr[0] != "h" {
    76  		t.Fatalf("node: %v, err: %v", node, e)
    77  	}
    78  
    79  	node, e = Get(data, "test", 4, "a")
    80  	c, _ := node.String()
    81  	if e != nil || c != "bc" {
    82  		t.Fatalf("node: %v, err: %v", node, e)
    83  	}
    84  }
    85  
    86  func TestExampleSearchEscapedKey(t *testing.T) {
    87  	data := []byte(`
    88  {
    89      "xx" : [] ,
    90      "yy" :{ }, 
    91      "test\"" : [
    92          true ,
    93          0.1 ,
    94          "abc",
    95          [
    96              "h"
    97          ], 
    98          {
    99              "a\u0008": {},
   100              "b\\\\": null,
   101              "\u2028\u2028": "\u2028\u2029",
   102              "\u0026":2,
   103              "0":1
   104          } 
   105      ],
   106      ",,,,,,,,,,(,,15": ",",
   107      ",,,,,,,,,,(,,,16": "a,]}",
   108      ",,,,,,,,,,(,,,,17": 1,
   109      ",,,,,,,,,,(,,,,,,,,,,,,,,,,(,,,,34": "c"
   110  } `)
   111  
   112  	type getTest struct {
   113  		path   []interface{}
   114  		expect interface{}
   115  	}
   116  
   117  	tests := []getTest{
   118  		{[]interface{}{"test\"", 0}, true},
   119  		{[]interface{}{"test\"", 1}, 0.1},
   120  		{[]interface{}{"test\"", 2}, "abc"},
   121  		{[]interface{}{"test\"", 3}, []interface{}{"h"}},
   122  		{[]interface{}{"test\"", 4, "a\u0008"}, map[string]interface{}{}},
   123  		{[]interface{}{"test\"", 4, "b\\\\"}, nil},
   124  		{[]interface{}{"test\"", 4, "\u2028\u2028"}, "\u2028\u2029"},
   125  		{[]interface{}{"test\"", 4, "0"}, float64(1)},
   126  		{[]interface{}{",,,,,,,,,,(,,15"}, ","},
   127  		{[]interface{}{",,,,,,,,,,(,,,16"}, "a,]}"},
   128  		{[]interface{}{",,,,,,,,,,(,,,,17"}, float64(1)},
   129  		{[]interface{}{",,,,,,,,,,(,,,,,,,,,,,,,,,,(,,,,34"}, "c"},
   130  	}
   131  
   132  	for _, test := range tests {
   133  		node, err := Get(data, test.path...)
   134  		assert.NoErrorf(t, err, "get return errors")
   135  		got, err := node.Interface()
   136  		assert.NoErrorf(t, err, "get convert errors")
   137  		assert.Equalf(t, test.expect, got, "get result is wrong from path %#v", test.path)
   138  	}
   139  }
   140  
   141  func TestExampleSearchErr(t *testing.T) {
   142  	data := []byte(` { "xx" : [] ,"yy" :{ }, "test" : [ true , 0.1 , "abc", ["h"], {"a":"bc"} ] } `)
   143  	node, e := Get(data, "zz")
   144  	if e == nil {
   145  		t.Fatalf("node: %v, err: %v", node, e)
   146  	}
   147  	fmt.Println(e)
   148  
   149  	node, e = Get(data, "xx", 4)
   150  	if e == nil {
   151  		t.Fatalf("node: %v, err: %v", node, e)
   152  	}
   153  	fmt.Println(e)
   154  
   155  	node, e = Get(data, "yy", "a")
   156  	if e == nil {
   157  		t.Fatalf("node: %v, err: %v", node, e)
   158  	}
   159  	fmt.Println(e)
   160  
   161  	node, e = Get(data, "test", 4, "x")
   162  	if e == nil {
   163  		t.Fatalf("node: %v, err: %v", node, e)
   164  	}
   165  	fmt.Println(e)
   166  }
   167  
   168  func TestExampleSearchEscapedKeyError(t *testing.T) {
   169  	data := []byte(` { "xx" : [] ,"yy" :{ }, "x\u0008" : [] ,"y\\\"y" :{ }, "test" : [ true , 0.1 , "abc", ["h"], {"a":"bc"} ] } `)
   170  	node, e := Get(data, "zz")
   171  	if e == nil {
   172  		t.Fatalf("node: %v, err: %v", node, e)
   173  	}
   174  	fmt.Println(e)
   175  
   176  	node, e = Get(data, "x\u0008", 4)
   177  	if e == nil {
   178  		t.Fatalf("node: %v, err: %v", node, e)
   179  	}
   180  	fmt.Println(e)
   181  
   182  	node, e = Get(data, "yy", "a")
   183  	if e == nil {
   184  		t.Fatalf("node: %v, err: %v", node, e)
   185  	}
   186  	fmt.Println(e)
   187  
   188  	node, e = Get(data, "test", 4, "x")
   189  	if e == nil {
   190  		t.Fatalf("node: %v, err: %v", node, e)
   191  	}
   192  
   193  	node, e = Get(data, "y\\\"y", 4, "x")
   194  	if e == nil {
   195  		t.Fatalf("node: %v, err: %v", node, e)
   196  	}
   197  	fmt.Println(e)
   198  }
   199  
   200  func TestRandomData(t *testing.T) {
   201  	var lstr string
   202  	defer func() {
   203  		if v := recover(); v != nil {
   204  			println("'" + hex.Dump([]byte(lstr)) + "'")
   205  			println(lstr)
   206  			panic(v)
   207  		}
   208  	}()
   209  	data := []byte(`"�-mp�`)
   210  	_, err := ast.NewParser(string(data)).Parse()
   211  	if err != 0 {
   212  		fmt.Println(hex.Dump(data))
   213  		fmt.Println(string(data))
   214  	}
   215  	rand.Seed(time.Now().UnixNano())
   216  	b := make([]byte, 200)
   217  	for i := 0; i < 1000000; i++ {
   218  		n, ee := rand.Read(b[:rand.Int()%len(b)])
   219  		if ee != nil {
   220  			t.Fatalf("get random bytes failed: %v,", ee)
   221  			return
   222  		}
   223  		lstr = string(b[:n])
   224  		_, _ = ast.NewParser(lstr).Parse()
   225  	}
   226  }
   227  
   228  func TestRandomValidStrings(t *testing.T) {
   229  	rand.Seed(time.Now().UnixNano())
   230  	b := make([]byte, 200)
   231  	for i := 0; i < 1000; i++ {
   232  		n, err := rand.Read(b[:rand.Int()%len(b)])
   233  		if err != nil {
   234  			t.Fatal("get random data failed:", err)
   235  		}
   236  		sm, err := json.Marshal(string(b[:n]))
   237  		if err != nil {
   238  			t.Fatal("marshal data failed:", err)
   239  		}
   240  		var su string
   241  		if err := json.Unmarshal(sm, &su); err != nil {
   242  			t.Fatal("unmarshal data failed:", err)
   243  		}
   244  		token, err := GetFromString(`{"str":`+string(sm)+`}`, "str")
   245  		if err != nil {
   246  			spew.Dump(string(sm))
   247  			t.Fatal("search data failed:", err)
   248  		}
   249  		x, _ := token.Interface()
   250  		st, ok := x.(string)
   251  		if !ok {
   252  			t.Fatalf("type mismatch, exp: %v, got: %v", su, x)
   253  		}
   254  		if st != su {
   255  			t.Fatalf("string mismatch, exp: %v, got: %v", su, x)
   256  		}
   257  	}
   258  }
   259  
   260  func TestEmoji(t *testing.T) {
   261  	var input = []byte(`{"utf8":"Example emoji, KO: \ud83d\udd13, \ud83c\udfc3 ` +
   262  		`OK: \u2764\ufe0f "}`)
   263  	value, err := Get(input, "utf8")
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	var v map[string]interface{}
   268  	if err := json.Unmarshal(input, &v); err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	s, _ := v["utf8"].(string)
   272  	x, _ := value.String()
   273  	if x != s {
   274  		t.Fatalf("expected '%v', got '%v'", s, x)
   275  	}
   276  }
   277  
   278  func testEscapePath(t *testing.T, json, expect string, path ...interface{}) {
   279  	n, e := Get([]byte(json), path...)
   280  	if e != nil {
   281  		t.Fatal(e)
   282  	}
   283  	x, _ := n.String()
   284  	if x != expect {
   285  		x, _ := n.Interface()
   286  		t.Fatalf("expected '%v', got '%v'", expect, x)
   287  	}
   288  }
   289  
   290  func TestEscapePath(t *testing.T) {
   291  	data := `{
   292          "test":{
   293              "*":"valZ",
   294              "*v":"val0",
   295              "keyv*":"val1",
   296              "key*v":"val2",
   297              "keyv?":"val3",
   298              "key?v":"val4",
   299              "keyv.":"val5",
   300              "key.v":"val6",
   301              "keyk*":{"key?":"val7"}
   302          }
   303      }`
   304  
   305  	testEscapePath(t, data, "valZ", "test", "*")
   306  	testEscapePath(t, data, "val0", "test", "*v")
   307  	testEscapePath(t, data, "val1", "test", "keyv*")
   308  	testEscapePath(t, data, "val2", "test", "key*v")
   309  	testEscapePath(t, data, "val3", "test", "keyv?")
   310  	testEscapePath(t, data, "val4", "test", "key?v")
   311  	testEscapePath(t, data, "val5", "test", "keyv.")
   312  	testEscapePath(t, data, "val6", "test", "key.v")
   313  	testEscapePath(t, data, "val7", "test", "keyk*", "key?")
   314  }
   315  
   316  func TestParseAny(t *testing.T) {
   317  	n, e := Parse("100")
   318  	assertCond(e == nil)
   319  	if n == nil {
   320  		panic("n is nil")
   321  	}
   322  	x, _ := n.Float64()
   323  	assertCond(x == 100)
   324  	n, e = Parse("true")
   325  	assertCond(e == nil)
   326  	if n == nil {
   327  		panic("n is nil")
   328  	}
   329  
   330  	a, _ := n.Bool()
   331  	assertCond(a)
   332  	n, e = Parse("false")
   333  	assertCond(e == nil)
   334  	if n == nil {
   335  		panic("n is nil")
   336  	}
   337  	b, _ := n.Bool()
   338  	assertCond(b == false)
   339  	n, e = Parse("yikes")
   340  	assertCond(e != nil)
   341  }
   342  
   343  func TestTime(t *testing.T) {
   344  	data := []byte(`{
   345        "code": 0,
   346        "msg": "",
   347        "data": {
   348          "sz002024": {
   349            "qfqday": [
   350              [
   351                "2014-01-02",
   352                "8.93",
   353                "9.03",
   354                "9.17",
   355                "8.88",
   356                "621143.00"
   357              ],
   358              [
   359                "2014-01-03",
   360                "9.03",
   361                "9.30",
   362                "9.47",
   363                "8.98",
   364                "1624438.00"
   365              ]
   366            ]
   367          }
   368        }
   369      }`)
   370  
   371  	var num []string
   372  	n, e := Get(data, "data", "sz002024", "qfqday", 0)
   373  	if e != nil {
   374  		t.Fatal(e)
   375  	}
   376  
   377  	arr, _ := n.Array()
   378  	for _, v := range arr {
   379  		s := v.(string)
   380  		num = append(num, s)
   381  	}
   382  	if fmt.Sprintf("%v", num) != "[2014-01-02 8.93 9.03 9.17 8.88 621143.00]" {
   383  		t.Fatalf("invalid result")
   384  	}
   385  }
   386  
   387  var exampleJSON = `{
   388      "widget": {
   389          "debug": "on",
   390          "window": {
   391              "title": "Sample Konfabulator Widget",
   392              "name": "main_window",
   393              "width": 500,
   394              "height": 500
   395          },
   396          "image": {
   397              "src": "Images/Sun.png",
   398              "hOffset": 250,
   399              "vOffset": 250,
   400              "alignment": "center"
   401          },
   402          "text": {
   403              "data": "Click Here",
   404              "size": 36,
   405              "style": "bold",
   406              "vOffset": 100,
   407              "alignment": "center",
   408              "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
   409          }
   410      }
   411  }`
   412  
   413  func TestUnmarshalMap(t *testing.T) {
   414  	n, err := Parse(exampleJSON)
   415  	if err != nil || n == nil {
   416  		t.Fatal(err)
   417  	}
   418  	m1, _ := n.Map()
   419  	var m2 map[string]interface{}
   420  	if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
   421  		t.Fatal(err)
   422  	}
   423  	b1, err := json.Marshal(m1)
   424  	if err != nil {
   425  		t.Fatal(err)
   426  	}
   427  	b2, err := json.Marshal(m2)
   428  	if err != nil {
   429  		t.Fatal(err)
   430  	}
   431  	if !bytes.Equal(b1, b2) {
   432  		t.Fatalf("b1 != b2\n b1: %v\nb2: %v", string(b1), string(b2))
   433  	}
   434  }
   435  
   436  func GetMany(src2 string, path ...string) (ret []string) {
   437  	src := []byte(src2)
   438  	for _, p := range path {
   439  		pathes := strings.Split(p, ".")
   440  		if len(pathes) == 0 {
   441  			panic(fmt.Sprintf("invalid path: %v", p))
   442  		}
   443  		ps := make([]interface{}, 0, len(pathes))
   444  		for _, p := range pathes {
   445  			ps = append(ps, p)
   446  		}
   447  		n, e := Get(src, ps...)
   448  		if e != nil {
   449  			ret = append(ret, "")
   450  			continue
   451  		}
   452  		x, _ := n.Interface()
   453  		ret = append(ret, fmt.Sprintf("%v", x))
   454  	}
   455  	return
   456  }
   457  
   458  func get(str string, path string) *ast.Node {
   459  	src := []byte(str)
   460  	pathes := strings.Split(path, ".")
   461  	if len(pathes) == 0 {
   462  		panic(fmt.Sprintf("invalid path: %v", path))
   463  	}
   464  	ps := make([]interface{}, 0, len(pathes))
   465  	for _, p := range pathes {
   466  		ps = append(ps, p)
   467  	}
   468  	n, e := Get(src, ps...)
   469  	if e != nil {
   470  		return nil
   471  	}
   472  	return &n
   473  }
   474  
   475  func TestSingleArrayValue(t *testing.T) {
   476  	var data = []byte(`{"key": "value","key2":[1,2,3,4,"A"]}`)
   477  	array, _ := get(string(data), "key2").Array()
   478  	if len(array) != 5 {
   479  		t.Fatalf("got '%v', expected '%v'", len(array), 5)
   480  	}
   481  
   482  	_, e := Get(data, "key3")
   483  	if e == nil {
   484  		t.Fatalf("got '%v', expected '%v'", e, nil)
   485  	}
   486  }
   487  
   488  var manyJSON = `  {
   489      "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   490          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   491          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   492          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   493          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   494          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
   495          "a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"hello":"world"
   496          }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
   497          "position":{"type":"Point","coordinates":[-115.24,33.09]},
   498          "loves":["world peace"],
   499          "name":{"last":"Anderson","first":"Nancy"},
   500          "age":31,
   501          "x":{"a":"emptya","b":"emptyb"},
   502          "name_last":"Yellow",
   503          "name_first":"Cat",
   504  }`
   505  
   506  func TestManyBasic(t *testing.T) {
   507  	testMany := func(shouldFallback bool, expect string, paths ...string) {
   508  		println()
   509  		rs := GetMany(
   510  			manyJSON,
   511  			paths...,
   512  		)
   513  		// if len(rs) != len(paths) {
   514  		//     t.Fatalf("expected %v, got %v", len(paths), len(rs))
   515  		// }
   516  		var results = "[" + strings.Join(rs, " ") + "]"
   517  		if results != expect {
   518  			fmt.Printf("%v\n", paths)
   519  			t.Fatalf("expected %v, got %v", expect, results)
   520  		}
   521  	}
   522  	testMany(false, "[Point]", "position.type")
   523  	testMany(false, `[emptya [world peace] 31]`, "x.a", "loves", "age")
   524  	testMany(false, `[[world peace]]`, "loves")
   525  	testMany(false, `[map[first:Nancy last:Anderson] Nancy]`, "name",
   526  		"name.first")
   527  	testMany(true, `[]`, strings.Repeat("a.", 40)+"hello")
   528  	res := get(manyJSON, strings.Repeat("a.", 48)+"a")
   529  	assertCond(res != nil)
   530  	x, _ := res.Interface()
   531  	testMany(true, "["+fmt.Sprint(x)+"]", strings.Repeat("a.", 48)+"a")
   532  	// these should fallback
   533  	testMany(true, `[Cat Nancy]`, "name_first", "name.first")
   534  	testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
   535  }
   536  
   537  func testMany(t *testing.T, json string, paths, expected []string) {
   538  	testManyAny(t, json, paths, expected)
   539  	testManyAny(t, json, paths, expected)
   540  }
   541  
   542  func testManyAny(t *testing.T, json string, paths, expected []string) {
   543  	var result []string
   544  	for i := 0; i < 2; i++ {
   545  		var which string
   546  		if i == 0 {
   547  			which = "Get"
   548  			result = nil
   549  			for j := 0; j < len(expected); j++ {
   550  				x, _ := get(json, paths[j]).Interface()
   551  				result = append(result, fmt.Sprintf("%v", x))
   552  			}
   553  		} else if i == 1 {
   554  			which = "GetMany"
   555  			result = GetMany(json, paths...)
   556  		}
   557  		if result == nil {
   558  			panic("result is nil")
   559  		}
   560  		for j := 0; j < len(expected); j++ {
   561  			if result[j] != expected[j] {
   562  				t.Fatalf("Using key '%s' for '%s'\nexpected '%v', got '%v'",
   563  					paths[j], which, expected[j], result[j])
   564  			}
   565  		}
   566  	}
   567  }
   568  
   569  func TestNested(t *testing.T) {
   570  	data := `{ "name": "FirstName", "name1": "FirstName1", ` +
   571  		`"address": "address1", "addressDetails": "address2", }`
   572  	paths := []string{"name", "name1", "address", "addressDetails"}
   573  	expected := []string{"FirstName", "FirstName1", "address1", "address2"}
   574  	t.Run("SingleMany", func(t *testing.T) {
   575  		testMany(t, data, paths,
   576  			expected)
   577  	})
   578  }
   579  
   580  func TestMultiLevelFields(t *testing.T) {
   581  	data := `{ "Level1Field1":3, 
   582                 "Level1Field4":4, 
   583                 "Level1Field2":{ "Level2Field1":[ "value1", "value2" ], 
   584                 "Level2Field2":{ "Level3Field1":[ { "key1":"value1" } ] } } }`
   585  	paths := []string{"Level1Field1", "Level1Field2.Level2Field1",
   586  		"Level1Field2.Level2Field2.Level3Field1", "Level1Field4"}
   587  	expected := []string{"3", `[value1 value2]`,
   588  		`[map[key1:value1]]`, "4"}
   589  	t.Run("SingleMany", func(t *testing.T) {
   590  		testMany(t, data, paths,
   591  			expected)
   592  	})
   593  }
   594  
   595  func TestRandomMany(t *testing.T) {
   596  	var lstr string
   597  	defer func() {
   598  		if v := recover(); v != nil {
   599  			println("'" + hex.EncodeToString([]byte(lstr)) + "'")
   600  			println("'" + lstr + "'")
   601  			panic(v)
   602  		}
   603  	}()
   604  	rand.Seed(time.Now().UnixNano())
   605  	b := make([]byte, 512)
   606  	for i := 0; i < 5000; i++ {
   607  		n, err := rand.Read(b[:rand.Int()%len(b)])
   608  		if err != nil {
   609  			t.Fatal(err)
   610  		}
   611  		lstr = string(b[:n])
   612  		paths := make([]string, rand.Int()%64)
   613  		for i := range paths {
   614  			var b []byte
   615  			n := rand.Int() % 5
   616  			for j := 0; j < n; j++ {
   617  				if j > 0 {
   618  					b = append(b, '.')
   619  				}
   620  				nn := rand.Int() % 10
   621  				for k := 0; k < nn; k++ {
   622  					b = append(b, 'a'+byte(rand.Int()%26))
   623  				}
   624  			}
   625  			paths[i] = string(b)
   626  		}
   627  		GetMany(lstr, paths...)
   628  	}
   629  }
   630  
   631  func TestGetMany(t *testing.T) {
   632  	data := `{"bar": {"id": 99, "mybar": "my mybar" }, "foo": ` +
   633  		`{"myfoo": [605]}}`
   634  	paths := []string{"foo.myfoo", "bar.id", "bar.mybar", "bar.mybarx"}
   635  	expected := []string{"[605]", "99", "my mybar", ""}
   636  	results := GetMany(data, paths...)
   637  	if len(expected) != len(results) {
   638  		t.Fatalf("expected %v, got %v", len(expected), len(results))
   639  	}
   640  	for i, path := range paths {
   641  		if results[i] != expected[i] {
   642  			t.Fatalf("expected '%v', got '%v' for path '%v'", expected[i],
   643  				results[i], path)
   644  		}
   645  	}
   646  }
   647  
   648  func TestGetMany2(t *testing.T) {
   649  	data := `{"bar": {"id": 99, "xyz": "my xyz"}, "foo": {"myfoo": [605]}}`
   650  	paths := []string{"foo.myfoo", "bar.id", "bar.xyz", "bar.abc"}
   651  	expected := []string{"[605]", "99", "my xyz", ""}
   652  	results := GetMany(data, paths...)
   653  	if len(expected) != len(results) {
   654  		t.Fatalf("expected %v, got %v", len(expected), len(results))
   655  	}
   656  	for i, path := range paths {
   657  		if results[i] != expected[i] {
   658  			t.Fatalf("expected '%v', got '%v' for path '%v'", expected[i],
   659  				results[i], path)
   660  		}
   661  	}
   662  }
   663  
   664  func TestNullArray(t *testing.T) {
   665  	n, _ := get(`{"data":null}`, "data").Interface()
   666  	if n != nil {
   667  		t.Fatalf("expected '%v', got '%v'", nil, n)
   668  	}
   669  	n = get(`{}`, "data")
   670  	if reflect.DeepEqual(n, nil) {
   671  		t.Fatalf("expected '%v', got '%v'", nil, n)
   672  	}
   673  	n = get(`{"data":[]}`, "data")
   674  	if reflect.DeepEqual(n, &ast.Node{}) {
   675  		t.Fatalf("expected '%v', got '%v'", nil, n)
   676  	}
   677  	arr, _ := get(`{"data":[null]}`, "data").Array()
   678  	n = len(arr)
   679  	if n != 1 {
   680  		t.Fatalf("expected '%v', got '%v'", 1, n)
   681  	}
   682  }
   683  
   684  func TestGetMany3(t *testing.T) {
   685  	var r []string
   686  	data := `{"MarketName":null,"Nounce":6115}`
   687  	r = GetMany(data, "Nounce", "Buys", "Sells", "Fills")
   688  	if strings.Replace(fmt.Sprintf("%v", r), " ", "", -1) != "[6115]" {
   689  		t.Fatalf("expected '%v', got '%v'", "[6115]",
   690  			strings.Replace(fmt.Sprintf("%v", r), " ", "", -1))
   691  	}
   692  	r = GetMany(data, "Nounce", "Buys", "Sells")
   693  	if strings.Replace(fmt.Sprintf("%v", r), " ", "", -1) != "[6115]" {
   694  		t.Fatalf("expected '%v', got '%v'", "[6115]",
   695  			strings.Replace(fmt.Sprintf("%v", r), " ", "", -1))
   696  	}
   697  	r = GetMany(data, "Nounce")
   698  	if strings.Replace(fmt.Sprintf("%v", r), " ", "", -1) != "[6115]" {
   699  		t.Fatalf("expected '%v', got '%v'", "[6115]",
   700  			strings.Replace(fmt.Sprintf("%v", r), " ", "", -1))
   701  	}
   702  }
   703  
   704  func TestGetMany4(t *testing.T) {
   705  	data := `{"one": {"two": 2, "three": 3}, "four": 4, "five": 5}`
   706  	results := GetMany(data, "four", "five", "one.two", "one.six")
   707  	expected := []string{"4", "5", "2", ""}
   708  	for i, r := range results {
   709  		if r != expected[i] {
   710  			t.Fatalf("expected %v, got %v", expected[i], r)
   711  		}
   712  	}
   713  }
   714  
   715  func TestGetNotExist(t *testing.T) {
   716  	var dataStr = `{"m1":{"m2":3}}`
   717  	ret, err := GetFromString(dataStr, "not_exist", "m3")
   718  	if err == nil || ret.Exists() {
   719  		t.Fatal("Get exist!")
   720  	}
   721  	if ret.Type() != ast.V_NONE {
   722  		t.Fatal(ret.Type())
   723  	}
   724  	ret, err = GetFromString(dataStr)
   725  	if !ret.IsRaw() || ret.Type() != ast.V_OBJECT {
   726  		t.Fatal(ret.Type())
   727  	}
   728  	v11 := ret.Get("not_exist")
   729  	if v11.Exists() {
   730  		t.Fatal()
   731  	}
   732  	v2 := ret.GetByPath("m1", "m2")
   733  	if !v2.Exists() || !v2.IsRaw() {
   734  		t.Fatal(ret.Type())
   735  	}
   736  	x, _ := v2.Int64()
   737  	if x != 3 {
   738  		t.Fatal(x)
   739  	}
   740  }