Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
v2_encode_test.go1431 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 isZeroer interface {93	IsZero() bool94}95 96type OptionalsZero struct {97	Sr string `json:"sr"`98	So string `json:"so,omitzero"`99	Sw string `json:"-"`100 101	Ir int `json:"omitzero"` // actually named omitzero, not an option102	Io int `json:"io,omitzero"`103 104	Slr       []string `json:"slr,random"`105	Slo       []string `json:"slo,omitzero"`106	SloNonNil []string `json:"slononnil,omitzero"`107 108	Mr  map[string]any `json:"mr"`109	Mo  map[string]any `json:",omitzero"`110	Moo map[string]any `json:"moo,omitzero"`111 112	Fr   float64    `json:"fr"`113	Fo   float64    `json:"fo,omitzero"`114	Foo  float64    `json:"foo,omitzero"`115	Foo2 [2]float64 `json:"foo2,omitzero"`116 117	Br bool `json:"br"`118	Bo bool `json:"bo,omitzero"`119 120	Ur uint `json:"ur"`121	Uo uint `json:"uo,omitzero"`122 123	Str struct{} `json:"str"`124	Sto struct{} `json:"sto,omitzero"`125 126	Time      time.Time     `json:"time,omitzero"`127	TimeLocal time.Time     `json:"timelocal,omitzero"`128	Nzs       NonZeroStruct `json:"nzs,omitzero"`129 130	NilIsZeroer    isZeroer       `json:"niliszeroer,omitzero"`    // nil interface131	NonNilIsZeroer isZeroer       `json:"nonniliszeroer,omitzero"` // non-nil interface132	NoPanicStruct0 isZeroer       `json:"nps0,omitzero"`           // non-nil interface with nil pointer133	NoPanicStruct1 isZeroer       `json:"nps1,omitzero"`           // non-nil interface with non-nil pointer134	NoPanicStruct2 *NoPanicStruct `json:"nps2,omitzero"`           // nil pointer135	NoPanicStruct3 *NoPanicStruct `json:"nps3,omitzero"`           // non-nil pointer136	NoPanicStruct4 NoPanicStruct  `json:"nps4,omitzero"`           // concrete type137}138 139func TestOmitZero(t *testing.T) {140	const want = `{141 "sr": "",142 "omitzero": 0,143 "slr": null,144 "slononnil": [],145 "mr": {},146 "Mo": {},147 "fr": 0,148 "br": false,149 "ur": 0,150 "str": {},151 "nzs": {},152 "nps1": {},153 "nps3": {},154 "nps4": {}155}`156	var o OptionalsZero157	o.Sw = "something"158	o.SloNonNil = make([]string, 0)159	o.Mr = map[string]any{}160	o.Mo = map[string]any{}161 162	o.Foo = -0163	o.Foo2 = [2]float64{+0, -0}164 165	o.TimeLocal = time.Time{}.Local()166 167	o.NonNilIsZeroer = time.Time{}168	o.NoPanicStruct0 = (*NoPanicStruct)(nil)169	o.NoPanicStruct1 = &NoPanicStruct{}170	o.NoPanicStruct3 = &NoPanicStruct{}171 172	got, err := MarshalIndent(&o, "", " ")173	if err != nil {174		t.Fatalf("MarshalIndent error: %v", err)175	}176	if got := string(got); got != want {177		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))178	}179}180 181func TestOmitZeroMap(t *testing.T) {182	const want = `{183 "foo": {184  "sr": "",185  "omitzero": 0,186  "slr": null,187  "mr": null,188  "fr": 0,189  "br": false,190  "ur": 0,191  "str": {},192  "nzs": {},193  "nps4": {}194 }195}`196	m := map[string]OptionalsZero{"foo": {}}197	got, err := MarshalIndent(m, "", " ")198	if err != nil {199		t.Fatalf("MarshalIndent error: %v", err)200	}201	if got := string(got); got != want {202		fmt.Println(got)203		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))204	}205}206 207type OptionalsEmptyZero struct {208	Sr string `json:"sr"`209	So string `json:"so,omitempty,omitzero"`210	Sw string `json:"-"`211 212	Io int `json:"io,omitempty,omitzero"`213 214	Slr       []string `json:"slr,random"`215	Slo       []string `json:"slo,omitempty,omitzero"`216	SloNonNil []string `json:"slononnil,omitempty,omitzero"`217 218	Mr map[string]any `json:"mr"`219	Mo map[string]any `json:",omitempty,omitzero"`220 221	Fr float64 `json:"fr"`222	Fo float64 `json:"fo,omitempty,omitzero"`223 224	Br bool `json:"br"`225	Bo bool `json:"bo,omitempty,omitzero"`226 227	Ur uint `json:"ur"`228	Uo uint `json:"uo,omitempty,omitzero"`229 230	Str struct{} `json:"str"`231	Sto struct{} `json:"sto,omitempty,omitzero"`232 233	Time time.Time     `json:"time,omitempty,omitzero"`234	Nzs  NonZeroStruct `json:"nzs,omitempty,omitzero"`235}236 237func TestOmitEmptyZero(t *testing.T) {238	const want = `{239 "sr": "",240 "slr": null,241 "mr": {},242 "fr": 0,243 "br": false,244 "ur": 0,245 "str": {},246 "nzs": {}247}`248	var o OptionalsEmptyZero249	o.Sw = "something"250	o.SloNonNil = make([]string, 0)251	o.Mr = map[string]any{}252	o.Mo = map[string]any{}253 254	got, err := MarshalIndent(&o, "", " ")255	if err != nil {256		t.Fatalf("MarshalIndent error: %v", err)257	}258	if got := string(got); got != want {259		t.Errorf("MarshalIndent:\n\tgot:  %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))260	}261}262 263type StringTag struct {264	BoolStr    bool    `json:",string"`265	IntStr     int64   `json:",string"`266	UintptrStr uintptr `json:",string"`267	StrStr     string  `json:",string"`268	NumberStr  Number  `json:",string"`269}270 271func TestRoundtripStringTag(t *testing.T) {272	tests := []struct {273		CaseName274		in   StringTag275		want string // empty to just test that we roundtrip276	}{{277		CaseName: Name("AllTypes"),278		in: StringTag{279			BoolStr:    true,280			IntStr:     42,281			UintptrStr: 44,282			StrStr:     "xzbit",283			NumberStr:  "46",284		},285		want: `{286	"BoolStr": "true",287	"IntStr": "42",288	"UintptrStr": "44",289	"StrStr": "\"xzbit\"",290	"NumberStr": "46"291}`,292	}, {293		// See golang.org/issues/38173.294		CaseName: Name("StringDoubleEscapes"),295		in: StringTag{296			StrStr:    "\b\f\n\r\t\"\\",297			NumberStr: "0", // just to satisfy the roundtrip298		},299		want: `{300	"BoolStr": "false",301	"IntStr": "0",302	"UintptrStr": "0",303	"StrStr": "\"\\b\\f\\n\\r\\t\\\"\\\\\"",304	"NumberStr": "0"305}`,306	}}307	for _, tt := range tests {308		t.Run(tt.Name, func(t *testing.T) {309			got, err := MarshalIndent(&tt.in, "", "\t")310			if err != nil {311				t.Fatalf("%s: MarshalIndent error: %v", tt.Where, err)312			}313			if got := string(got); got != tt.want {314				t.Fatalf("%s: MarshalIndent:\n\tgot:  %s\n\twant: %s", tt.Where, stripWhitespace(got), stripWhitespace(tt.want))315			}316 317			// Verify that it round-trips.318			var s2 StringTag319			if err := Unmarshal(got, &s2); err != nil {320				t.Fatalf("%s: Decode error: %v", tt.Where, err)321			}322			if !reflect.DeepEqual(s2, tt.in) {323				t.Fatalf("%s: Decode:\n\tinput: %s\n\tgot:  %#v\n\twant: %#v", tt.Where, indentNewlines(string(got)), s2, tt.in)324			}325		})326	}327}328 329// byte slices are special even if they're renamed types.330type renamedByte byte331type renamedByteSlice []byte332type renamedRenamedByteSlice []renamedByte333 334func TestEncodeRenamedByteSlice(t *testing.T) {335	s := renamedByteSlice("abc")336	got, err := Marshal(s)337	if err != nil {338		t.Fatalf("Marshal error: %v", err)339	}340	want := `"YWJj"`341	if string(got) != want {342		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)343	}344	r := renamedRenamedByteSlice("abc")345	got, err = Marshal(r)346	if err != nil {347		t.Fatalf("Marshal error: %v", err)348	}349	if string(got) != want {350		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)351	}352}353 354type SamePointerNoCycle struct {355	Ptr1, Ptr2 *SamePointerNoCycle356}357 358var samePointerNoCycle = &SamePointerNoCycle{}359 360type PointerCycle struct {361	Ptr *PointerCycle362}363 364var pointerCycle = &PointerCycle{}365 366type PointerCycleIndirect struct {367	Ptrs []any368}369 370type RecursiveSlice []RecursiveSlice371 372var (373	pointerCycleIndirect = &PointerCycleIndirect{}374	mapCycle             = make(map[string]any)375	sliceCycle           = []any{nil}376	sliceNoCycle         = []any{nil, nil}377	recursiveSliceCycle  = []RecursiveSlice{nil}378)379 380func init() {381	ptr := &SamePointerNoCycle{}382	samePointerNoCycle.Ptr1 = ptr383	samePointerNoCycle.Ptr2 = ptr384 385	pointerCycle.Ptr = pointerCycle386	pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}387 388	mapCycle["x"] = mapCycle389	sliceCycle[0] = sliceCycle390	sliceNoCycle[1] = sliceNoCycle[:1]391	const startDetectingCyclesAfter = 1e3392	for i := startDetectingCyclesAfter; i > 0; i-- {393		sliceNoCycle = []any{sliceNoCycle}394	}395	recursiveSliceCycle[0] = recursiveSliceCycle396}397 398func TestSamePointerNoCycle(t *testing.T) {399	if _, err := Marshal(samePointerNoCycle); err != nil {400		t.Fatalf("Marshal error: %v", err)401	}402}403 404func TestSliceNoCycle(t *testing.T) {405	if _, err := Marshal(sliceNoCycle); err != nil {406		t.Fatalf("Marshal error: %v", err)407	}408}409 410func TestUnsupportedValues(t *testing.T) {411	tests := []struct {412		CaseName413		in any414	}{415		{Name(""), math.NaN()},416		{Name(""), math.Inf(-1)},417		{Name(""), math.Inf(1)},418		{Name(""), pointerCycle},419		{Name(""), pointerCycleIndirect},420		{Name(""), mapCycle},421		{Name(""), sliceCycle},422		{Name(""), recursiveSliceCycle},423	}424	for _, tt := range tests {425		t.Run(tt.Name, func(t *testing.T) {426			if _, err := Marshal(tt.in); err != nil {427				if _, ok := err.(*UnsupportedValueError); !ok {428					t.Errorf("%s: Marshal error:\n\tgot:  %T\n\twant: %T", tt.Where, err, new(UnsupportedValueError))429				}430			} else {431				t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)432			}433		})434	}435}436 437// Issue 43207438func TestMarshalTextFloatMap(t *testing.T) {439	m := map[textfloat]string{440		textfloat(math.NaN()): "1",441		textfloat(math.NaN()): "1",442	}443	got, err := Marshal(m)444	if err != nil {445		t.Errorf("Marshal error: %v", err)446	}447	want := `{"TF:NaN":"1","TF:NaN":"1"}`448	if string(got) != want {449		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)450	}451}452 453// Ref has Marshaler and Unmarshaler methods with pointer receiver.454type Ref int455 456func (*Ref) MarshalJSON() ([]byte, error) {457	return []byte(`"ref"`), nil458}459 460func (r *Ref) UnmarshalJSON([]byte) error {461	*r = 12462	return nil463}464 465// Val has Marshaler methods with value receiver.466type Val int467 468func (Val) MarshalJSON() ([]byte, error) {469	return []byte(`"val"`), nil470}471 472// RefText has Marshaler and Unmarshaler methods with pointer receiver.473type RefText int474 475func (*RefText) MarshalText() ([]byte, error) {476	return []byte(`"ref"`), nil477}478 479func (r *RefText) UnmarshalText([]byte) error {480	*r = 13481	return nil482}483 484// ValText has Marshaler methods with value receiver.485type ValText int486 487func (ValText) MarshalText() ([]byte, error) {488	return []byte(`"val"`), nil489}490 491func TestRefValMarshal(t *testing.T) {492	var s = struct {493		R0 Ref494		R1 *Ref495		R2 RefText496		R3 *RefText497		V0 Val498		V1 *Val499		V2 ValText500		V3 *ValText501	}{502		R0: 12,503		R1: new(Ref),504		R2: 14,505		R3: new(RefText),506		V0: 13,507		V1: new(Val),508		V2: 15,509		V3: new(ValText),510	}511	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`512	b, err := Marshal(&s)513	if err != nil {514		t.Fatalf("Marshal error: %v", err)515	}516	if got := string(b); got != want {517		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)518	}519}520 521// C implements Marshaler and returns unescaped JSON.522type C int523 524func (C) MarshalJSON() ([]byte, error) {525	return []byte(`"<&>"`), nil526}527 528// CText implements Marshaler and returns unescaped text.529type CText int530 531func (CText) MarshalText() ([]byte, error) {532	return []byte(`"<&>"`), nil533}534 535func TestMarshalerEscaping(t *testing.T) {536	var c C537	want := `"\u003c\u0026\u003e"`538	b, err := Marshal(c)539	if err != nil {540		t.Fatalf("Marshal error: %v", err)541	}542	if got := string(b); got != want {543		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)544	}545 546	var ct CText547	want = `"\"\u003c\u0026\u003e\""`548	b, err = Marshal(ct)549	if err != nil {550		t.Fatalf("Marshal error: %v", err)551	}552	if got := string(b); got != want {553		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)554	}555}556 557func TestAnonymousFields(t *testing.T) {558	tests := []struct {559		CaseName560		makeInput func() any // Function to create input value561		want      string     // Expected JSON output562	}{{563		// Both S1 and S2 have a field named X. From the perspective of S,564		// it is ambiguous which one X refers to.565		// This should not serialize either field.566		CaseName: Name("AmbiguousField"),567		makeInput: func() any {568			type (569				S1 struct{ x, X int }570				S2 struct{ x, X int }571				S  struct {572					S1573					S2574				}575			)576			return S{S1{1, 2}, S2{3, 4}}577		},578		want: `{}`,579	}, {580		CaseName: Name("DominantField"),581		// Both S1 and S2 have a field named X, but since S has an X field as582		// well, it takes precedence over S1.X and S2.X.583		makeInput: func() any {584			type (585				S1 struct{ x, X int }586				S2 struct{ x, X int }587				S  struct {588					S1589					S2590					x, X int591				}592			)593			return S{S1{1, 2}, S2{3, 4}, 5, 6}594		},595		want: `{"X":6}`,596	}, {597		// Unexported embedded field of non-struct type should not be serialized.598		CaseName: Name("UnexportedEmbeddedInt"),599		makeInput: func() any {600			type (601				myInt int602				S     struct{ myInt }603			)604			return S{5}605		},606		want: `{}`,607	}, {608		// Exported embedded field of non-struct type should be serialized.609		CaseName: Name("ExportedEmbeddedInt"),610		makeInput: func() any {611			type (612				MyInt int613				S     struct{ MyInt }614			)615			return S{5}616		},617		want: `{"MyInt":5}`,618	}, {619		// Unexported embedded field of pointer to non-struct type620		// should not be serialized.621		CaseName: Name("UnexportedEmbeddedIntPointer"),622		makeInput: func() any {623			type (624				myInt int625				S     struct{ *myInt }626			)627			s := S{new(myInt)}628			*s.myInt = 5629			return s630		},631		want: `{}`,632	}, {633		// Exported embedded field of pointer to non-struct type634		// should be serialized.635		CaseName: Name("ExportedEmbeddedIntPointer"),636		makeInput: func() any {637			type (638				MyInt int639				S     struct{ *MyInt }640			)641			s := S{new(MyInt)}642			*s.MyInt = 5643			return s644		},645		want: `{"MyInt":5}`,646	}, {647		// Exported fields of embedded structs should have their648		// exported fields be serialized regardless of whether the struct types649		// themselves are exported.650		CaseName: Name("EmbeddedStruct"),651		makeInput: func() any {652			type (653				s1 struct{ x, X int }654				S2 struct{ y, Y int }655				S  struct {656					s1657					S2658				}659			)660			return S{s1{1, 2}, S2{3, 4}}661		},662		want: `{"X":2,"Y":4}`,663	}, {664		// Exported fields of pointers to embedded structs should have their665		// exported fields be serialized regardless of whether the struct types666		// themselves are exported.667		CaseName: Name("EmbeddedStructPointer"),668		makeInput: func() any {669			type (670				s1 struct{ x, X int }671				S2 struct{ y, Y int }672				S  struct {673					*s1674					*S2675				}676			)677			return S{&s1{1, 2}, &S2{3, 4}}678		},679		want: `{"X":2,"Y":4}`,680	}, {681		// Exported fields on embedded unexported structs at multiple levels682		// of nesting should still be serialized.683		CaseName: Name("NestedStructAndInts"),684		makeInput: func() any {685			type (686				MyInt1 int687				MyInt2 int688				myInt  int689				s2     struct {690					MyInt2691					myInt692				}693				s1 struct {694					MyInt1695					myInt696					s2697				}698				S struct {699					s1700					myInt701				}702			)703			return S{s1{1, 2, s2{3, 4}}, 6}704		},705		want: `{"MyInt1":1,"MyInt2":3}`,706	}, {707		// If an anonymous struct pointer field is nil, we should ignore708		// the embedded fields behind it. Not properly doing so may709		// result in the wrong output or reflect panics.710		CaseName: Name("EmbeddedFieldBehindNilPointer"),711		makeInput: func() any {712			type (713				S2 struct{ Field string }714				S  struct{ *S2 }715			)716			return S{}717		},718		want: `{}`,719	}}720 721	for _, tt := range tests {722		t.Run(tt.Name, func(t *testing.T) {723			b, err := Marshal(tt.makeInput())724			if err != nil {725				t.Fatalf("%s: Marshal error: %v", tt.Where, err)726			}727			if string(b) != tt.want {728				t.Fatalf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, b, tt.want)729			}730		})731	}732}733 734type BugA struct {735	S string736}737 738type BugB struct {739	BugA740	S string741}742 743type BugC struct {744	S string745}746 747// Legal Go: We never use the repeated embedded field (S).748type BugX struct {749	A int750	BugA751	BugB752}753 754// golang.org/issue/16042.755// Even if a nil interface value is passed in, as long as756// it implements Marshaler, it should be marshaled.757type nilJSONMarshaler string758 759func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {760	if nm == nil {761		return Marshal("0zenil0")762	}763	return Marshal("zenil:" + string(*nm))764}765 766// golang.org/issue/34235.767// Even if a nil interface value is passed in, as long as768// it implements encoding.TextMarshaler, it should be marshaled.769type nilTextMarshaler string770 771func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {772	if nm == nil {773		return []byte("0zenil0"), nil774	}775	return []byte("zenil:" + string(*nm)), nil776}777 778// See golang.org/issue/16042 and golang.org/issue/34235.779func TestNilMarshal(t *testing.T) {780	tests := []struct {781		CaseName782		in   any783		want string784	}{785		{Name(""), nil, `null`},786		{Name(""), new(float64), `0`},787		{Name(""), []any(nil), `null`},788		{Name(""), []string(nil), `null`},789		{Name(""), map[string]string(nil), `null`},790		{Name(""), []byte(nil), `null`},791		{Name(""), struct{ M string }{"gopher"}, `{"M":"gopher"}`},792		{Name(""), struct{ M Marshaler }{}, `{"M":null}`},793		{Name(""), struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, `{"M":"0zenil0"}`},794		{Name(""), struct{ M any }{(*nilJSONMarshaler)(nil)}, `{"M":null}`},795		{Name(""), struct{ M encoding.TextMarshaler }{}, `{"M":null}`},796		{Name(""), struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, `{"M":"0zenil0"}`},797		{Name(""), struct{ M any }{(*nilTextMarshaler)(nil)}, `{"M":null}`},798	}799	for _, tt := range tests {800		t.Run(tt.Name, func(t *testing.T) {801			switch got, err := Marshal(tt.in); {802			case err != nil:803				t.Fatalf("%s: Marshal error: %v", tt.Where, err)804			case string(got) != tt.want:805				t.Fatalf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, got, tt.want)806			}807		})808	}809}810 811// Issue 5245.812func TestEmbeddedBug(t *testing.T) {813	v := BugB{814		BugA{"A"},815		"B",816	}817	b, err := Marshal(v)818	if err != nil {819		t.Fatal("Marshal error:", err)820	}821	want := `{"S":"B"}`822	got := string(b)823	if got != want {824		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)825	}826	// Now check that the duplicate field, S, does not appear.827	x := BugX{828		A: 23,829	}830	b, err = Marshal(x)831	if err != nil {832		t.Fatal("Marshal error:", err)833	}834	want = `{"A":23}`835	got = string(b)836	if got != want {837		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)838	}839}840 841type BugD struct { // Same as BugA after tagging.842	XXX string `json:"S"`843}844 845// BugD's tagged S field should dominate BugA's.846type BugY struct {847	BugA848	BugD849}850 851// Test that a field with a tag dominates untagged fields.852func TestTaggedFieldDominates(t *testing.T) {853	v := BugY{854		BugA{"BugA"},855		BugD{"BugD"},856	}857	b, err := Marshal(v)858	if err != nil {859		t.Fatal("Marshal error:", err)860	}861	want := `{"S":"BugD"}`862	got := string(b)863	if got != want {864		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)865	}866}867 868// There are no tags here, so S should not appear.869type BugZ struct {870	BugA871	BugC872	BugY // Contains a tagged S field through BugD; should not dominate.873}874 875func TestDuplicatedFieldDisappears(t *testing.T) {876	v := BugZ{877		BugA{"BugA"},878		BugC{"BugC"},879		BugY{880			BugA{"nested BugA"},881			BugD{"nested BugD"},882		},883	}884	b, err := Marshal(v)885	if err != nil {886		t.Fatal("Marshal error:", err)887	}888	want := `{}`889	got := string(b)890	if got != want {891		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)892	}893}894 895func TestIssue10281(t *testing.T) {896	type Foo struct {897		N Number898	}899	x := Foo{Number(`invalid`)}900 901	if _, err := Marshal(&x); err == nil {902		t.Fatalf("Marshal error: got nil, want non-nil")903	}904}905 906func TestMarshalErrorAndReuseEncodeState(t *testing.T) {907	// Disable the GC temporarily to prevent encodeState's in Pool being cleaned away during the test.908	percent := debug.SetGCPercent(-1)909	defer debug.SetGCPercent(percent)910 911	// Trigger an error in Marshal with cyclic data.912	type Dummy struct {913		Name string914		Next *Dummy915	}916	dummy := Dummy{Name: "Dummy"}917	dummy.Next = &dummy918	if _, err := Marshal(dummy); err == nil {919		t.Errorf("Marshal error: got nil, want non-nil")920	}921 922	type Data struct {923		A string924		I int925	}926	want := Data{A: "a", I: 1}927	b, err := Marshal(want)928	if err != nil {929		t.Errorf("Marshal error: %v", err)930	}931 932	var got Data933	if err := Unmarshal(b, &got); err != nil {934		t.Errorf("Unmarshal error: %v", err)935	}936	if got != want {937		t.Errorf("Unmarshal:\n\tgot:  %v\n\twant: %v", got, want)938	}939}940 941func TestHTMLEscape(t *testing.T) {942	var b, want bytes.Buffer943	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`944	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))945	HTMLEscape(&b, []byte(m))946	if !bytes.Equal(b.Bytes(), want.Bytes()) {947		t.Errorf("HTMLEscape:\n\tgot:  %s\n\twant: %s", b.Bytes(), want.Bytes())948	}949}950 951// golang.org/issue/8582952func TestEncodePointerString(t *testing.T) {953	type stringPointer struct {954		N *int64 `json:"n,string"`955	}956	var n int64 = 42957	b, err := Marshal(stringPointer{N: &n})958	if err != nil {959		t.Fatalf("Marshal error: %v", err)960	}961	if got, want := string(b), `{"n":"42"}`; got != want {962		t.Fatalf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)963	}964	var back stringPointer965	switch err = Unmarshal(b, &back); {966	case err != nil:967		t.Fatalf("Unmarshal error: %v", err)968	case back.N == nil:969		t.Fatalf("Unmarshal: back.N = nil, want non-nil")970	case *back.N != 42:971		t.Fatalf("Unmarshal: *back.N = %d, want 42", *back.N)972	}973}974 975var encodeStringTests = []struct {976	in  string977	out string978}{979	{"\x00", `"\u0000"`},980	{"\x01", `"\u0001"`},981	{"\x02", `"\u0002"`},982	{"\x03", `"\u0003"`},983	{"\x04", `"\u0004"`},984	{"\x05", `"\u0005"`},985	{"\x06", `"\u0006"`},986	{"\x07", `"\u0007"`},987	{"\x08", `"\b"`},988	{"\x09", `"\t"`},989	{"\x0a", `"\n"`},990	{"\x0b", `"\u000b"`},991	{"\x0c", `"\f"`},992	{"\x0d", `"\r"`},993	{"\x0e", `"\u000e"`},994	{"\x0f", `"\u000f"`},995	{"\x10", `"\u0010"`},996	{"\x11", `"\u0011"`},997	{"\x12", `"\u0012"`},998	{"\x13", `"\u0013"`},999	{"\x14", `"\u0014"`},1000	{"\x15", `"\u0015"`},1001	{"\x16", `"\u0016"`},1002	{"\x17", `"\u0017"`},1003	{"\x18", `"\u0018"`},1004	{"\x19", `"\u0019"`},1005	{"\x1a", `"\u001a"`},1006	{"\x1b", `"\u001b"`},1007	{"\x1c", `"\u001c"`},1008	{"\x1d", `"\u001d"`},1009	{"\x1e", `"\u001e"`},1010	{"\x1f", `"\u001f"`},1011}1012 1013func TestEncodeString(t *testing.T) {1014	for _, tt := range encodeStringTests {1015		b, err := Marshal(tt.in)1016		if err != nil {1017			t.Errorf("Marshal(%q) error: %v", tt.in, err)1018			continue1019		}1020		out := string(b)1021		if out != tt.out {1022			t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)1023		}1024	}1025}1026 1027type jsonbyte byte1028 1029func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }1030 1031type textbyte byte1032 1033func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }1034 1035type jsonint int1036 1037func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }1038 1039type textint int1040 1041func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }1042 1043func tenc(format string, a ...any) ([]byte, error) {1044	var buf bytes.Buffer1045	fmt.Fprintf(&buf, format, a...)1046	return buf.Bytes(), nil1047}1048 1049type textfloat float641050 1051func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }1052 1053// Issue 137831054func TestEncodeBytekind(t *testing.T) {1055	tests := []struct {1056		CaseName1057		in   any1058		want string1059	}{1060		{Name(""), byte(7), "7"},1061		{Name(""), jsonbyte(7), `{"JB":7}`},1062		{Name(""), textbyte(4), `"TB:4"`},1063		{Name(""), jsonint(5), `{"JI":5}`},1064		{Name(""), textint(1), `"TI:1"`},1065		{Name(""), []byte{0, 1}, `"AAE="`},1066		{Name(""), []jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},1067		{Name(""), [][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},1068		{Name(""), []textbyte{2, 3}, `["TB:2","TB:3"]`},1069		{Name(""), []jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},1070		{Name(""), []textint{9, 3}, `["TI:9","TI:3"]`},1071		{Name(""), []int{9, 3}, `[9,3]`},1072		{Name(""), []textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},1073	}1074	for _, tt := range tests {1075		t.Run(tt.Name, func(t *testing.T) {1076			b, err := Marshal(tt.in)1077			if err != nil {1078				t.Errorf("%s: Marshal error: %v", tt.Where, err)1079			}1080			got, want := string(b), tt.want1081			if got != want {1082				t.Errorf("%s: Marshal:\n\tgot:  %s\n\twant: %s", tt.Where, got, want)1083			}1084		})1085	}1086}1087 1088func TestTextMarshalerMapKeysAreSorted(t *testing.T) {1089	got, err := Marshal(map[unmarshalerText]int{1090		{"x", "y"}: 1,1091		{"y", "x"}: 2,1092		{"a", "z"}: 3,1093		{"z", "a"}: 4,1094	})1095	if err != nil {1096		t.Fatalf("Marshal error: %v", err)1097	}1098	const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`1099	if string(got) != want {1100		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)1101	}1102}1103 1104// https://golang.org/issue/336751105func TestNilMarshalerTextMapKey(t *testing.T) {1106	got, err := Marshal(map[*unmarshalerText]int{1107		(*unmarshalerText)(nil): 1,1108		{"A", "B"}:              2,1109	})1110	if err != nil {1111		t.Fatalf("Marshal error: %v", err)1112	}1113	const want = `{"":1,"A:B":2}`1114	if string(got) != want {1115		t.Errorf("Marshal:\n\tgot:  %s\n\twant: %s", got, want)1116	}1117}1118 1119var re = regexp.MustCompile1120 1121// syntactic checks on form of marshaled floating point numbers.1122var badFloatREs = []*regexp.Regexp{1123	re(`p`),                     // no binary exponential notation1124	re(`^\+`),                   // no leading + sign1125	re(`^-?0[^.]`),              // no unnecessary leading zeros1126	re(`^-?\.`),                 // leading zero required before decimal point1127	re(`\.(e|$)`),               // no trailing decimal1128	re(`\.[0-9]+0(e|$)`),        // no trailing zero in fraction1129	re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa1130	re(`e[0-9]`),                // positive exponent must be signed1131	re(`e[+-]0`),                // exponent must not have leading zeros1132	re(`e-[1-6]$`),              // not tiny enough for exponential notation1133	re(`e+(.|1.|20)$`),          // not big enough for exponential notation1134	re(`^-?0\.0000000`),         // too tiny, should use exponential notation1135	re(`^-?[0-9]{22}`),          // too big, should use exponential notation1136	re(`[1-9][0-9]{16}[1-9]`),   // too many significant digits in integer1137	re(`[1-9][0-9.]{17}[1-9]`),  // too many significant digits in decimal1138	// below here for float32 only1139	re(`[1-9][0-9]{8}[1-9]`),  // too many significant digits in integer1140	re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal1141}1142 1143func TestMarshalFloat(t *testing.T) {1144	t.Parallel()1145	nfail := 01146	test := func(f float64, bits int) {1147		vf := any(f)1148		if bits == 32 {1149			f = float64(float32(f)) // round1150			vf = float32(f)1151		}1152		bout, err := Marshal(vf)1153		if err != nil {1154			t.Errorf("Marshal(%T(%g)) error: %v", vf, vf, err)1155			nfail++1156			return1157		}1158		out := string(bout)1159 1160		// result must convert back to the same float1161		g, err := strconv.ParseFloat(out, bits)1162		if err != nil {1163			t.Errorf("ParseFloat(%q) error: %v", out, err)1164			nfail++1165			return1166		}1167		if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±01168			t.Errorf("ParseFloat(%q):\n\tgot:  %g\n\twant: %g", out, float32(g), vf)1169			nfail++1170			return1171		}1172 1173		bad := badFloatREs1174		if bits == 64 {1175			bad = bad[:len(bad)-2]1176		}1177		for _, re := range bad {1178			if re.MatchString(out) {1179				t.Errorf("Marshal(%T(%g)) = %q; must not match /%s/", vf, vf, out, re)1180				nfail++1181				return1182			}1183		}1184	}1185 1186	var (1187		bigger  = math.Inf(+1)1188		smaller = math.Inf(-1)1189	)1190 1191	var digits = "1.2345678901234567890123"1192	for i := len(digits); i >= 2; i-- {1193		if testing.Short() && i < len(digits)-4 {1194			break1195		}1196		for exp := -30; exp <= 30; exp++ {1197			for _, sign := range "+-" {1198				for bits := 32; bits <= 64; bits += 32 {1199					s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)1200					f, err := strconv.ParseFloat(s, bits)

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

codekingpro/portable-devtools · Team Ai