Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: cleanup some tests, add more testdata #15

Merged
merged 3 commits into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 66 additions & 161 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,189 +4,94 @@
package jx

import (
"bytes"
_ "embed"
"encoding/json"
"embed"
"path"
"testing"

"github.com/go-faster/errors"
)

var (
//go:embed testdata/file.json
//go:embed testdata/medium.json
benchData []byte
//go:embed testdata/floats.json
floatsData []byte
//go:embed testdata
testdata embed.FS
)

func Benchmark_large_file(b *testing.B) {
b.Run("JX", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(len(benchData)))
d := Decode(nil, 4096)

for n := 0; n < b.N; n++ {
d.ResetBytes(benchData)
if err := d.Arr(func(d *Decoder) error {
return d.ObjBytes(func(d *Decoder, key []byte) error {
switch string(key) {
case "person", "company": // ok
default:
return errors.New("unexpected key")
}
switch d.Next() {
case Object:
return d.ObjBytes(func(d *Decoder, key []byte) error {
switch d.Next() {
case String:
_, err := d.StrBytes()
return err
case Number:
_, err := d.Num()
return err
case Null:
return d.Null()
default:
return d.Skip()
}
})
default:
return d.Skip()
}
})
}); err != nil {
b.Fatal(err)
}
func runTestdata(fatal func(...interface{}), cb func(name string, data []byte)) {
dir, err := testdata.ReadDir("testdata")
if err != nil {
fatal(err)
}
for _, e := range dir {
if e.IsDir() {
continue
}
})
b.Run("Std", func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(len(benchData)))

type T struct {
Person struct {
ID string `json:"id"`
Name struct {
FullName string `json:"fullName"`
GivenName string `json:"givenName"`
FamilyName string `json:"familyName"`
} `json:"name"`
Email string `json:"email"`
Gender string `json:"gender"`
Location string `json:"location"`
Geo struct {
City string `json:"city"`
State string `json:"state"`
Country string `json:"country"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
} `json:"geo"`
Bio string `json:"bio"`
Site string `json:"site"`
Avatar string `json:"avatar"`
Employment struct {
Name string `json:"name"`
Title string `json:"title"`
Domain string `json:"domain"`
} `json:"employment"`
Facebook struct {
Handle string `json:"handle"`
} `json:"facebook"`
Github struct {
Handle string `json:"handle"`
ID int `json:"id"`
Avatar string `json:"avatar"`
Company string `json:"company"`
Blog string `json:"blog"`
Followers int `json:"followers"`
Following int `json:"following"`
} `json:"github"`
Twitter struct {
Handle string `json:"handle"`
ID int `json:"id"`
Bio json.RawMessage `json:"bio"`
Followers int `json:"followers"`
Following int `json:"following"`
Statuses int `json:"statuses"`
Favorites int `json:"favorites"`
Location string `json:"location"`
Site string `json:"site"`
Avatar json.RawMessage `json:"avatar"`
} `json:"twitter"`
Linkedin struct {
Handle string `json:"handle"`
} `json:"linkedin"`
Googleplus struct {
Handle json.RawMessage `json:"handle"`
} `json:"googleplus"`
Angellist struct {
Handle string `json:"handle"`
ID int `json:"id"`
Bio string `json:"bio"`
Blog string `json:"blog"`
Site string `json:"site"`
Followers int `json:"followers"`
Avatar string `json:"avatar"`
} `json:"angellist"`
Klout struct {
Handle json.RawMessage `json:"handle"`
Score json.RawMessage `json:"score"`
} `json:"klout"`
Foursquare struct {
Handle json.RawMessage `json:"handle"`
} `json:"foursquare"`
Aboutme struct {
Handle string `json:"handle"`
Bio json.RawMessage `json:"bio"`
Avatar json.RawMessage `json:"avatar"`
} `json:"aboutme"`
Gravatar struct {
Handle string `json:"handle"`
Urls json.RawMessage `json:"urls"`
Avatar string `json:"avatar"`
Avatars []struct {
URL string `json:"url"`
Type string `json:"type"`
} `json:"avatars"`
} `json:"gravatar"`
Fuzzy bool `json:"fuzzy"`
} `json:"person"`
Company string `json:"company"`
name := path.Join("testdata", e.Name())
data, err := testdata.ReadFile(name)
if err != nil {
fatal(err)
}
cb(e.Name(), data)
}
}

buf := new(bytes.Reader)
d := json.NewDecoder(buf)
var target []T
for n := 0; n < b.N; n++ {
buf.Reset(benchData)
if err := d.Decode(&target); err != nil {
b.Fatal(err)
}
func BenchmarkFile_Decode(b *testing.B) {
b.ReportAllocs()
b.SetBytes(int64(len(benchData)))
d := Decode(nil, 4096)

for n := 0; n < b.N; n++ {
d.ResetBytes(benchData)
if err := d.Arr(func(d *Decoder) error {
return d.ObjBytes(func(d *Decoder, key []byte) error {
switch string(key) {
case "person", "company": // ok
default:
return errors.New("unexpected key")
}
switch d.Next() {
case Object:
return d.ObjBytes(func(d *Decoder, key []byte) error {
switch d.Next() {
case String:
_, err := d.StrBytes()
return err
case Number:
_, err := d.Num()
return err
case Null:
return d.Null()
default:
return d.Skip()
}
})
default:
return d.Skip()
}
})
}); err != nil {
b.Fatal(err)
}
})
}
}

func BenchmarkValid(b *testing.B) {
bch := []struct {
name string
input []byte
}{
{"Big", benchData},
{"Floats", floatsData},
}
for _, bench := range bch {
b.Run(bench.name, func(b *testing.B) {
d := GetDecoder()
runTestdata(b.Fatal, func(name string, data []byte) {
b.Run(name, func(b *testing.B) {
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.SetBytes(int64(len(bench.input)))
var d Decoder
for n := 0; n < b.N; n++ {
d.ResetBytes(bench.input)
b.ResetTimer()

for i := 0; i < b.N; i++ {
d.ResetBytes(data)
if err := d.Validate(); err != nil {
b.Fatal(err)
}
}
})
}
})
}

func encodeSmallObject(e *Encoder) {
Expand Down
2 changes: 1 addition & 1 deletion dec_b64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func BenchmarkDecoder_Base64Append(b *testing.B) {
512,
1024,
} {
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
b.Run(fmt.Sprintf("%db", n), func(b *testing.B) {
var v []byte
for i := 0; i < n; i++ {
v = append(v, byte(i%256))
Expand Down
18 changes: 17 additions & 1 deletion dec_skip_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@ import (
"github.com/stretchr/testify/require"
)

func TestSkip(t *testing.T) {
func TestDecoder_Skip(t *testing.T) {
type testCase struct {
ptr interface{}
inputs []string
}
var testCases []testCase

testCases = append(testCases, testCase{
ptr: (*bool)(nil),
inputs: []string{
"tru",
"fals",
"",
"nope",
"true",
"false",
},
})
testCases = append(testCases, testCase{
ptr: (*string)(nil),
inputs: []string{
Expand Down Expand Up @@ -104,6 +115,11 @@ func TestSkip(t *testing.T) {
testCases = append(testCases, testCase{
ptr: (*struct{})(nil),
inputs: []string{
"", // invalid
"nope", // invalid
"nul", // invalid
"nil", // invalid
"null", // valid
`{}`, // valid
`{"hello":"world"}`, // valid
`{hello:"world"}`, // invalid
Expand Down
15 changes: 0 additions & 15 deletions dec_skip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,3 @@ func TestDecoder_Null(t *testing.T) {
require.Error(t, d.Null())
}
}

func TestDecoder_Skip(t *testing.T) {
for _, s := range []string{
"",
"nope",
"nul",
"nil",
"tru",
"fals",
"1.2.3",
} {
d := DecodeStr(s)
require.Error(t, d.Skip())
}
}
17 changes: 17 additions & 0 deletions dec_validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package jx

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestDecoder_Validate(t *testing.T) {
d := GetDecoder()
runTestdata(t.Fatal, func(name string, data []byte) {
t.Run(name, func(t *testing.T) {
d.ResetBytes(data)
require.NoError(t, d.Validate())
})
})
}
6 changes: 3 additions & 3 deletions invalid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
)

func Test_invalid_float(t *testing.T) {
func TestInvalidFloat(t *testing.T) {
inputs := []string{
`1.e1`, // dot without following digit
`1.`, // dot can not be the last char
Expand All @@ -31,7 +31,7 @@ func Test_invalid_float(t *testing.T) {
}
}

func TestValid_positive(t *testing.T) {
func TestValidPositive(t *testing.T) {
for _, tt := range []struct {
Name string
Value string
Expand Down Expand Up @@ -59,7 +59,7 @@ func TestValid_positive(t *testing.T) {
}
}

func TestValid_negative(t *testing.T) {
func TestValidNegative(t *testing.T) {
for _, tt := range []struct {
Name string
Value string
Expand Down
9 changes: 9 additions & 0 deletions testdata/canada.json

Large diffs are not rendered by default.

Loading