2010-04-21 17:40:53 -06:00
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
2009-11-30 14:55:09 -07:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package json
|
|
|
|
|
|
|
|
import (
|
2010-04-21 17:40:53 -06:00
|
|
|
"bytes"
|
2009-12-15 16:35:38 -07:00
|
|
|
"reflect"
|
2010-04-21 17:40:53 -06:00
|
|
|
"strings"
|
2009-12-15 16:35:38 -07:00
|
|
|
"testing"
|
2009-11-30 14:55:09 -07:00
|
|
|
)
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
type unmarshalTest struct {
|
|
|
|
in string
|
|
|
|
ptr interface{}
|
|
|
|
out interface{}
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
var unmarshalTests = []unmarshalTest{
|
|
|
|
// basic types
|
|
|
|
unmarshalTest{`true`, new(bool), true},
|
|
|
|
unmarshalTest{`1`, new(int), 1},
|
|
|
|
unmarshalTest{`1.2`, new(float), 1.2},
|
|
|
|
unmarshalTest{`-5`, new(int16), int16(-5)},
|
|
|
|
unmarshalTest{`"a\u1234"`, new(string), "a\u1234"},
|
|
|
|
unmarshalTest{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E"},
|
|
|
|
unmarshalTest{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD"},
|
|
|
|
unmarshalTest{"null", new(interface{}), nil},
|
2009-11-30 14:55:09 -07:00
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
// composite tests
|
|
|
|
unmarshalTest{allValueIndent, new(All), allValue},
|
|
|
|
unmarshalTest{allValueCompact, new(All), allValue},
|
|
|
|
unmarshalTest{allValueIndent, new(*All), &allValue},
|
|
|
|
unmarshalTest{allValueCompact, new(*All), &allValue},
|
|
|
|
unmarshalTest{pallValueIndent, new(All), pallValue},
|
|
|
|
unmarshalTest{pallValueCompact, new(All), pallValue},
|
|
|
|
unmarshalTest{pallValueIndent, new(*All), &pallValue},
|
|
|
|
unmarshalTest{pallValueCompact, new(*All), &pallValue},
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
func TestMarshal(t *testing.T) {
|
|
|
|
b, err := Marshal(allValue)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Marshal allValue: %v", err)
|
|
|
|
}
|
|
|
|
if string(b) != allValueCompact {
|
|
|
|
t.Errorf("Marshal allValueCompact")
|
|
|
|
diff(t, b, []byte(allValueCompact))
|
|
|
|
return
|
|
|
|
}
|
2009-11-30 14:55:09 -07:00
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
b, err = Marshal(pallValue)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Marshal pallValue: %v", err)
|
|
|
|
}
|
|
|
|
if string(b) != pallValueCompact {
|
|
|
|
t.Errorf("Marshal pallValueCompact")
|
|
|
|
diff(t, b, []byte(pallValueCompact))
|
|
|
|
return
|
|
|
|
}
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
func TestUnmarshal(t *testing.T) {
|
|
|
|
var scan scanner
|
|
|
|
for i, tt := range unmarshalTests {
|
|
|
|
in := []byte(tt.in)
|
|
|
|
if err := checkValid(in, &scan); err != nil {
|
|
|
|
t.Errorf("#%d: checkValid: %v", i, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// v = new(right-type)
|
|
|
|
v := reflect.NewValue(tt.ptr).(*reflect.PtrValue)
|
|
|
|
v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
|
|
|
|
if err := Unmarshal([]byte(in), v.Interface()); err != nil {
|
|
|
|
t.Errorf("#%d: %v", i, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
|
|
|
|
t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
|
|
|
|
data, _ := Marshal(v.Elem().Interface())
|
|
|
|
println(string(data))
|
|
|
|
data, _ = Marshal(tt.out)
|
|
|
|
println(string(data))
|
|
|
|
return
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
func TestUnmarshalMarshal(t *testing.T) {
|
|
|
|
var v interface{}
|
|
|
|
if err := Unmarshal(jsonBig, &v); err != nil {
|
|
|
|
t.Fatalf("Unmarshal: %v", err)
|
|
|
|
}
|
|
|
|
b, err := Marshal(v)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Marshal: %v", err)
|
|
|
|
}
|
|
|
|
if bytes.Compare(jsonBig, b) != 0 {
|
|
|
|
t.Errorf("Marshal jsonBig")
|
|
|
|
diff(t, b, jsonBig)
|
|
|
|
return
|
|
|
|
}
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
func noSpace(c int) int {
|
|
|
|
if isSpace(c) {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
return c
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
type All struct {
|
|
|
|
Bool bool
|
|
|
|
Int int
|
|
|
|
Int8 int8
|
|
|
|
Int16 int16
|
|
|
|
Int32 int32
|
|
|
|
Int64 int64
|
|
|
|
Uint uint
|
|
|
|
Uint8 uint8
|
|
|
|
Uint16 uint16
|
|
|
|
Uint32 uint32
|
|
|
|
Uint64 uint64
|
|
|
|
Uintptr uintptr
|
|
|
|
Float float
|
|
|
|
Float32 float32
|
|
|
|
Float64 float64
|
2009-11-30 14:55:09 -07:00
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
Foo string "bar"
|
2009-11-30 14:55:09 -07:00
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
PBool *bool
|
|
|
|
PInt *int
|
|
|
|
PInt8 *int8
|
|
|
|
PInt16 *int16
|
|
|
|
PInt32 *int32
|
|
|
|
PInt64 *int64
|
|
|
|
PUint *uint
|
|
|
|
PUint8 *uint8
|
|
|
|
PUint16 *uint16
|
|
|
|
PUint32 *uint32
|
|
|
|
PUint64 *uint64
|
|
|
|
PUintptr *uintptr
|
|
|
|
PFloat *float
|
|
|
|
PFloat32 *float32
|
|
|
|
PFloat64 *float64
|
|
|
|
|
|
|
|
String string
|
|
|
|
PString *string
|
2009-11-30 14:55:09 -07:00
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
Map map[string]Small
|
|
|
|
MapP map[string]*Small
|
|
|
|
PMap *map[string]Small
|
|
|
|
PMapP *map[string]*Small
|
|
|
|
|
|
|
|
EmptyMap map[string]Small
|
|
|
|
NilMap map[string]Small
|
|
|
|
|
|
|
|
Slice []Small
|
|
|
|
SliceP []*Small
|
|
|
|
PSlice *[]Small
|
|
|
|
PSliceP *[]*Small
|
|
|
|
|
|
|
|
EmptySlice []Small
|
|
|
|
NilSlice []Small
|
|
|
|
|
|
|
|
StringSlice []string
|
|
|
|
ByteSlice []byte
|
|
|
|
|
|
|
|
Small Small
|
|
|
|
PSmall *Small
|
|
|
|
PPSmall **Small
|
|
|
|
|
|
|
|
Interface interface{}
|
|
|
|
PInterface *interface{}
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
type Small struct {
|
|
|
|
Tag string
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
var allValue = All{
|
|
|
|
Bool: true,
|
|
|
|
Int: 2,
|
|
|
|
Int8: 3,
|
|
|
|
Int16: 4,
|
|
|
|
Int32: 5,
|
|
|
|
Int64: 6,
|
|
|
|
Uint: 7,
|
|
|
|
Uint8: 8,
|
|
|
|
Uint16: 9,
|
|
|
|
Uint32: 10,
|
|
|
|
Uint64: 11,
|
|
|
|
Uintptr: 12,
|
|
|
|
Float: 13.1,
|
|
|
|
Float32: 14.1,
|
|
|
|
Float64: 15.1,
|
|
|
|
Foo: "foo",
|
|
|
|
String: "16",
|
|
|
|
Map: map[string]Small{
|
|
|
|
"17": Small{Tag: "tag17"},
|
|
|
|
"18": Small{Tag: "tag18"},
|
|
|
|
},
|
|
|
|
MapP: map[string]*Small{
|
|
|
|
"19": &Small{Tag: "tag19"},
|
|
|
|
"20": nil,
|
|
|
|
},
|
|
|
|
EmptyMap: map[string]Small{},
|
|
|
|
Slice: []Small{Small{Tag: "tag20"}, Small{Tag: "tag21"}},
|
|
|
|
SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
|
|
|
|
EmptySlice: []Small{},
|
|
|
|
StringSlice: []string{"str24", "str25", "str26"},
|
|
|
|
ByteSlice: []byte{27, 28, 29},
|
|
|
|
Small: Small{Tag: "tag30"},
|
|
|
|
PSmall: &Small{Tag: "tag31"},
|
|
|
|
Interface: float64(5.2),
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
var pallValue = All{
|
|
|
|
PBool: &allValue.Bool,
|
|
|
|
PInt: &allValue.Int,
|
|
|
|
PInt8: &allValue.Int8,
|
|
|
|
PInt16: &allValue.Int16,
|
|
|
|
PInt32: &allValue.Int32,
|
|
|
|
PInt64: &allValue.Int64,
|
|
|
|
PUint: &allValue.Uint,
|
|
|
|
PUint8: &allValue.Uint8,
|
|
|
|
PUint16: &allValue.Uint16,
|
|
|
|
PUint32: &allValue.Uint32,
|
|
|
|
PUint64: &allValue.Uint64,
|
|
|
|
PUintptr: &allValue.Uintptr,
|
|
|
|
PFloat: &allValue.Float,
|
|
|
|
PFloat32: &allValue.Float32,
|
|
|
|
PFloat64: &allValue.Float64,
|
|
|
|
PString: &allValue.String,
|
|
|
|
PMap: &allValue.Map,
|
|
|
|
PMapP: &allValue.MapP,
|
|
|
|
PSlice: &allValue.Slice,
|
|
|
|
PSliceP: &allValue.SliceP,
|
|
|
|
PPSmall: &allValue.PSmall,
|
|
|
|
PInterface: &allValue.Interface,
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
|
|
|
|
2010-04-21 17:40:53 -06:00
|
|
|
var allValueIndent = `{
|
|
|
|
"bool": true,
|
|
|
|
"int": 2,
|
|
|
|
"int8": 3,
|
|
|
|
"int16": 4,
|
|
|
|
"int32": 5,
|
|
|
|
"int64": 6,
|
|
|
|
"uint": 7,
|
|
|
|
"uint8": 8,
|
|
|
|
"uint16": 9,
|
|
|
|
"uint32": 10,
|
|
|
|
"uint64": 11,
|
|
|
|
"uintptr": 12,
|
|
|
|
"float": 13.1,
|
|
|
|
"float32": 14.1,
|
|
|
|
"float64": 15.1,
|
|
|
|
"bar": "foo",
|
|
|
|
"pbool": null,
|
|
|
|
"pint": null,
|
|
|
|
"pint8": null,
|
|
|
|
"pint16": null,
|
|
|
|
"pint32": null,
|
|
|
|
"pint64": null,
|
|
|
|
"puint": null,
|
|
|
|
"puint8": null,
|
|
|
|
"puint16": null,
|
|
|
|
"puint32": null,
|
|
|
|
"puint64": null,
|
|
|
|
"puintptr": null,
|
|
|
|
"pfloat": null,
|
|
|
|
"pfloat32": null,
|
|
|
|
"pfloat64": null,
|
|
|
|
"string": "16",
|
|
|
|
"pstring": null,
|
|
|
|
"map": {
|
|
|
|
"17": {
|
|
|
|
"tag": "tag17"
|
|
|
|
},
|
|
|
|
"18": {
|
|
|
|
"tag": "tag18"
|
2009-11-30 14:55:09 -07:00
|
|
|
}
|
2010-04-21 17:40:53 -06:00
|
|
|
},
|
|
|
|
"mapp": {
|
|
|
|
"19": {
|
|
|
|
"tag": "tag19"
|
|
|
|
},
|
|
|
|
"20": null
|
|
|
|
},
|
|
|
|
"pmap": null,
|
|
|
|
"pmapp": null,
|
|
|
|
"emptymap": {},
|
|
|
|
"nilmap": null,
|
|
|
|
"slice": [
|
|
|
|
{
|
|
|
|
"tag": "tag20"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"tag": "tag21"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"slicep": [
|
|
|
|
{
|
|
|
|
"tag": "tag22"
|
|
|
|
},
|
|
|
|
null,
|
|
|
|
{
|
|
|
|
"tag": "tag23"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"pslice": null,
|
|
|
|
"pslicep": null,
|
|
|
|
"emptyslice": [],
|
|
|
|
"nilslice": [],
|
|
|
|
"stringslice": [
|
|
|
|
"str24",
|
|
|
|
"str25",
|
|
|
|
"str26"
|
|
|
|
],
|
|
|
|
"byteslice": [
|
|
|
|
27,
|
|
|
|
28,
|
|
|
|
29
|
|
|
|
],
|
|
|
|
"small": {
|
|
|
|
"tag": "tag30"
|
|
|
|
},
|
|
|
|
"psmall": {
|
|
|
|
"tag": "tag31"
|
|
|
|
},
|
|
|
|
"ppsmall": null,
|
|
|
|
"interface": 5.2,
|
|
|
|
"pinterface": null
|
|
|
|
}`
|
|
|
|
|
|
|
|
var allValueCompact = strings.Map(noSpace, allValueIndent)
|
|
|
|
|
|
|
|
var pallValueIndent = `{
|
|
|
|
"bool": false,
|
|
|
|
"int": 0,
|
|
|
|
"int8": 0,
|
|
|
|
"int16": 0,
|
|
|
|
"int32": 0,
|
|
|
|
"int64": 0,
|
|
|
|
"uint": 0,
|
|
|
|
"uint8": 0,
|
|
|
|
"uint16": 0,
|
|
|
|
"uint32": 0,
|
|
|
|
"uint64": 0,
|
|
|
|
"uintptr": 0,
|
|
|
|
"float": 0,
|
|
|
|
"float32": 0,
|
|
|
|
"float64": 0,
|
|
|
|
"bar": "",
|
|
|
|
"pbool": true,
|
|
|
|
"pint": 2,
|
|
|
|
"pint8": 3,
|
|
|
|
"pint16": 4,
|
|
|
|
"pint32": 5,
|
|
|
|
"pint64": 6,
|
|
|
|
"puint": 7,
|
|
|
|
"puint8": 8,
|
|
|
|
"puint16": 9,
|
|
|
|
"puint32": 10,
|
|
|
|
"puint64": 11,
|
|
|
|
"puintptr": 12,
|
|
|
|
"pfloat": 13.1,
|
|
|
|
"pfloat32": 14.1,
|
|
|
|
"pfloat64": 15.1,
|
|
|
|
"string": "",
|
|
|
|
"pstring": "16",
|
|
|
|
"map": null,
|
|
|
|
"mapp": null,
|
|
|
|
"pmap": {
|
|
|
|
"17": {
|
|
|
|
"tag": "tag17"
|
|
|
|
},
|
|
|
|
"18": {
|
|
|
|
"tag": "tag18"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"pmapp": {
|
|
|
|
"19": {
|
|
|
|
"tag": "tag19"
|
|
|
|
},
|
|
|
|
"20": null
|
|
|
|
},
|
|
|
|
"emptymap": null,
|
|
|
|
"nilmap": null,
|
|
|
|
"slice": [],
|
|
|
|
"slicep": [],
|
|
|
|
"pslice": [
|
|
|
|
{
|
|
|
|
"tag": "tag20"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"tag": "tag21"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"pslicep": [
|
|
|
|
{
|
|
|
|
"tag": "tag22"
|
|
|
|
},
|
|
|
|
null,
|
|
|
|
{
|
|
|
|
"tag": "tag23"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"emptyslice": [],
|
|
|
|
"nilslice": [],
|
|
|
|
"stringslice": [],
|
|
|
|
"byteslice": [],
|
|
|
|
"small": {
|
|
|
|
"tag": ""
|
|
|
|
},
|
|
|
|
"psmall": null,
|
|
|
|
"ppsmall": {
|
|
|
|
"tag": "tag31"
|
|
|
|
},
|
|
|
|
"interface": null,
|
|
|
|
"pinterface": 5.2
|
|
|
|
}`
|
|
|
|
|
|
|
|
var pallValueCompact = strings.Map(noSpace, pallValueIndent)
|