gjson/gjson_test.go

1556 lines
40 KiB
Go
Raw Normal View History

2016-08-11 06:07:45 +03:00
package gjson
import (
"bytes"
"encoding/hex"
"encoding/json"
2016-08-22 18:25:33 +03:00
"fmt"
2016-08-11 06:07:45 +03:00
"io"
"math/rand"
"reflect"
2016-08-11 06:07:45 +03:00
"strings"
"testing"
"time"
2016-08-11 20:53:50 +03:00
"github.com/buger/jsonparser"
jsoniter "github.com/json-iterator/go"
2016-08-11 06:07:45 +03:00
"github.com/mailru/easyjson/jlexer"
fflib "github.com/pquerna/ffjson/fflib/v1"
)
// TestRandomData is a fuzzing test that throws random data at the Parse
2016-08-11 06:07:45 +03:00
// function looking for panics.
func TestRandomData(t *testing.T) {
var lstr string
defer func() {
if v := recover(); v != nil {
println("'" + hex.EncodeToString([]byte(lstr)) + "'")
println("'" + lstr + "'")
panic(v)
}
}()
rand.Seed(time.Now().UnixNano())
b := make([]byte, 200)
for i := 0; i < 2000000; i++ {
n, err := rand.Read(b[:rand.Int()%len(b)])
if err != nil {
t.Fatal(err)
}
lstr = string(b[:n])
2016-09-08 18:08:53 +03:00
GetBytes([]byte(lstr), "zzzz")
2016-10-19 03:13:15 +03:00
Parse(lstr)
2016-08-11 06:07:45 +03:00
}
}
func TestRandomValidStrings(t *testing.T) {
rand.Seed(time.Now().UnixNano())
b := make([]byte, 200)
for i := 0; i < 100000; i++ {
n, err := rand.Read(b[:rand.Int()%len(b)])
if err != nil {
t.Fatal(err)
}
sm, err := json.Marshal(string(b[:n]))
if err != nil {
t.Fatal(err)
}
var su string
if err := json.Unmarshal([]byte(sm), &su); err != nil {
t.Fatal(err)
}
token := Get(`{"str":`+string(sm)+`}`, "str")
if token.Type != String || token.Str != su {
println("["+token.Raw+"]", "["+token.Str+"]", "["+su+"]", "["+string(sm)+"]")
t.Fatal("string mismatch")
}
}
}
2017-04-10 05:40:55 +03:00
func TestEmoji(t *testing.T) {
const input = `{"utf8":"Example emoji, KO: \ud83d\udd13, \ud83c\udfc3 OK: \u2764\ufe0f "}`
value := Get(input, "utf8")
var s string
json.Unmarshal([]byte(value.Raw), &s)
if value.String() != s {
t.Fatalf("expected '%v', got '%v'", s, value.String())
}
}
2016-08-12 04:51:29 +03:00
func testEscapePath(t *testing.T, json, path, expect string) {
if Get(json, path).String() != expect {
t.Fatalf("expected '%v', got '%v'", expect, Get(json, path).String())
}
}
func TestEscapePath(t *testing.T) {
json := `{
"test":{
"*":"valZ",
"*v":"val0",
"keyv*":"val1",
"key*v":"val2",
"keyv?":"val3",
"key?v":"val4",
"keyv.":"val5",
"key.v":"val6",
"keyk*":{"key?":"val7"}
}
}`
testEscapePath(t, json, "test.\\*", "valZ")
testEscapePath(t, json, "test.\\*v", "val0")
testEscapePath(t, json, "test.keyv\\*", "val1")
testEscapePath(t, json, "test.key\\*v", "val2")
testEscapePath(t, json, "test.keyv\\?", "val3")
testEscapePath(t, json, "test.key\\?v", "val4")
testEscapePath(t, json, "test.keyv\\.", "val5")
testEscapePath(t, json, "test.key\\.v", "val6")
testEscapePath(t, json, "test.keyk\\*.key\\?", "val7")
}
2016-08-11 06:07:45 +03:00
// this json block is poorly formed on purpose.
var basicJSON = `{"age":100, "name":{"here":"B\\\"R"},
"noop":{"what is a wren?":"a bird"},
"happy":true,"immortal":false,
2016-08-15 14:56:55 +03:00
"items":[1,2,3,{"tags":[1,2,3],"points":[[1,2],[3,4]]},4,5,6,7],
2016-08-11 06:07:45 +03:00
"arr":["1",2,"3",{"hello":"world"},"4",5],
"vals":[1,2,3,{"sadf":sdf"asdf"}],"name":{"first":"tom","last":null},
2017-04-15 03:58:25 +03:00
"created":"2014-05-16T08:28:06.989Z",
"loggy":{
"programmers": [
{
"firstName": "Brett",
"lastName": "McLaughlin",
"email": "aaaa",
"tag": "good"
},
{
"firstName": "Jason",
"lastName": "Hunter",
"email": "bbbb",
"tag": "bad"
},
{
"firstName": "Elliotte",
"lastName": "Harold",
"email": "cccc",
"tag":, "good"
},
{
2016-08-31 23:38:53 +03:00
"firstName": 1002.3,
"age": 101
}
]
2017-04-11 18:54:19 +03:00
},
"lastly":{"yay":"final"}
}`
2016-09-08 18:08:53 +03:00
var basicJSONB = []byte(basicJSON)
2017-04-15 03:58:25 +03:00
func TestTimeResult(t *testing.T) {
assert(t, Get(basicJSON, "created").String() == Get(basicJSON, "created").Time().Format(time.RFC3339Nano))
}
2017-04-11 18:54:19 +03:00
func TestParseAny(t *testing.T) {
assert(t, Parse("100").Float() == 100)
assert(t, Parse("true").Bool())
assert(t, Parse("valse").Bool() == false)
}
func TestManyVariousPathCounts(t *testing.T) {
json := `{"a":"a","b":"b","c":"c"}`
counts := []int{3, 4, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257, 511, 512, 513}
paths := []string{"a", "b", "c"}
expects := []string{"a", "b", "c"}
for _, count := range counts {
var gpaths []string
var gexpects []string
for i := 0; i < count; i++ {
if i < len(paths) {
gpaths = append(gpaths, paths[i])
gexpects = append(gexpects, expects[i])
} else {
gpaths = append(gpaths, fmt.Sprintf("not%d", i))
gexpects = append(gexpects, "null")
}
}
results := GetMany(json, gpaths...)
for i := 0; i < len(paths); i++ {
if results[i].String() != expects[i] {
t.Fatalf("expected '%v', got '%v'", expects[i], results[i].String())
}
}
}
}
func TestManyRecursion(t *testing.T) {
var json string
var path string
for i := 0; i < 100; i++ {
json += `{"a":`
path += ".a"
}
json += `"b"`
for i := 0; i < 100; i++ {
json += `}`
}
path = path[1:]
assert(t, GetMany(json, path)[0].String() == "b")
}
2016-09-08 18:08:53 +03:00
func TestByteSafety(t *testing.T) {
2016-09-08 18:34:01 +03:00
jsonb := []byte(`{"name":"Janet","age":38}`)
2016-09-08 18:08:53 +03:00
mtok := GetBytes(jsonb, "name")
if mtok.String() != "Janet" {
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
}
2016-09-08 18:34:01 +03:00
mtok2 := GetBytes(jsonb, "age")
if mtok2.Raw != "38" {
t.Fatalf("expected %v, got %v", "Jason", mtok2.Raw)
}
2016-09-08 18:08:53 +03:00
jsonb[9] = 'T'
jsonb[12] = 'd'
jsonb[13] = 'y'
if mtok.String() != "Janet" {
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
}
}
2016-08-11 06:07:45 +03:00
2016-09-08 19:02:40 +03:00
func get(json, path string) Result {
2017-04-11 18:54:19 +03:00
return GetBytes([]byte(json), path)
2016-09-08 19:02:40 +03:00
}
2016-08-11 06:07:45 +03:00
func TestBasic(t *testing.T) {
var mtok Result
mtok = get(basicJSON, `loggy.programmers.#[tag="good"].firstName`)
if mtok.String() != "Brett" {
t.Fatalf("expected %v, got %v", "Brett", mtok.String())
}
mtok = get(basicJSON, `loggy.programmers.#[tag="good"]#.firstName`)
if mtok.String() != `["Brett","Elliotte"]` {
t.Fatalf("expected %v, got %v", `["Brett","Elliotte"]`, mtok.String())
}
2017-04-11 06:45:34 +03:00
}
2017-04-11 18:54:19 +03:00
func TestTypes(t *testing.T) {
assert(t, (Result{Type: String}).Type.String() == "String")
assert(t, (Result{Type: Number}).Type.String() == "Number")
assert(t, (Result{Type: Null}).Type.String() == "Null")
assert(t, (Result{Type: False}).Type.String() == "False")
assert(t, (Result{Type: True}).Type.String() == "True")
assert(t, (Result{Type: JSON}).Type.String() == "JSON")
assert(t, (Result{Type: 100}).Type.String() == "")
// bool
assert(t, (Result{Type: String, Str: "true"}).Bool())
assert(t, (Result{Type: True}).Bool())
assert(t, (Result{Type: False}).Bool() == false)
assert(t, (Result{Type: Number, Num: 1}).Bool())
// int
assert(t, (Result{Type: String, Str: "1"}).Int() == 1)
assert(t, (Result{Type: True}).Int() == 1)
assert(t, (Result{Type: False}).Int() == 0)
assert(t, (Result{Type: Number, Num: 1}).Int() == 1)
// uint
assert(t, (Result{Type: String, Str: "1"}).Uint() == 1)
assert(t, (Result{Type: True}).Uint() == 1)
assert(t, (Result{Type: False}).Uint() == 0)
assert(t, (Result{Type: Number, Num: 1}).Uint() == 1)
// float
assert(t, (Result{Type: String, Str: "1"}).Float() == 1)
assert(t, (Result{Type: True}).Float() == 1)
assert(t, (Result{Type: False}).Float() == 0)
assert(t, (Result{Type: Number, Num: 1}).Float() == 1)
}
func TestForEach(t *testing.T) {
Result{}.ForEach(nil)
Result{Type: String, Str: "Hello"}.ForEach(func(_, value Result) bool {
assert(t, value.String() == "Hello")
return false
})
Result{Type: JSON, Raw: "*invalid*"}.ForEach(nil)
json := ` {"name": {"first": "Janet","last": "Prichard"},
"asd\nf":"\ud83d\udd13","age": 47}`
var count int
ParseBytes([]byte(json)).ForEach(func(key, value Result) bool {
count++
return true
})
assert(t, count == 3)
ParseBytes([]byte(`{"bad`)).ForEach(nil)
ParseBytes([]byte(`{"ok":"bad`)).ForEach(nil)
}
func TestMap(t *testing.T) {
assert(t, len(ParseBytes([]byte(`"asdf"`)).Map()) == 0)
assert(t, ParseBytes([]byte(`{"asdf":"ghjk"`)).Map()["asdf"].String() == "ghjk")
assert(t, len(Result{Type: JSON, Raw: "**invalid**"}.Map()) == 0)
assert(t, Result{Type: JSON, Raw: "**invalid**"}.Value() == nil)
assert(t, Result{Type: JSON, Raw: "{"}.Map() != nil)
}
2017-04-11 06:45:34 +03:00
func TestBasic1(t *testing.T) {
mtok := get(basicJSON, `loggy.programmers`)
2016-11-30 20:50:59 +03:00
var count int
mtok.ForEach(func(key, value Result) bool {
if key.Exists() {
t.Fatalf("expected %v, got %v", false, key.Exists())
}
count++
if count == 3 {
return false
}
if count == 1 {
i := 0
value.ForEach(func(key, value Result) bool {
switch i {
case 0:
if key.String() != "firstName" || value.String() != "Brett" {
t.Fatalf("expected %v/%v got %v/%v", "firstName", "Brett", key.String(), value.String())
}
case 1:
if key.String() != "lastName" || value.String() != "McLaughlin" {
t.Fatalf("expected %v/%v got %v/%v", "lastName", "McLaughlin", key.String(), value.String())
}
case 2:
if key.String() != "email" || value.String() != "aaaa" {
t.Fatalf("expected %v/%v got %v/%v", "email", "aaaa", key.String(), value.String())
}
}
i++
return true
})
}
return true
})
if count != 3 {
t.Fatalf("expected %v, got %v", 3, count)
}
2017-04-11 06:45:34 +03:00
}
func TestBasic2(t *testing.T) {
mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`)
2016-09-08 18:08:53 +03:00
if mtok.String() != "1002.3" {
t.Fatalf("expected %v, got %v", "1002.3", mtok.String())
2016-09-08 18:08:53 +03:00
}
2016-12-01 00:38:08 +03:00
mtok = get(basicJSON, `loggy.programmers.#[firstName != "Brett"].firstName`)
if mtok.String() != "Jason" {
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
}
2016-12-01 00:32:17 +03:00
mtok = get(basicJSON, `loggy.programmers.#[firstName % "Bre*"].email`)
if mtok.String() != "aaaa" {
t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
}
2016-09-08 19:02:40 +03:00
mtok = get(basicJSON, `loggy.programmers.#[firstName == "Brett"].email`)
2016-08-31 23:23:20 +03:00
if mtok.String() != "aaaa" {
t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
}
2016-09-08 19:02:40 +03:00
mtok = get(basicJSON, "loggy")
if mtok.Type != JSON {
t.Fatalf("expected %v, got %v", JSON, mtok.Type)
}
if len(mtok.Map()) != 1 {
t.Fatalf("expected %v, got %v", 1, len(mtok.Map()))
}
programmers := mtok.Map()["programmers"]
if programmers.Array()[1].Map()["firstName"].Str != "Jason" {
t.Fatalf("expected %v, got %v", "Jason", mtok.Map()["programmers"].Array()[1].Map()["firstName"].Str)
}
2017-04-11 06:45:34 +03:00
}
func TestBasic3(t *testing.T) {
var mtok Result
if Parse(basicJSON).Get("loggy.programmers").Get("1").Get("firstName").Str != "Jason" {
t.Fatalf("expected %v, got %v", "Jason", Parse(basicJSON).Get("loggy.programmers").Get("1").Get("firstName").Str)
}
2016-08-11 06:07:45 +03:00
var token Result
if token = Parse("-102"); token.Num != -102 {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", -102, token.Num)
}
if token = Parse("102"); token.Num != 102 {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", 102, token.Num)
}
if token = Parse("102.2"); token.Num != 102.2 {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", 102.2, token.Num)
}
if token = Parse(`"hello"`); token.Str != "hello" {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", "hello", token.Str)
}
if token = Parse(`"\"he\nllo\""`); token.Str != "\"he\nllo\"" {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", "\"he\nllo\"", token.Str)
}
2016-09-08 19:02:40 +03:00
mtok = get(basicJSON, "loggy.programmers.#.firstName")
if len(mtok.Array()) != 4 {
t.Fatalf("expected 4, got %v", len(mtok.Array()))
}
for i, ex := range []string{"Brett", "Jason", "Elliotte", "1002.3"} {
if mtok.Array()[i].String() != ex {
t.Fatalf("expected '%v', got '%v'", ex, mtok.Array()[i].String())
}
}
2016-09-08 19:02:40 +03:00
mtok = get(basicJSON, "loggy.programmers.#.asd")
if mtok.Type != JSON {
2017-04-10 21:41:19 +03:00
t.Fatalf("expected %v, got %v", JSON, mtok.Type)
}
if len(mtok.Array()) != 0 {
t.Fatalf("expected 0, got %v", len(mtok.Array()))
}
2017-04-11 06:45:34 +03:00
}
func TestBasic4(t *testing.T) {
2016-09-08 19:02:40 +03:00
if get(basicJSON, "items.3.tags.#").Num != 3 {
t.Fatalf("expected 3, got %v", get(basicJSON, "items.3.tags.#").Num)
2016-08-15 14:56:55 +03:00
}
2016-09-08 19:02:40 +03:00
if get(basicJSON, "items.3.points.1.#").Num != 2 {
t.Fatalf("expected 2, got %v", get(basicJSON, "items.3.points.1.#").Num)
2016-08-15 14:56:55 +03:00
}
2016-09-08 19:02:40 +03:00
if get(basicJSON, "items.#").Num != 8 {
t.Fatalf("expected 6, got %v", get(basicJSON, "items.#").Num)
2016-08-15 14:56:55 +03:00
}
2016-09-08 19:02:40 +03:00
if get(basicJSON, "vals.#").Num != 4 {
t.Fatalf("expected 4, got %v", get(basicJSON, "vals.#").Num)
2016-08-15 14:56:55 +03:00
}
2016-09-08 19:02:40 +03:00
if !get(basicJSON, "name.last").Exists() {
2016-08-12 18:39:08 +03:00
t.Fatal("expected true, got false")
}
2017-04-11 06:45:34 +03:00
token := get(basicJSON, "name.here")
2016-08-11 06:07:45 +03:00
if token.String() != "B\\\"R" {
t.Fatal("expecting 'B\\\"R'", "got", token.String())
}
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "arr.#")
2016-08-11 06:07:45 +03:00
if token.String() != "6" {
t.Fatal("expecting '6'", "got", token.String())
}
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "arr.3.hello")
2016-08-11 06:07:45 +03:00
if token.String() != "world" {
t.Fatal("expecting 'world'", "got", token.String())
}
_ = token.Value().(string)
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "name.first")
2016-08-11 06:07:45 +03:00
if token.String() != "tom" {
t.Fatal("expecting 'tom'", "got", token.String())
}
_ = token.Value().(string)
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "name.last")
if token.String() != "" {
t.Fatal("expecting ''", "got", token.String())
2016-08-11 06:07:45 +03:00
}
if token.Value() != nil {
t.Fatal("should be nil")
}
2017-04-11 06:45:34 +03:00
}
func TestBasic5(t *testing.T) {
token := get(basicJSON, "age")
2016-08-11 06:07:45 +03:00
if token.String() != "100" {
t.Fatal("expecting '100'", "got", token.String())
}
_ = token.Value().(float64)
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "happy")
2016-08-11 06:07:45 +03:00
if token.String() != "true" {
t.Fatal("expecting 'true'", "got", token.String())
}
_ = token.Value().(bool)
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "immortal")
2016-08-11 06:07:45 +03:00
if token.String() != "false" {
t.Fatal("expecting 'false'", "got", token.String())
}
_ = token.Value().(bool)
2016-09-08 19:02:40 +03:00
token = get(basicJSON, "noop")
2016-08-11 06:07:45 +03:00
if token.String() != `{"what is a wren?":"a bird"}` {
t.Fatal("expecting '"+`{"what is a wren?":"a bird"}`+"'", "got", token.String())
}
_ = token.Value().(map[string]interface{})
2016-08-11 06:07:45 +03:00
2016-09-08 19:02:40 +03:00
if get(basicJSON, "").Value() != nil {
2016-08-11 06:07:45 +03:00
t.Fatal("should be nil")
}
2016-09-08 19:02:40 +03:00
get(basicJSON, "vals.hello")
mm := Parse(basicJSON).Value().(map[string]interface{})
fn := mm["loggy"].(map[string]interface{})["programmers"].([]interface{})[1].(map[string]interface{})["firstName"].(string)
if fn != "Jason" {
t.Fatalf("expecting %v, got %v", "Jason", fn)
}
2016-08-11 06:07:45 +03:00
}
2016-08-24 23:26:44 +03:00
func TestUnicode(t *testing.T) {
var json = `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
if Get(json, "的情况下解.key").Num != 1 {
t.Fatal("fail")
}
if Get(json, "的情况下解.的情况").Num != 2 {
t.Fatal("fail")
}
if Get(json, "的情况下解.的?况").Num != 2 {
t.Fatal("fail")
}
if Get(json, "的情况下解.的?*").Num != 2 {
t.Fatal("fail")
}
if Get(json, "的情况下解.*?况").Num != 2 {
t.Fatal("fail")
}
if Get(json, "的情?下解.*?况").Num != 2 {
t.Fatal("fail")
}
if Get(json, "的情下解.*?况").Num != 0 {
t.Fatal("fail")
}
}
2016-08-25 01:50:18 +03:00
2016-08-11 06:07:45 +03:00
func TestUnescape(t *testing.T) {
unescape(string([]byte{'\\', '\\', 0}))
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
}
func assert(t testing.TB, cond bool) {
if !cond {
t.Fatal("assert failed")
}
}
func TestLess(t *testing.T) {
assert(t, !Result{Type: Null}.Less(Result{Type: Null}, true))
assert(t, Result{Type: Null}.Less(Result{Type: False}, true))
assert(t, Result{Type: Null}.Less(Result{Type: True}, true))
assert(t, Result{Type: Null}.Less(Result{Type: JSON}, true))
assert(t, Result{Type: Null}.Less(Result{Type: Number}, true))
assert(t, Result{Type: Null}.Less(Result{Type: String}, true))
assert(t, !Result{Type: False}.Less(Result{Type: Null}, true))
assert(t, Result{Type: False}.Less(Result{Type: True}, true))
assert(t, Result{Type: String, Str: "abc"}.Less(Result{Type: String, Str: "bcd"}, true))
assert(t, Result{Type: String, Str: "ABC"}.Less(Result{Type: String, Str: "abc"}, true))
assert(t, !Result{Type: String, Str: "ABC"}.Less(Result{Type: String, Str: "abc"}, false))
assert(t, Result{Type: Number, Num: 123}.Less(Result{Type: Number, Num: 456}, true))
assert(t, !Result{Type: Number, Num: 456}.Less(Result{Type: Number, Num: 123}, true))
assert(t, !Result{Type: Number, Num: 456}.Less(Result{Type: Number, Num: 456}, true))
assert(t, stringLessInsensitive("abcde", "BBCDE"))
assert(t, stringLessInsensitive("abcde", "bBCDE"))
assert(t, stringLessInsensitive("Abcde", "BBCDE"))
assert(t, stringLessInsensitive("Abcde", "bBCDE"))
assert(t, !stringLessInsensitive("bbcde", "aBCDE"))
assert(t, !stringLessInsensitive("bbcde", "ABCDE"))
assert(t, !stringLessInsensitive("Bbcde", "aBCDE"))
assert(t, !stringLessInsensitive("Bbcde", "ABCDE"))
assert(t, !stringLessInsensitive("abcde", "ABCDE"))
assert(t, !stringLessInsensitive("Abcde", "ABCDE"))
assert(t, !stringLessInsensitive("abcde", "ABCDE"))
assert(t, !stringLessInsensitive("ABCDE", "ABCDE"))
assert(t, !stringLessInsensitive("abcde", "abcde"))
assert(t, !stringLessInsensitive("123abcde", "123Abcde"))
assert(t, !stringLessInsensitive("123Abcde", "123Abcde"))
assert(t, !stringLessInsensitive("123Abcde", "123abcde"))
assert(t, !stringLessInsensitive("123abcde", "123abcde"))
assert(t, !stringLessInsensitive("124abcde", "123abcde"))
assert(t, !stringLessInsensitive("124Abcde", "123Abcde"))
assert(t, !stringLessInsensitive("124Abcde", "123abcde"))
assert(t, !stringLessInsensitive("124abcde", "123abcde"))
assert(t, stringLessInsensitive("124abcde", "125abcde"))
assert(t, stringLessInsensitive("124Abcde", "125Abcde"))
assert(t, stringLessInsensitive("124Abcde", "125abcde"))
assert(t, stringLessInsensitive("124abcde", "125abcde"))
}
2016-08-22 18:25:33 +03:00
func TestIssue6(t *testing.T) {
data := `{
"code": 0,
"msg": "",
"data": {
"sz002024": {
"qfqday": [
[
"2014-01-02",
"8.93",
"9.03",
"9.17",
"8.88",
"621143.00"
],
[
"2014-01-03",
"9.03",
"9.30",
"9.47",
"8.98",
"1624438.00"
]
]
}
}
}`
var num []string
for _, v := range Get(data, "data.sz002024.qfqday.0").Array() {
num = append(num, v.String())
}
2016-08-22 18:26:44 +03:00
if fmt.Sprintf("%v", num) != "[2014-01-02 8.93 9.03 9.17 8.88 621143.00]" {
t.Fatalf("invalid result")
}
2016-08-22 18:25:33 +03:00
}
2016-08-19 21:22:59 +03:00
var exampleJSON = `{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
2016-08-19 21:22:59 +03:00
"src": "Images/Sun.png",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
2016-08-11 06:07:45 +03:00
}
}
2016-08-19 21:22:59 +03:00
}`
2016-08-11 06:07:45 +03:00
func TestNewParse(t *testing.T) {
//fmt.Printf("%v\n", parse2(exampleJSON, "widget").String())
}
2016-08-25 01:59:54 +03:00
func TestUnmarshalMap(t *testing.T) {
var m1 = Parse(exampleJSON).Value().(map[string]interface{})
var m2 map[string]interface{}
if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
t.Fatal(err)
}
b1, err := json.Marshal(m1)
if err != nil {
t.Fatal(err)
}
b2, err := json.Marshal(m2)
if err != nil {
t.Fatal(err)
}
if bytes.Compare(b1, b2) != 0 {
t.Fatal("b1 != b2")
}
}
func TestSingleArrayValue(t *testing.T) {
var json = `{"key": "value","key2":[1,2,3,4,"A"]}`
var result = Get(json, "key")
var array = result.Array()
if len(array) != 1 {
t.Fatal("array is empty")
}
if array[0].String() != "value" {
2017-04-10 21:41:19 +03:00
t.Fatalf("got %s, should be %s", array[0].String(), "value")
}
array = Get(json, "key2.#").Array()
if len(array) != 1 {
2017-04-10 21:41:19 +03:00
t.Fatalf("got '%v', expected '%v'", len(array), 1)
}
array = Get(json, "key3").Array()
if len(array) != 0 {
2017-04-10 21:41:19 +03:00
t.Fatalf("got '%v', expected '%v'", len(array), 0)
}
}
var manyJSON = ` {
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{
"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"hello":"world"
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
"position":{"type":"Point","coordinates":[-115.24,33.09]},
"loves":["world peace"],
"name":{"last":"Anderson","first":"Nancy"},
"age":31
"":{"a":"emptya","b":"emptyb"},
"name.last":"Yellow",
"name.first":"Cat",
}`
func combine(results []Result) string {
return fmt.Sprintf("%v", results)
}
func TestManyBasic(t *testing.T) {
testWatchForFallback = true
defer func() {
testWatchForFallback = false
}()
testMany := func(shouldFallback bool, expect string, paths ...string) {
2017-04-11 18:54:19 +03:00
results := GetManyBytes(
[]byte(manyJSON),
paths...,
)
if len(results) != len(paths) {
t.Fatalf("expected %v, got %v", len(paths), len(results))
}
if fmt.Sprintf("%v", results) != expect {
fmt.Printf("%v\n", paths)
t.Fatalf("expected %v, got %v", expect, results)
}
2017-04-10 21:41:19 +03:00
//if testLastWasFallback != shouldFallback {
// t.Fatalf("expected %v, got %v", shouldFallback, testLastWasFallback)
//}
}
testMany(false, "[Point]", "position.type")
testMany(false, `[emptya ["world peace"] 31]`, ".a", "loves", "age")
testMany(false, `[["world peace"]]`, "loves")
testMany(false, `[{"last":"Anderson","first":"Nancy"} Nancy]`, "name", "name.first")
testMany(true, `[]`, strings.Repeat("a.", 40)+"hello")
res := Get(manyJSON, strings.Repeat("a.", 48)+"a")
testMany(true, `[`+res.String()+`]`, strings.Repeat("a.", 48)+"a")
// these should fallback
testMany(true, `[Cat Nancy]`, "name\\.first", "name.first")
testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
}
func testMany(t *testing.T, json string, paths, expected []string) {
2017-04-11 18:54:19 +03:00
testManyAny(t, json, paths, expected, true)
testManyAny(t, json, paths, expected, false)
}
func testManyAny(t *testing.T, json string, paths, expected []string, bytes bool) {
var result []Result
for i := 0; i < 2; i++ {
var which string
if i == 0 {
which = "Get"
result = nil
for j := 0; j < len(expected); j++ {
2017-04-11 18:54:19 +03:00
if bytes {
result = append(result, GetBytes([]byte(json), paths[j]))
} else {
result = append(result, Get(json, paths[j]))
}
}
} else if i == 1 {
which = "GetMany"
2017-04-11 18:54:19 +03:00
if bytes {
result = GetManyBytes([]byte(json), paths...)
} else {
result = GetMany(json, paths...)
}
}
for j := 0; j < len(expected); j++ {
if result[j].String() != expected[j] {
t.Fatalf("Using key '%s' for '%s'\nexpected '%v', got '%v'", paths[j], which, expected[j], result[j].String())
}
}
}
}
func TestIssue20(t *testing.T) {
json := `{ "name": "FirstName", "name1": "FirstName1", "address": "address1", "addressDetails": "address2", }`
paths := []string{"name", "name1", "address", "addressDetails"}
expected := []string{"FirstName", "FirstName1", "address1", "address2"}
t.Run("SingleMany", func(t *testing.T) { testMany(t, json, paths, expected) })
}
func TestIssue21(t *testing.T) {
json := `{ "Level1Field1":3,
"Level1Field4":4,
"Level1Field2":{ "Level2Field1":[ "value1", "value2" ],
"Level2Field2":{ "Level3Field1":[ { "key1":"value1" } ] } } }`
paths := []string{"Level1Field1", "Level1Field2.Level2Field1", "Level1Field2.Level2Field2.Level3Field1", "Level1Field4"}
expected := []string{"3", `[ "value1", "value2" ]`, `[ { "key1":"value1" } ]`, "4"}
t.Run("SingleMany", func(t *testing.T) { testMany(t, json, paths, expected) })
}
func TestRandomMany(t *testing.T) {
var lstr string
defer func() {
if v := recover(); v != nil {
println("'" + hex.EncodeToString([]byte(lstr)) + "'")
println("'" + lstr + "'")
panic(v)
}
}()
rand.Seed(time.Now().UnixNano())
b := make([]byte, 512)
for i := 0; i < 50000; i++ {
n, err := rand.Read(b[:rand.Int()%len(b)])
if err != nil {
t.Fatal(err)
}
lstr = string(b[:n])
paths := make([]string, rand.Int()%64)
for i := range paths {
var b []byte
n := rand.Int() % 5
for j := 0; j < n; j++ {
if j > 0 {
b = append(b, '.')
}
nn := rand.Int() % 10
for k := 0; k < nn; k++ {
b = append(b, 'a'+byte(rand.Int()%26))
}
}
paths[i] = string(b)
}
GetMany(lstr, paths...)
}
}
type ComplicatedType struct {
unsettable int
Tagged string `json:"tagged"`
NotTagged bool
Nested struct {
Yellow string `json:"yellow"`
}
NestedTagged struct {
Green string
Map map[string]interface{}
Ints struct {
Int int `json:"int"`
Int8 int8
Int16 int16
Int32 int32
Int64 int64 `json:"int64"`
}
Uints struct {
Uint uint
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
}
Floats struct {
Float64 float64
Float32 float32
}
Byte byte
Bool bool
} `json:"nestedTagged"`
LeftOut string `json:"-"`
SelfPtr *ComplicatedType
SelfSlice []ComplicatedType
SelfSlicePtr []*ComplicatedType
SelfPtrSlice *[]ComplicatedType
Interface interface{} `json:"interface"`
Array [3]int
Time time.Time `json:"time"`
Binary []byte
NonBinary []byte
}
var complicatedJSON = `
{
"tagged": "OK",
"Tagged": "KO",
"NotTagged": true,
"unsettable": 101,
"Nested": {
"Yellow": "Green",
"yellow": "yellow"
},
"nestedTagged": {
"Green": "Green",
"Map": {
"this": "that",
"and": "the other thing"
},
"Ints": {
"Uint": 99,
"Uint16": 16,
"Uint32": 32,
"Uint64": 65
},
"Uints": {
"int": -99,
"Int": -98,
"Int16": -16,
"Int32": -32,
"int64": -64,
"Int64": -65
},
"Uints": {
"Float32": 32.32,
"Float64": 64.64
},
"Byte": 254,
"Bool": true
},
"LeftOut": "you shouldn't be here",
"SelfPtr": {"tagged":"OK","nestedTagged":{"Ints":{"Uint32":32}}},
"SelfSlice": [{"tagged":"OK","nestedTagged":{"Ints":{"Uint32":32}}}],
"SelfSlicePtr": [{"tagged":"OK","nestedTagged":{"Ints":{"Uint32":32}}}],
"SelfPtrSlice": [{"tagged":"OK","nestedTagged":{"Ints":{"Uint32":32}}}],
"interface": "Tile38 Rocks!",
"Interface": "Please Download",
"Array": [0,2,3,4,5],
"time": "2017-05-07T13:24:43-07:00",
"Binary": "R0lGODlhPQBEAPeo",
"NonBinary": [9,3,100,115]
}
`
func TestUnmarshal(t *testing.T) {
var s1 ComplicatedType
var s2 ComplicatedType
if err := json.Unmarshal([]byte(complicatedJSON), &s1); err != nil {
t.Fatal(err)
}
if err := Unmarshal([]byte(complicatedJSON), &s2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(&s1, &s2) {
t.Fatal("not equal")
}
var str string
if err := json.Unmarshal([]byte(Get(complicatedJSON, "LeftOut").Raw), &str); err != nil {
t.Fatal(err)
}
assert(t, str == Get(complicatedJSON, "LeftOut").String())
}
func testvalid(json string, expect bool) {
_, ok := validpayload([]byte(json), 0)
if ok != expect {
panic("mismatch")
}
}
func TestValidBasic(t *testing.T) {
testvalid("0", true)
testvalid("00", false)
testvalid("-00", false)
testvalid("-.", false)
testvalid("0.0", true)
testvalid("10.0", true)
testvalid("10e1", true)
testvalid("10EE", false)
testvalid("10E-", false)
testvalid("10E+", false)
testvalid("10E123", true)
testvalid("10E-123", true)
testvalid("10E-0123", true)
testvalid("", false)
testvalid(" ", false)
testvalid("{}", true)
testvalid("{", false)
testvalid("-", false)
testvalid("-1", true)
testvalid("-1.", false)
testvalid("-1.0", true)
testvalid(" -1.0", true)
testvalid(" -1.0 ", true)
testvalid("-1.0 ", true)
testvalid("-1.0 i", false)
testvalid("-1.0 i", false)
testvalid("true", true)
testvalid(" true", true)
testvalid(" true ", true)
testvalid(" True ", false)
testvalid(" tru", false)
testvalid("false", true)
testvalid(" false", true)
testvalid(" false ", true)
testvalid(" False ", false)
testvalid(" fals", false)
testvalid("null", true)
testvalid(" null", true)
testvalid(" null ", true)
testvalid(" Null ", false)
testvalid(" nul", false)
testvalid(" []", true)
testvalid(" [true]", true)
testvalid(" [ true, null ]", true)
testvalid(" [ true,]", false)
testvalid(`{"hello":"world"}`, true)
testvalid(`{ "hello": "world" }`, true)
testvalid(`{ "hello": "world", }`, false)
testvalid(`{"a":"b",}`, false)
testvalid(`{"a":"b","a"}`, false)
testvalid(`{"a":"b","a":}`, false)
testvalid(`{"a":"b","a":1}`, true)
testvalid(`{"a":"b","a": 1, "c":{"hi":"there"} }`, true)
testvalid(`{"a":"b","a": 1, "c":{"hi":"there", "easy":["going",{"mixed":"bag"}]} }`, true)
testvalid(`""`, true)
testvalid(`"`, false)
testvalid(`"\n"`, true)
testvalid(`"\"`, false)
testvalid(`"\\"`, true)
testvalid(`"a\\b"`, true)
testvalid(`"a\\b\\\"a"`, true)
testvalid(`"a\\b\\\uFFAAa"`, true)
testvalid(`"a\\b\\\uFFAZa"`, false)
testvalid(`"a\\b\\\uFFA"`, false)
testvalid(string(complicatedJSON), true)
testvalid(string(exampleJSON), true)
}
var jsonchars = []string{"{", "[", ",", ":", "}", "]", "1", "0", "true", "false", "null", `""`, `"\""`, `"a"`}
func makeRandomJSONChars(b []byte) {
var bb []byte
for len(bb) < len(b) {
bb = append(bb, jsonchars[rand.Int()%len(jsonchars)]...)
}
copy(b, bb[:len(b)])
}
func TestValidRandom(t *testing.T) {
rand.Seed(time.Now().UnixNano())
b := make([]byte, 100000)
start := time.Now()
for time.Since(start) < time.Second*3 {
n := rand.Int() % len(b)
rand.Read(b[:n])
validpayload(b[:n], 0)
}
start = time.Now()
for time.Since(start) < time.Second*3 {
n := rand.Int() % len(b)
makeRandomJSONChars(b[:n])
validpayload(b[:n], 0)
}
}
2016-08-11 06:07:45 +03:00
type BenchStruct struct {
Widget struct {
Window struct {
Name string `json:"name"`
} `json:"window"`
Image struct {
HOffset int `json:"hOffset"`
} `json:"image"`
Text struct {
OnMouseUp string `json:"onMouseUp"`
} `json:"text"`
} `json:"widget"`
}
var benchPaths = []string{
"widget.window.name",
"widget.image.hOffset",
"widget.text.onMouseUp",
}
var benchManyPaths = []string{
"widget.window.name",
"widget.image.hOffset",
"widget.text.onMouseUp",
"widget.window.title",
"widget.image.alignment",
"widget.text.style",
"widget.window.height",
"widget.image.src",
"widget.text.data",
"widget.text.size",
}
2016-08-11 06:07:45 +03:00
func BenchmarkGJSONGet(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
if Get(exampleJSON, benchPaths[j]).Type == Null {
t.Fatal("did not find the value")
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func BenchmarkGJSONGetMany4Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 4)
}
func BenchmarkGJSONGetMany8Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 8)
}
func BenchmarkGJSONGetMany16Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 16)
}
func BenchmarkGJSONGetMany32Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 32)
}
func BenchmarkGJSONGetMany64Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 64)
}
func BenchmarkGJSONGetMany128Paths(t *testing.B) {
benchmarkGJSONGetManyN(t, 128)
}
func benchmarkGJSONGetManyN(t *testing.B, n int) {
var paths []string
for len(paths) < n {
paths = append(paths, benchManyPaths...)
}
paths = paths[:n]
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
results := GetMany(exampleJSON, paths...)
if len(results) == 0 {
t.Fatal("did not find the value")
}
for j := 0; j < len(results); j++ {
if results[j].Type == Null {
t.Fatal("did not find the value")
}
}
}
t.N *= len(paths) // because we are running against 3 paths
2016-08-11 06:07:45 +03:00
}
func BenchmarkGJSONUnmarshalMap(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
parts := strings.Split(benchPaths[j], ".")
2016-08-27 16:20:43 +03:00
m, _ := Parse(exampleJSON).Value().(map[string]interface{})
var v interface{}
for len(parts) > 0 {
part := parts[0]
if len(parts) > 1 {
m = m[part].(map[string]interface{})
if m == nil {
t.Fatal("did not find the value")
}
} else {
v = m[part]
if v == nil {
t.Fatal("did not find the value")
}
}
parts = parts[1:]
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func BenchmarkGJSONUnmarshalStruct(t *testing.B) {
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
var s BenchStruct
if err := Unmarshal([]byte(exampleJSON), &s); err != nil {
t.Fatal(err)
}
switch benchPaths[j] {
case "widget.window.name":
if s.Widget.Window.Name == "" {
t.Fatal("did not find the value")
}
case "widget.image.hOffset":
if s.Widget.Image.HOffset == 0 {
t.Fatal("did not find the value")
}
case "widget.text.onMouseUp":
if s.Widget.Text.OnMouseUp == "" {
t.Fatal("did not find the value")
}
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
2016-08-11 06:07:45 +03:00
func BenchmarkJSONUnmarshalMap(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
parts := strings.Split(benchPaths[j], ".")
var m map[string]interface{}
if err := json.Unmarshal([]byte(exampleJSON), &m); err != nil {
t.Fatal(err)
}
var v interface{}
for len(parts) > 0 {
part := parts[0]
if len(parts) > 1 {
m = m[part].(map[string]interface{})
if m == nil {
t.Fatal("did not find the value")
}
} else {
v = m[part]
if v == nil {
t.Fatal("did not find the value")
}
}
parts = parts[1:]
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func BenchmarkJSONUnmarshalStruct(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
var s BenchStruct
if err := json.Unmarshal([]byte(exampleJSON), &s); err != nil {
t.Fatal(err)
}
switch benchPaths[j] {
case "widget.window.name":
if s.Widget.Window.Name == "" {
t.Fatal("did not find the value")
}
case "widget.image.hOffset":
if s.Widget.Image.HOffset == 0 {
t.Fatal("did not find the value")
}
case "widget.text.onMouseUp":
if s.Widget.Text.OnMouseUp == "" {
t.Fatal("did not find the value")
}
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func BenchmarkJSONDecoder(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
dec := json.NewDecoder(bytes.NewBuffer([]byte(exampleJSON)))
var found bool
outer:
for {
tok, err := dec.Token()
if err != nil {
if err == io.EOF {
break
}
t.Fatal(err)
}
switch v := tok.(type) {
case string:
if found {
// break out once we find the value.
break outer
}
switch benchPaths[j] {
case "widget.window.name":
if v == "name" {
found = true
}
case "widget.image.hOffset":
if v == "hOffset" {
found = true
}
case "widget.text.onMouseUp":
if v == "onMouseUp" {
found = true
}
}
}
}
if !found {
t.Fatal("field not found")
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func BenchmarkFFJSONLexer(t *testing.B) {
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
l := fflib.NewFFLexer([]byte(exampleJSON))
var found bool
outer:
for {
t := l.Scan()
if t == fflib.FFTok_eof {
break
}
if t == fflib.FFTok_string {
b, _ := l.CaptureField(t)
v := string(b)
if found {
// break out once we find the value.
break outer
}
switch benchPaths[j] {
case "widget.window.name":
if v == "\"name\"" {
found = true
}
case "widget.image.hOffset":
if v == "\"hOffset\"" {
found = true
}
case "widget.text.onMouseUp":
if v == "\"onMouseUp\"" {
found = true
}
}
}
}
if !found {
t.Fatal("field not found")
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
2017-04-11 06:45:34 +03:00
func skipCC(l *jlexer.Lexer, n int) {
for i := 0; i < n; i++ {
l.Skip()
l.WantColon()
l.Skip()
l.WantComma()
}
}
func skipGroup(l *jlexer.Lexer, n int) {
l.WantColon()
l.Delim('{')
skipCC(l, n)
l.Delim('}')
l.WantComma()
}
func easyJSONWindowName(t *testing.B, l *jlexer.Lexer) {
if l.String() == "window" {
l.WantColon()
l.Delim('{')
skipCC(l, 1)
if l.String() == "name" {
2016-08-11 06:07:45 +03:00
l.WantColon()
2017-04-11 06:45:34 +03:00
if l.String() == "" {
t.Fatal("did not find the value")
}
2016-08-11 06:07:45 +03:00
}
}
2017-04-11 06:45:34 +03:00
}
func easyJSONImageHOffset(t *testing.B, l *jlexer.Lexer) {
if l.String() == "image" {
2016-08-11 06:07:45 +03:00
l.WantColon()
l.Delim('{')
2017-04-11 06:45:34 +03:00
skipCC(l, 1)
if l.String() == "hOffset" {
l.WantColon()
if l.Int() == 0 {
t.Fatal("did not find the value")
}
}
2016-08-11 06:07:45 +03:00
}
2017-04-11 06:45:34 +03:00
}
func easyJSONTextOnMouseUp(t *testing.B, l *jlexer.Lexer) {
if l.String() == "text" {
l.WantColon()
l.Delim('{')
skipCC(l, 5)
if l.String() == "onMouseUp" {
l.WantColon()
if l.String() == "" {
t.Fatal("did not find the value")
}
}
}
}
func easyJSONWidget(t *testing.B, l *jlexer.Lexer, j int) {
l.WantColon()
l.Delim('{')
switch benchPaths[j] {
case "widget.window.name":
skipCC(l, 1)
easyJSONWindowName(t, l)
case "widget.image.hOffset":
skipCC(l, 1)
if l.String() == "window" {
skipGroup(l, 4)
}
easyJSONImageHOffset(t, l)
case "widget.text.onMouseUp":
skipCC(l, 1)
if l.String() == "window" {
skipGroup(l, 4)
}
if l.String() == "image" {
skipGroup(l, 4)
}
easyJSONTextOnMouseUp(t, l)
}
}
func BenchmarkEasyJSONLexer(t *testing.B) {
2016-08-27 16:20:43 +03:00
t.ReportAllocs()
t.ResetTimer()
2016-08-11 06:07:45 +03:00
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
l := &jlexer.Lexer{Data: []byte(exampleJSON)}
l.Delim('{')
if l.String() == "widget" {
2017-04-11 06:45:34 +03:00
easyJSONWidget(t, l, j)
2016-08-11 06:07:45 +03:00
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
2016-08-11 20:53:50 +03:00
func BenchmarkJSONParserGet(t *testing.B) {
data := []byte(exampleJSON)
keys := make([][]string, 0, len(benchPaths))
2016-08-11 20:53:50 +03:00
for i := 0; i < len(benchPaths); i++ {
keys = append(keys, strings.Split(benchPaths[i], "."))
}
t.ReportAllocs()
2016-08-27 16:20:43 +03:00
t.ResetTimer()
2016-08-11 20:53:50 +03:00
for i := 0; i < t.N; i++ {
for j, k := range keys {
if j == 1 {
// "widget.image.hOffset" is a number
v, _ := jsonparser.GetInt(data, k...)
if v == 0 {
t.Fatal("did not find the value")
}
} else {
// "widget.window.name",
// "widget.text.onMouseUp",
v, _ := jsonparser.GetString(data, k...)
if v == "" {
t.Fatal("did not find the value")
}
2016-08-11 20:53:50 +03:00
}
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
func jsoniterWindowName(t *testing.B, iter *jsoniter.Iterator) {
var v string
for {
key := iter.ReadObject()
if key != "window" {
iter.Skip()
continue
}
for {
key := iter.ReadObject()
if key != "name" {
iter.Skip()
continue
}
v = iter.ReadString()
break
}
break
}
if v == "" {
t.Fatal("did not find the value")
}
}
func jsoniterTextOnMouseUp(t *testing.B, iter *jsoniter.Iterator) {
var v string
for {
key := iter.ReadObject()
if key != "text" {
iter.Skip()
continue
}
for {
key := iter.ReadObject()
if key != "onMouseUp" {
iter.Skip()
continue
}
v = iter.ReadString()
break
}
break
}
if v == "" {
t.Fatal("did not find the value")
}
}
func jsoniterImageOffset(t *testing.B, iter *jsoniter.Iterator) {
var v int
for {
key := iter.ReadObject()
if key != "image" {
iter.Skip()
continue
}
for {
key := iter.ReadObject()
if key != "hOffset" {
iter.Skip()
continue
}
v = iter.ReadInt()
break
}
break
}
if v == 0 {
t.Fatal("did not find the value")
}
}
func jsoniterWidget(t *testing.B, iter *jsoniter.Iterator, j int) {
for {
key := iter.ReadObject()
if key != "widget" {
iter.Skip()
continue
}
switch benchPaths[j] {
case "widget.window.name":
jsoniterWindowName(t, iter)
case "widget.image.hOffset":
jsoniterImageOffset(t, iter)
case "widget.text.onMouseUp":
jsoniterTextOnMouseUp(t, iter)
}
break
}
}
func BenchmarkJSONIterator(t *testing.B) {
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
for j := 0; j < len(benchPaths); j++ {
iter := jsoniter.ParseString(exampleJSON)
jsoniterWidget(t, iter, j)
}
}
t.N *= len(benchPaths) // because we are running against 3 paths
}
2016-09-08 18:08:53 +03:00
var massiveJSON = func() string {
var buf bytes.Buffer
buf.WriteString("[")
for i := 0; i < 100; i++ {
if i > 0 {
buf.WriteByte(',')
}
buf.WriteString(exampleJSON)
}
buf.WriteString("]")
return buf.String()
}()
func BenchmarkConvertNone(t *testing.B) {
json := massiveJSON
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
Get(json, "50.widget.text.onMouseUp")
}
}
func BenchmarkConvertGet(t *testing.B) {
data := []byte(massiveJSON)
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
Get(string(data), "50.widget.text.onMouseUp")
}
}
func BenchmarkConvertGetBytes(t *testing.B) {
data := []byte(massiveJSON)
t.ReportAllocs()
t.ResetTimer()
for i := 0; i < t.N; i++ {
GetBytes(data, "50.widget.text.onMouseUp")
}
}