Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
encode_test.go1426 linesDownload Raw Back to json
1// Copyright 2011 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5//go:build !goexperiment.jsonv26 7package json8 9import (10	"bytes"11	"encoding"12	"fmt"13	"log"14	"math"15	"reflect"16	"regexp"17	"runtime/debug"18	"strconv"19	"sync"20	"testing"21	"testing/synctest"22	"time"23)24 25type OptionalsEmpty struct {26	Sr string `json:"sr"`27	So string `json:"so,omitempty"`28	Sw string `json:"-"`29 30	Ir int `json:"omitempty"` // actually named omitempty, not an option31	Io int `json:"io,omitempty"`32 33	Slr []string `json:"slr,random"`34	Slo []string `json:"slo,omitempty"`35 36	Mr map[string]any `json:"mr"`37	Mo map[string]any `json:",omitempty"`38 39	Fr float64 `json:"fr"`40	Fo float64 `json:"fo,omitempty"`41 42	Br bool `json:"br"`43	Bo bool `json:"bo,omitempty"`44 45	Ur uint `json:"ur"`46	Uo uint `json:"uo,omitempty"`47 48	Str struct{} `json:"str"`49	Sto struct{} `json:"sto,omitempty"`50}51 52func TestOmitEmpty(t *testing.T) {53	const want = `{54 "sr": "",55 "omitempty": 0,56 "slr": null,57 "mr": {},58 "fr": 0,59 "br": false,60 "ur": 0,61 "str": {},62 "sto": {}63}`64	var o OptionalsEmpty65	o.Sw = "something"66	o.Mr = map[string]any{}67	o.Mo = map[string]any{}68 69	got, err := MarshalIndent(&o, "", " ")70	if err != nil {71		t.Fatalf("MarshalIndent error: %v", err)72	}73	if got := string(got); got != want {74		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))75	}76}77 78type NonZeroStruct struct{}79 80func (nzs NonZeroStruct) IsZero() bool {81	return false82}83 84type NoPanicStruct struct {85	Int int `json:"int,omitzero"`86}87 88func (nps *NoPanicStruct) IsZero() bool {89	return nps.Int != 090}91 92type OptionalsZero struct {93	Sr string `json:"sr"`94	So string `json:"so,omitzero"`95	Sw string `json:"-"`96 97	Ir int `json:"omitzero"` // actually named omitzero, not an option98	Io int `json:"io,omitzero"`99 100	Slr       []string `json:"slr,random"`101	Slo       []string `json:"slo,omitzero"`102	SloNonNil []string `json:"slononnil,omitzero"`103 104	Mr  map[string]any `json:"mr"`105	Mo  map[string]any `json:",omitzero"`106	Moo map[string]any `json:"moo,omitzero"`107 108	Fr   float64    `json:"fr"`109	Fo   float64    `json:"fo,omitzero"`110	Foo  float64    `json:"foo,omitzero"`111	Foo2 [2]float64 `json:"foo2,omitzero"`112 113	Br bool `json:"br"`114	Bo bool `json:"bo,omitzero"`115 116	Ur uint `json:"ur"`117	Uo uint `json:"uo,omitzero"`118 119	Str struct{} `json:"str"`120	Sto struct{} `json:"sto,omitzero"`121 122	Time      time.Time     `json:"time,omitzero"`123	TimeLocal time.Time     `json:"timelocal,omitzero"`124	Nzs       NonZeroStruct `json:"nzs,omitzero"`125 126	NilIsZeroer    isZeroer       `json:"niliszeroer,omitzero"`    // nil interface127	NonNilIsZeroer isZeroer       `json:"nonniliszeroer,omitzero"` // non-nil interface128	NoPanicStruct0 isZeroer       `json:"nps0,omitzero"`           // non-nil interface with nil pointer129	NoPanicStruct1 isZeroer       `json:"nps1,omitzero"`           // non-nil interface with non-nil pointer130	NoPanicStruct2 *NoPanicStruct `json:"nps2,omitzero"`           // nil pointer131	NoPanicStruct3 *NoPanicStruct `json:"nps3,omitzero"`           // non-nil pointer132	NoPanicStruct4 NoPanicStruct  `json:"nps4,omitzero"`           // concrete type133}134 135func TestOmitZero(t *testing.T) {136	const want = `{137 "sr": "",138 "omitzero": 0,139 "slr": null,140 "slononnil": [],141 "mr": {},142 "Mo": {},143 "fr": 0,144 "br": false,145 "ur": 0,146 "str": {},147 "nzs": {},148 "nps1": {},149 "nps3": {},150 "nps4": {}151}`152	var o OptionalsZero153	o.Sw = "something"154	o.SloNonNil = make([]string, 0)155	o.Mr = map[string]any{}156	o.Mo = map[string]any{}157 158	o.Foo = -0159	o.Foo2 = [2]float64{+0, -0}160 161	o.TimeLocal = time.Time{}.Local()162 163	o.NonNilIsZeroer = time.Time{}164	o.NoPanicStruct0 = (*NoPanicStruct)(nil)165	o.NoPanicStruct1 = &NoPanicStruct{}166	o.NoPanicStruct3 = &NoPanicStruct{}167 168	got, err := MarshalIndent(&o, "", " ")169	if err != nil {170		t.Fatalf("MarshalIndent error: %v", err)171	}172	if got := string(got); got != want {173		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))174	}175}176 177func TestOmitZeroMap(t *testing.T) {178	const want = `{179 "foo": {180  "sr": "",181  "omitzero": 0,182  "slr": null,183  "mr": null,184  "fr": 0,185  "br": false,186  "ur": 0,187  "str": {},188  "nzs": {},189  "nps4": {}190 }191}`192	m := map[string]OptionalsZero{"foo": {}}193	got, err := MarshalIndent(m, "", " ")194	if err != nil {195		t.Fatalf("MarshalIndent error: %v", err)196	}197	if got := string(got); got != want {198		fmt.Println(got)199		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))200	}201}202 203type OptionalsEmptyZero struct {204	Sr string `json:"sr"`205	So string `json:"so,omitempty,omitzero"`206	Sw string `json:"-"`207 208	Io int `json:"io,omitempty,omitzero"`209 210	Slr       []string `json:"slr,random"`211	Slo       []string `json:"slo,omitempty,omitzero"`212	SloNonNil []string `json:"slononnil,omitempty,omitzero"`213 214	Mr map[string]any `json:"mr"`215	Mo map[string]any `json:",omitempty,omitzero"`216 217	Fr float64 `json:"fr"`218	Fo float64 `json:"fo,omitempty,omitzero"`219 220	Br bool `json:"br"`221	Bo bool `json:"bo,omitempty,omitzero"`222 223	Ur uint `json:"ur"`224	Uo uint `json:"uo,omitempty,omitzero"`225 226	Str struct{} `json:"str"`227	Sto struct{} `json:"sto,omitempty,omitzero"`228 229	Time time.Time     `json:"time,omitempty,omitzero"`230	Nzs  NonZeroStruct `json:"nzs,omitempty,omitzero"`231}232 233func TestOmitEmptyZero(t *testing.T) {234	const want = `{235 "sr": "",236 "slr": null,237 "mr": {},238 "fr": 0,239 "br": false,240 "ur": 0,241 "str": {},242 "nzs": {}243}`244	var o OptionalsEmptyZero245	o.Sw = "something"246	o.SloNonNil = make([]string, 0)247	o.Mr = map[string]any{}248	o.Mo = map[string]any{}249 250	got, err := MarshalIndent(&o, "", " ")251	if err != nil {252		t.Fatalf("MarshalIndent error: %v", err)253	}254	if got := string(got); got != want {255		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))256	}257}258 259type StringTag struct {260	BoolStr    bool    `json:",string"`261	IntStr     int64   `json:",string"`262	UintptrStr uintptr `json:",string"`263	StrStr     string  `json:",string"`264	NumberStr  Number  `json:",string"`265}266 267func TestRoundtripStringTag(t *testing.T) {268	tests := []struct {269		CaseName270		in   StringTag271		want string // empty to just test that we roundtrip272	}{{273		CaseName: Name("AllTypes"),274		in: StringTag{275			BoolStr:    true,276			IntStr:     42,277			UintptrStr: 44,278			StrStr:     "xzbit",279			NumberStr:  "46",280		},281		want: `{282	"BoolStr": "true",283	"IntStr": "42",284	"UintptrStr": "44",285	"StrStr": "\"xzbit\"",286	"NumberStr": "46"287}`,288	}, {289		// See golang.org/issues/38173.290		CaseName: Name("StringDoubleEscapes"),291		in: StringTag{292			StrStr:    "\b\f\n\r\t\"\\",293			NumberStr: "0", // just to satisfy the roundtrip294		},295		want: `{296	"BoolStr": "false",297	"IntStr": "0",298	"UintptrStr": "0",299	"StrStr": "\"\\b\\f\\n\\r\\t\\\"\\\\\"",300	"NumberStr": "0"301}`,302	}}303	for _, tt := range tests {304		t.Run(tt.Name, func(t *testing.T) {305			got, err := MarshalIndent(&tt.in, "", "\t")306			if err != nil {307				t.Fatalf("%s: MarshalIndent error: %v", tt.Where, err)308			}309			if got := string(got); got != tt.want {310				t.Fatalf("%s: MarshalIndent:\n\tgot:  %s\n\twant: %s", tt.Where, stripWhitespace(got), stripWhitespace(tt.want))311			}312 313			// Verify that it round-trips.314			var s2 StringTag315			if err := Unmarshal(got, &s2); err != nil {316				t.Fatalf("%s: Decode error: %v", tt.Where, err)317			}318			if !reflect.DeepEqual(s2, tt.in) {319				t.Fatalf("%s: Decode:\n\tinput: %s\n\tgot:  %#v\n\twant: %#v", tt.Where, indentNewlines(string(got)), s2, tt.in)320			}321		})322	}323}324 325// byte slices are special even if they're renamed types.326type renamedByte byte327type renamedByteSlice []byte328type renamedRenamedByteSlice []renamedByte329 330func TestEncodeRenamedByteSlice(t *testing.T) {331	s := renamedByteSlice("abc")332	got, err := Marshal(s)333	if err != nil {334		t.Fatalf("Marshal error: %v", err)335	}336	want := `"YWJj"`337	if string(got) != want {338		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)339	}340	r := renamedRenamedByteSlice("abc")341	got, err = Marshal(r)342	if err != nil {343		t.Fatalf("Marshal error: %v", err)344	}345	if string(got) != want {346		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)347	}348}349 350type SamePointerNoCycle struct {351	Ptr1, Ptr2 *SamePointerNoCycle352}353 354var samePointerNoCycle = &SamePointerNoCycle{}355 356type PointerCycle struct {357	Ptr *PointerCycle358}359 360var pointerCycle = &PointerCycle{}361 362type PointerCycleIndirect struct {363	Ptrs []any364}365 366type RecursiveSlice []RecursiveSlice367 368var (369	pointerCycleIndirect = &PointerCycleIndirect{}370	mapCycle             = make(map[string]any)371	sliceCycle           = []any{nil}372	sliceNoCycle         = []any{nil, nil}373	recursiveSliceCycle  = []RecursiveSlice{nil}374)375 376func init() {377	ptr := &SamePointerNoCycle{}378	samePointerNoCycle.Ptr1 = ptr379	samePointerNoCycle.Ptr2 = ptr380 381	pointerCycle.Ptr = pointerCycle382	pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}383 384	mapCycle["x"] = mapCycle385	sliceCycle[0] = sliceCycle386	sliceNoCycle[1] = sliceNoCycle[:1]387	for i := startDetectingCyclesAfter; i > 0; i-- {388		sliceNoCycle = []any{sliceNoCycle}389	}390	recursiveSliceCycle[0] = recursiveSliceCycle391}392 393func TestSamePointerNoCycle(t *testing.T) {394	if _, err := Marshal(samePointerNoCycle); err != nil {395		t.Fatalf("Marshal error: %v", err)396	}397}398 399func TestSliceNoCycle(t *testing.T) {400	if _, err := Marshal(sliceNoCycle); err != nil {401		t.Fatalf("Marshal error: %v", err)402	}403}404 405func TestUnsupportedValues(t *testing.T) {406	tests := []struct {407		CaseName408		in any409	}{410		{Name(""), math.NaN()},411		{Name(""), math.Inf(-1)},412		{Name(""), math.Inf(1)},413		{Name(""), pointerCycle},414		{Name(""), pointerCycleIndirect},415		{Name(""), mapCycle},416		{Name(""), sliceCycle},417		{Name(""), recursiveSliceCycle},418	}419	for _, tt := range tests {420		t.Run(tt.Name, func(t *testing.T) {421			if _, err := Marshal(tt.in); err != nil {422				if _, ok := err.(*UnsupportedValueError); !ok {423					t.Errorf("%s: Marshal error:\n\tgot:  %T\n\twant: %T", tt.Where, err, new(UnsupportedValueError))424				}425			} else {426				t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)427			}428		})429	}430}431 432// Issue 43207433func TestMarshalTextFloatMap(t *testing.T) {434	m := map[textfloat]string{435		textfloat(math.NaN()): "1",436		textfloat(math.NaN()): "1",437	}438	got, err := Marshal(m)439	if err != nil {440		t.Errorf("Marshal error: %v", err)441	}442	want := `{"TF:NaN":"1","TF:NaN":"1"}`443	if string(got) != want {444		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)445	}446}447 448// Ref has Marshaler and Unmarshaler methods with pointer receiver.449type Ref int450 451func (*Ref) MarshalJSON() ([]byte, error) {452	return []byte(`"ref"`), nil453}454 455func (r *Ref) UnmarshalJSON([]byte) error {456	*r = 12457	return nil458}459 460// Val has Marshaler methods with value receiver.461type Val int462 463func (Val) MarshalJSON() ([]byte, error) {464	return []byte(`"val"`), nil465}466 467// RefText has Marshaler and Unmarshaler methods with pointer receiver.468type RefText int469 470func (*RefText) MarshalText() ([]byte, error) {471	return []byte(`"ref"`), nil472}473 474func (r *RefText) UnmarshalText([]byte) error {475	*r = 13476	return nil477}478 479// ValText has Marshaler methods with value receiver.480type ValText int481 482func (ValText) MarshalText() ([]byte, error) {483	return []byte(`"val"`), nil484}485 486func TestRefValMarshal(t *testing.T) {487	var s = struct {488		R0 Ref489		R1 *Ref490		R2 RefText491		R3 *RefText492		V0 Val493		V1 *Val494		V2 ValText495		V3 *ValText496	}{497		R0: 12,498		R1: new(Ref),499		R2: 14,500		R3: new(RefText),501		V0: 13,502		V1: new(Val),503		V2: 15,504		V3: new(ValText),505	}506	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`507	b, err := Marshal(&s)508	if err != nil {509		t.Fatalf("Marshal error: %v", err)510	}511	if got := string(b); got != want {512		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)513	}514}515 516// C implements Marshaler and returns unescaped JSON.517type C int518 519func (C) MarshalJSON() ([]byte, error) {520	return []byte(`"<&>"`), nil521}522 523// CText implements Marshaler and returns unescaped text.524type CText int525 526func (CText) MarshalText() ([]byte, error) {527	return []byte(`"<&>"`), nil528}529 530func TestMarshalerEscaping(t *testing.T) {531	var c C532	want := `"\u003c\u0026\u003e"`533	b, err := Marshal(c)534	if err != nil {535		t.Fatalf("Marshal error: %v", err)536	}537	if got := string(b); got != want {538		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)539	}540 541	var ct CText542	want = `"\"\u003c\u0026\u003e\""`543	b, err = Marshal(ct)544	if err != nil {545		t.Fatalf("Marshal error: %v", err)546	}547	if got := string(b); got != want {548		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)549	}550}551 552func TestAnonymousFields(t *testing.T) {553	tests := []struct {554		CaseName555		makeInput func() any // Function to create input value556		want      string     // Expected JSON output557	}{{558		// Both S1 and S2 have a field named X. From the perspective of S,559		// it is ambiguous which one X refers to.560		// This should not serialize either field.561		CaseName: Name("AmbiguousField"),562		makeInput: func() any {563			type (564				S1 struct{ x, X int }565				S2 struct{ x, X int }566				S  struct {567					S1568					S2569				}570			)571			return S{S1{1, 2}, S2{3, 4}}572		},573		want: `{}`,574	}, {575		CaseName: Name("DominantField"),576		// Both S1 and S2 have a field named X, but since S has an X field as577		// well, it takes precedence over S1.X and S2.X.578		makeInput: func() any {579			type (580				S1 struct{ x, X int }581				S2 struct{ x, X int }582				S  struct {583					S1584					S2585					x, X int586				}587			)588			return S{S1{1, 2}, S2{3, 4}, 5, 6}589		},590		want: `{"X":6}`,591	}, {592		// Unexported embedded field of non-struct type should not be serialized.593		CaseName: Name("UnexportedEmbeddedInt"),594		makeInput: func() any {595			type (596				myInt int597				S     struct{ myInt }598			)599			return S{5}600		},601		want: `{}`,602	}, {603		// Exported embedded field of non-struct type should be serialized.604		CaseName: Name("ExportedEmbeddedInt"),605		makeInput: func() any {606			type (607				MyInt int608				S     struct{ MyInt }609			)610			return S{5}611		},612		want: `{"MyInt":5}`,613	}, {614		// Unexported embedded field of pointer to non-struct type615		// should not be serialized.616		CaseName: Name("UnexportedEmbeddedIntPointer"),617		makeInput: func() any {618			type (619				myInt int620				S     struct{ *myInt }621			)622			s := S{new(myInt)}623			*s.myInt = 5624			return s625		},626		want: `{}`,627	}, {628		// Exported embedded field of pointer to non-struct type629		// should be serialized.630		CaseName: Name("ExportedEmbeddedIntPointer"),631		makeInput: func() any {632			type (633				MyInt int634				S     struct{ *MyInt }635			)636			s := S{new(MyInt)}637			*s.MyInt = 5638			return s639		},640		want: `{"MyInt":5}`,641	}, {642		// Exported fields of embedded structs should have their643		// exported fields be serialized regardless of whether the struct types644		// themselves are exported.645		CaseName: Name("EmbeddedStruct"),646		makeInput: func() any {647			type (648				s1 struct{ x, X int }649				S2 struct{ y, Y int }650				S  struct {651					s1652					S2653				}654			)655			return S{s1{1, 2}, S2{3, 4}}656		},657		want: `{"X":2,"Y":4}`,658	}, {659		// Exported fields of pointers to embedded structs should have their660		// exported fields be serialized regardless of whether the struct types661		// themselves are exported.662		CaseName: Name("EmbeddedStructPointer"),663		makeInput: func() any {664			type (665				s1 struct{ x, X int }666				S2 struct{ y, Y int }667				S  struct {668					*s1669					*S2670				}671			)672			return S{&s1{1, 2}, &S2{3, 4}}673		},674		want: `{"X":2,"Y":4}`,675	}, {676		// Exported fields on embedded unexported structs at multiple levels677		// of nesting should still be serialized.678		CaseName: Name("NestedStructAndInts"),679		makeInput: func() any {680			type (681				MyInt1 int682				MyInt2 int683				myInt  int684				s2     struct {685					MyInt2686					myInt687				}688				s1 struct {689					MyInt1690					myInt691					s2692				}693				S struct {694					s1695					myInt696				}697			)698			return S{s1{1, 2, s2{3, 4}}, 6}699		},700		want: `{"MyInt1":1,"MyInt2":3}`,701	}, {702		// If an anonymous struct pointer field is nil, we should ignore703		// the embedded fields behind it. Not properly doing so may704		// result in the wrong output or reflect panics.705		CaseName: Name("EmbeddedFieldBehindNilPointer"),706		makeInput: func() any {707			type (708				S2 struct{ Field string }709				S  struct{ *S2 }710			)711			return S{}712		},713		want: `{}`,714	}}715 716	for _, tt := range tests {717		t.Run(tt.Name, func(t *testing.T) {718			b, err := Marshal(tt.makeInput())719			if err != nil {720				t.Fatalf("%s: Marshal error: %v", tt.Where, err)721			}722			if string(b) != tt.want {723				t.Fatalf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, b, tt.want)724			}725		})726	}727}728 729type BugA struct {730	S string731}732 733type BugB struct {734	BugA735	S string736}737 738type BugC struct {739	S string740}741 742// Legal Go: We never use the repeated embedded field (S).743type BugX struct {744	A int745	BugA746	BugB747}748 749// golang.org/issue/16042.750// Even if a nil interface value is passed in, as long as751// it implements Marshaler, it should be marshaled.752type nilJSONMarshaler string753 754func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {755	if nm == nil {756		return Marshal("0zenil0")757	}758	return Marshal("zenil:" + string(*nm))759}760 761// golang.org/issue/34235.762// Even if a nil interface value is passed in, as long as763// it implements encoding.TextMarshaler, it should be marshaled.764type nilTextMarshaler string765 766func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {767	if nm == nil {768		return []byte("0zenil0"), nil769	}770	return []byte("zenil:" + string(*nm)), nil771}772 773// See golang.org/issue/16042 and golang.org/issue/34235.774func TestNilMarshal(t *testing.T) {775	tests := []struct {776		CaseName777		in   any778		want string779	}{780		{Name(""), nil, `null`},781		{Name(""), new(float64), `0`},782		{Name(""), []any(nil), `null`},783		{Name(""), []string(nil), `null`},784		{Name(""), map[string]string(nil), `null`},785		{Name(""), []byte(nil), `null`},786		{Name(""), struct{ M string }{"gopher"}, `{"M":"gopher"}`},787		{Name(""), struct{ M Marshaler }{}, `{"M":null}`},788		{Name(""), struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, `{"M":"0zenil0"}`},789		{Name(""), struct{ M any }{(*nilJSONMarshaler)(nil)}, `{"M":null}`},790		{Name(""), struct{ M encoding.TextMarshaler }{}, `{"M":null}`},791		{Name(""), struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, `{"M":"0zenil0"}`},792		{Name(""), struct{ M any }{(*nilTextMarshaler)(nil)}, `{"M":null}`},793	}794	for _, tt := range tests {795		t.Run(tt.Name, func(t *testing.T) {796			switch got, err := Marshal(tt.in); {797			case err != nil:798				t.Fatalf("%s: Marshal error: %v", tt.Where, err)799			case string(got) != tt.want:800				t.Fatalf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, got, tt.want)801			}802		})803	}804}805 806// Issue 5245.807func TestEmbeddedBug(t *testing.T) {808	v := BugB{809		BugA{"A"},810		"B",811	}812	b, err := Marshal(v)813	if err != nil {814		t.Fatal("Marshal error:", err)815	}816	want := `{"S":"B"}`817	got := string(b)818	if got != want {819		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)820	}821	// Now check that the duplicate field, S, does not appear.822	x := BugX{823		A: 23,824	}825	b, err = Marshal(x)826	if err != nil {827		t.Fatal("Marshal error:", err)828	}829	want = `{"A":23}`830	got = string(b)831	if got != want {832		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)833	}834}835 836type BugD struct { // Same as BugA after tagging.837	XXX string `json:"S"`838}839 840// BugD's tagged S field should dominate BugA's.841type BugY struct {842	BugA843	BugD844}845 846// Test that a field with a tag dominates untagged fields.847func TestTaggedFieldDominates(t *testing.T) {848	v := BugY{849		BugA{"BugA"},850		BugD{"BugD"},851	}852	b, err := Marshal(v)853	if err != nil {854		t.Fatal("Marshal error:", err)855	}856	want := `{"S":"BugD"}`857	got := string(b)858	if got != want {859		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)860	}861}862 863// There are no tags here, so S should not appear.864type BugZ struct {865	BugA866	BugC867	BugY // Contains a tagged S field through BugD; should not dominate.868}869 870func TestDuplicatedFieldDisappears(t *testing.T) {871	v := BugZ{872		BugA{"BugA"},873		BugC{"BugC"},874		BugY{875			BugA{"nested BugA"},876			BugD{"nested BugD"},877		},878	}879	b, err := Marshal(v)880	if err != nil {881		t.Fatal("Marshal error:", err)882	}883	want := `{}`884	got := string(b)885	if got != want {886		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)887	}888}889 890func TestIssue10281(t *testing.T) {891	type Foo struct {892		N Number893	}894	x := Foo{Number(`invalid`)}895 896	if _, err := Marshal(&x); err == nil {897		t.Fatalf("Marshal error: got nil, want non-nil")898	}899}900 901func TestMarshalErrorAndReuseEncodeState(t *testing.T) {902	// Disable the GC temporarily to prevent encodeState's in Pool being cleaned away during the test.903	percent := debug.SetGCPercent(-1)904	defer debug.SetGCPercent(percent)905 906	// Trigger an error in Marshal with cyclic data.907	type Dummy struct {908		Name string909		Next *Dummy910	}911	dummy := Dummy{Name: "Dummy"}912	dummy.Next = &dummy913	if _, err := Marshal(dummy); err == nil {914		t.Errorf("Marshal error: got nil, want non-nil")915	}916 917	type Data struct {918		A string919		I int920	}921	want := Data{A: "a", I: 1}922	b, err := Marshal(want)923	if err != nil {924		t.Errorf("Marshal error: %v", err)925	}926 927	var got Data928	if err := Unmarshal(b, &got); err != nil {929		t.Errorf("Unmarshal error: %v", err)930	}931	if got != want {932		t.Errorf("Unmarshal:\n\tgot:  %v\n\twant: %v", got, want)933	}934}935 936func TestHTMLEscape(t *testing.T) {937	var b, want bytes.Buffer938	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`939	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))940	HTMLEscape(&b, []byte(m))941	if !bytes.Equal(b.Bytes(), want.Bytes()) {942		t.Errorf("HTMLEscape:\n\tgot:  %s\n\twant: %s", b.Bytes(), want.Bytes())943	}944}945 946// golang.org/issue/8582947func TestEncodePointerString(t *testing.T) {948	type stringPointer struct {949		N *int64 `json:"n,string"`950	}951	var n int64 = 42952	b, err := Marshal(stringPointer{N: &n})953	if err != nil {954		t.Fatalf("Marshal error: %v", err)955	}956	if got, want := string(b), `{"n":"42"}`; got != want {957		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)958	}959	var back stringPointer960	switch err = Unmarshal(b, &back); {961	case err != nil:962		t.Fatalf("Unmarshal error: %v", err)963	case back.N == nil:964		t.Fatalf("Unmarshal: back.N = nil, want non-nil")965	case *back.N != 42:966		t.Fatalf("Unmarshal: *back.N = %d, want 42", *back.N)967	}968}969 970var encodeStringTests = []struct {971	in  string972	out string973}{974	{"\x00", `"\u0000"`},975	{"\x01", `"\u0001"`},976	{"\x02", `"\u0002"`},977	{"\x03", `"\u0003"`},978	{"\x04", `"\u0004"`},979	{"\x05", `"\u0005"`},980	{"\x06", `"\u0006"`},981	{"\x07", `"\u0007"`},982	{"\x08", `"\b"`},983	{"\x09", `"\t"`},984	{"\x0a", `"\n"`},985	{"\x0b", `"\u000b"`},986	{"\x0c", `"\f"`},987	{"\x0d", `"\r"`},988	{"\x0e", `"\u000e"`},989	{"\x0f", `"\u000f"`},990	{"\x10", `"\u0010"`},991	{"\x11", `"\u0011"`},992	{"\x12", `"\u0012"`},993	{"\x13", `"\u0013"`},994	{"\x14", `"\u0014"`},995	{"\x15", `"\u0015"`},996	{"\x16", `"\u0016"`},997	{"\x17", `"\u0017"`},998	{"\x18", `"\u0018"`},999	{"\x19", `"\u0019"`},1000	{"\x1a", `"\u001a"`},1001	{"\x1b", `"\u001b"`},1002	{"\x1c", `"\u001c"`},1003	{"\x1d", `"\u001d"`},1004	{"\x1e", `"\u001e"`},1005	{"\x1f", `"\u001f"`},1006}1007 1008func TestEncodeString(t *testing.T) {1009	for _, tt := range encodeStringTests {1010		b, err := Marshal(tt.in)1011		if err != nil {1012			t.Errorf("Marshal(%q) error: %v", tt.in, err)1013			continue1014		}1015		out := string(b)1016		if out != tt.out {1017			t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)1018		}1019	}1020}1021 1022type jsonbyte byte1023 1024func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }1025 1026type textbyte byte1027 1028func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }1029 1030type jsonint int1031 1032func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }1033 1034type textint int1035 1036func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }1037 1038func tenc(format string, a ...any) ([]byte, error) {1039	var buf bytes.Buffer1040	fmt.Fprintf(&buf, format, a...)1041	return buf.Bytes(), nil1042}1043 1044type textfloat float641045 1046func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }1047 1048// Issue 137831049func TestEncodeBytekind(t *testing.T) {1050	tests := []struct {1051		CaseName1052		in   any1053		want string1054	}{1055		{Name(""), byte(7), "7"},1056		{Name(""), jsonbyte(7), `{"JB":7}`},1057		{Name(""), textbyte(4), `"TB:4"`},1058		{Name(""), jsonint(5), `{"JI":5}`},1059		{Name(""), textint(1), `"TI:1"`},1060		{Name(""), []byte{0, 1}, `"AAE="`},1061		{Name(""), []jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},1062		{Name(""), [][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},1063		{Name(""), []textbyte{2, 3}, `["TB:2","TB:3"]`},1064		{Name(""), []jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},1065		{Name(""), []textint{9, 3}, `["TI:9","TI:3"]`},1066		{Name(""), []int{9, 3}, `[9,3]`},1067		{Name(""), []textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},1068	}1069	for _, tt := range tests {1070		t.Run(tt.Name, func(t *testing.T) {1071			b, err := Marshal(tt.in)1072			if err != nil {1073				t.Errorf("%s: Marshal error: %v", tt.Where, err)1074			}1075			got, want := string(b), tt.want1076			if got != want {1077				t.Errorf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, got, want)1078			}1079		})1080	}1081}1082 1083func TestTextMarshalerMapKeysAreSorted(t *testing.T) {1084	got, err := Marshal(map[unmarshalerText]int{1085		{"x", "y"}: 1,1086		{"y", "x"}: 2,1087		{"a", "z"}: 3,1088		{"z", "a"}: 4,1089	})1090	if err != nil {1091		t.Fatalf("Marshal error: %v", err)1092	}1093	const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`1094	if string(got) != want {1095		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)1096	}1097}1098 1099// https://golang.org/issue/336751100func TestNilMarshalerTextMapKey(t *testing.T) {1101	got, err := Marshal(map[*unmarshalerText]int{1102		(*unmarshalerText)(nil): 1,1103		{"A", "B"}:              2,1104	})1105	if err != nil {1106		t.Fatalf("Marshal error: %v", err)1107	}1108	const want = `{"":1,"A:B":2}`1109	if string(got) != want {1110		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)1111	}1112}1113 1114var re = regexp.MustCompile1115 1116// syntactic checks on form of marshaled floating point numbers.1117var badFloatREs = []*regexp.Regexp{1118	re(`p`),                     // no binary exponential notation1119	re(`^\+`),                   // no leading + sign1120	re(`^-?0[^.]`),              // no unnecessary leading zeros1121	re(`^-?\.`),                 // leading zero required before decimal point1122	re(`\.(e|$)`),               // no trailing decimal1123	re(`\.[0-9]+0(e|$)`),        // no trailing zero in fraction1124	re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa1125	re(`e[0-9]`),                // positive exponent must be signed1126	re(`e[+-]0`),                // exponent must not have leading zeros1127	re(`e-[1-6]$`),              // not tiny enough for exponential notation1128	re(`e+(.|1.|20)$`),          // not big enough for exponential notation1129	re(`^-?0\.0000000`),         // too tiny, should use exponential notation1130	re(`^-?[0-9]{22}`),          // too big, should use exponential notation1131	re(`[1-9][0-9]{16}[1-9]`),   // too many significant digits in integer1132	re(`[1-9][0-9.]{17}[1-9]`),  // too many significant digits in decimal1133	// below here for float32 only1134	re(`[1-9][0-9]{8}[1-9]`),  // too many significant digits in integer1135	re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal1136}1137 1138func TestMarshalFloat(t *testing.T) {1139	t.Parallel()1140	nfail := 01141	test := func(f float64, bits int) {1142		vf := any(f)1143		if bits == 32 {1144			f = float64(float32(f)) // round1145			vf = float32(f)1146		}1147		bout, err := Marshal(vf)1148		if err != nil {1149			t.Errorf("Marshal(%T(%g)) error: %v", vf, vf, err)1150			nfail++1151			return1152		}1153		out := string(bout)1154 1155		// result must convert back to the same float1156		g, err := strconv.ParseFloat(out, bits)1157		if err != nil {1158			t.Errorf("ParseFloat(%q) error: %v", out, err)1159			nfail++1160			return1161		}1162		if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±01163			t.Errorf("ParseFloat(%q):\n\tgot:  %g\n\twant: %g", out, float32(g), vf)1164			nfail++1165			return1166		}1167 1168		bad := badFloatREs1169		if bits == 64 {1170			bad = bad[:len(bad)-2]1171		}1172		for _, re := range bad {1173			if re.MatchString(out) {1174				t.Errorf("Marshal(%T(%g)) = %q; must not match /%s/", vf, vf, out, re)1175				nfail++1176				return1177			}1178		}1179	}1180 1181	var (1182		bigger  = math.Inf(+1)1183		smaller = math.Inf(-1)1184	)1185 1186	var digits = "1.2345678901234567890123"1187	for i := len(digits); i >= 2; i-- {1188		if testing.Short() && i < len(digits)-4 {1189			break1190		}1191		for exp := -30; exp <= 30; exp++ {1192			for _, sign := range "+-" {1193				for bits := 32; bits <= 64; bits += 32 {1194					s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)1195					f, err := strconv.ParseFloat(s, bits)1196					if err != nil {1197						log.Fatal(err)1198					}1199					next := math.Nextafter1200					if bits == 32 {

Showing the first 1,200 of 1426 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai