github.com/searKing/golang/go@v1.2.117/encoding/prettyjson/encode_test.go (about)

     1  // Copyright 2023 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package prettyjson
     6  
     7  import (
     8  	"bytes"
     9  	"encoding"
    10  	"fmt"
    11  	"log"
    12  	"math"
    13  	"reflect"
    14  	"regexp"
    15  	"strconv"
    16  	"testing"
    17  )
    18  
    19  type Optionals struct {
    20  	Sr string `json:"sr"`
    21  	So string `json:"so,omitempty"`
    22  	Sw string `json:"-"`
    23  
    24  	Ir int `json:"omitempty"` // actually named omitempty, not an option
    25  	Io int `json:"io,omitempty"`
    26  
    27  	Slr []string `json:"slr,random"`
    28  	Slo []string `json:"slo,omitempty"`
    29  
    30  	Mr map[string]any `json:"mr"`
    31  	Mo map[string]any `json:",omitempty"`
    32  
    33  	Fr float64 `json:"fr"`
    34  	Fo float64 `json:"fo,omitempty"`
    35  
    36  	Br bool `json:"br"`
    37  	Bo bool `json:"bo,omitempty"`
    38  
    39  	Ur uint `json:"ur"`
    40  	Uo uint `json:"uo,omitempty"`
    41  
    42  	Str struct{} `json:"str"`
    43  	Sto struct{} `json:"sto,omitempty"`
    44  }
    45  
    46  var optionalsExpected = `{
    47   "sr": "",
    48   "omitempty": 0,
    49   "slr": null,
    50   "mr": {},
    51   "fr": 0,
    52   "br": false,
    53   "ur": 0,
    54   "str": {}
    55  }`
    56  
    57  func TestOmitEmpty(t *testing.T) {
    58  	var o Optionals
    59  	o.Sw = "something"
    60  	o.Mr = map[string]any{}
    61  	o.Mo = map[string]any{}
    62  
    63  	got, err := MarshalIndent(&o, "", " ")
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	if got := string(got); got != optionalsExpected {
    68  		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
    69  	}
    70  }
    71  
    72  type StringTag struct {
    73  	BoolStr    bool    `json:",string"`
    74  	IntStr     int64   `json:",string"`
    75  	UintptrStr uintptr `json:",string"`
    76  	StrStr     string  `json:",string"`
    77  	NumberStr  Number  `json:",string"`
    78  }
    79  
    80  // byte slices are special even if they're renamed types.
    81  type renamedByte byte
    82  type renamedByteSlice []byte
    83  type renamedRenamedByteSlice []renamedByte
    84  
    85  func TestEncodeRenamedByteSlice(t *testing.T) {
    86  	s := renamedByteSlice("abc")
    87  	result, err := Marshal(s)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	expect := `"YWJj"`
    92  	if string(result) != expect {
    93  		t.Errorf(" got %s want %s", result, expect)
    94  	}
    95  	r := renamedRenamedByteSlice("abc")
    96  	result, err = Marshal(r)
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  	if string(result) != expect {
   101  		t.Errorf(" got %s want %s", result, expect)
   102  	}
   103  }
   104  
   105  type SamePointerNoCycle struct {
   106  	Ptr1, Ptr2 *SamePointerNoCycle
   107  }
   108  
   109  var samePointerNoCycle = &SamePointerNoCycle{}
   110  
   111  type PointerCycle struct {
   112  	Ptr *PointerCycle
   113  }
   114  
   115  var pointerCycle = &PointerCycle{}
   116  
   117  type PointerCycleIndirect struct {
   118  	Ptrs []any
   119  }
   120  
   121  type RecursiveSlice []RecursiveSlice
   122  
   123  var (
   124  	pointerCycleIndirect = &PointerCycleIndirect{}
   125  	mapCycle             = make(map[string]any)
   126  	sliceCycle           = []any{nil}
   127  	sliceNoCycle         = []any{nil, nil}
   128  	recursiveSliceCycle  = []RecursiveSlice{nil}
   129  )
   130  
   131  func init() {
   132  	ptr := &SamePointerNoCycle{}
   133  	samePointerNoCycle.Ptr1 = ptr
   134  	samePointerNoCycle.Ptr2 = ptr
   135  
   136  	pointerCycle.Ptr = pointerCycle
   137  	pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}
   138  
   139  	mapCycle["x"] = mapCycle
   140  	sliceCycle[0] = sliceCycle
   141  	sliceNoCycle[1] = sliceNoCycle[:1]
   142  	for i := startDetectingCyclesAfter; i > 0; i-- {
   143  		sliceNoCycle = []any{sliceNoCycle}
   144  	}
   145  	recursiveSliceCycle[0] = recursiveSliceCycle
   146  }
   147  
   148  func TestSamePointerNoCycle(t *testing.T) {
   149  	if _, err := Marshal(samePointerNoCycle); err != nil {
   150  		t.Fatalf("unexpected error: %v", err)
   151  	}
   152  }
   153  
   154  func TestSliceNoCycle(t *testing.T) {
   155  	if _, err := Marshal(sliceNoCycle); err != nil {
   156  		t.Fatalf("unexpected error: %v", err)
   157  	}
   158  }
   159  
   160  var unsupportedValues = []any{
   161  	math.NaN(),
   162  	math.Inf(-1),
   163  	math.Inf(1),
   164  	pointerCycle,
   165  	pointerCycleIndirect,
   166  	mapCycle,
   167  	sliceCycle,
   168  	recursiveSliceCycle,
   169  }
   170  
   171  func TestUnsupportedValues(t *testing.T) {
   172  	for _, v := range unsupportedValues {
   173  		if _, err := Marshal(v); err != nil {
   174  			if _, ok := err.(*UnsupportedValueError); !ok {
   175  				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
   176  			}
   177  		} else {
   178  			t.Errorf("for %v, expected error", v)
   179  		}
   180  	}
   181  }
   182  
   183  // Issue 43207
   184  func TestMarshalTextFloatMap(t *testing.T) {
   185  	m := map[textfloat]string{
   186  		textfloat(math.NaN()): "1",
   187  		textfloat(math.NaN()): "1",
   188  	}
   189  	got, err := Marshal(m)
   190  	if err != nil {
   191  		t.Errorf("Marshal() error: %v", err)
   192  	}
   193  	want := `{"TF:NaN":"1","TF:NaN":"1"}`
   194  	if string(got) != want {
   195  		t.Errorf("Marshal() = %s, want %s", got, want)
   196  	}
   197  }
   198  
   199  // Ref has Marshaler and Unmarshaler methods with pointer receiver.
   200  type Ref int
   201  
   202  func (*Ref) MarshalJSON() ([]byte, error) {
   203  	return []byte(`"ref"`), nil
   204  }
   205  
   206  func (r *Ref) UnmarshalJSON([]byte) error {
   207  	*r = 12
   208  	return nil
   209  }
   210  
   211  // Val has Marshaler methods with value receiver.
   212  type Val int
   213  
   214  func (Val) MarshalJSON() ([]byte, error) {
   215  	return []byte(`"val"`), nil
   216  }
   217  
   218  // RefText has Marshaler and Unmarshaler methods with pointer receiver.
   219  type RefText int
   220  
   221  func (*RefText) MarshalText() ([]byte, error) {
   222  	return []byte(`"ref"`), nil
   223  }
   224  
   225  func (r *RefText) UnmarshalText([]byte) error {
   226  	*r = 13
   227  	return nil
   228  }
   229  
   230  // ValText has Marshaler methods with value receiver.
   231  type ValText int
   232  
   233  func (ValText) MarshalText() ([]byte, error) {
   234  	return []byte(`"val"`), nil
   235  }
   236  
   237  func TestRefValMarshal(t *testing.T) {
   238  	var s = struct {
   239  		R0 Ref
   240  		R1 *Ref
   241  		R2 RefText
   242  		R3 *RefText
   243  		V0 Val
   244  		V1 *Val
   245  		V2 ValText
   246  		V3 *ValText
   247  	}{
   248  		R0: 12,
   249  		R1: new(Ref),
   250  		R2: 14,
   251  		R3: new(RefText),
   252  		V0: 13,
   253  		V1: new(Val),
   254  		V2: 15,
   255  		V3: new(ValText),
   256  	}
   257  	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
   258  	b, err := Marshal(&s)
   259  	if err != nil {
   260  		t.Fatalf("Marshal: %v", err)
   261  	}
   262  	if got := string(b); got != want {
   263  		t.Errorf("got %q, want %q", got, want)
   264  	}
   265  }
   266  
   267  // C implements Marshaler and returns unescaped JSON.
   268  type C int
   269  
   270  func (C) MarshalJSON() ([]byte, error) {
   271  	return []byte(`"<&>"`), nil
   272  }
   273  
   274  // CText implements Marshaler and returns unescaped text.
   275  type CText int
   276  
   277  func (CText) MarshalText() ([]byte, error) {
   278  	return []byte(`"<&>"`), nil
   279  }
   280  
   281  func TestMarshalerEscaping(t *testing.T) {
   282  	var c C
   283  	want := `"\u003c\u0026\u003e"`
   284  	b, err := Marshal(c)
   285  	if err != nil {
   286  		t.Fatalf("Marshal(c): %v", err)
   287  	}
   288  	if got := string(b); got != want {
   289  		t.Errorf("Marshal(c) = %#q, want %#q", got, want)
   290  	}
   291  
   292  	var ct CText
   293  	want = `"\"\u003c\u0026\u003e\""`
   294  	b, err = Marshal(ct)
   295  	if err != nil {
   296  		t.Fatalf("Marshal(ct): %v", err)
   297  	}
   298  	if got := string(b); got != want {
   299  		t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
   300  	}
   301  }
   302  
   303  func TestAnonymousFields(t *testing.T) {
   304  	tests := []struct {
   305  		label     string     // Test name
   306  		makeInput func() any // Function to create input value
   307  		want      string     // Expected JSON output
   308  	}{{
   309  		// Both S1 and S2 have a field named X. From the perspective of S,
   310  		// it is ambiguous which one X refers to.
   311  		// This should not serialize either field.
   312  		label: "AmbiguousField",
   313  		makeInput: func() any {
   314  			type (
   315  				S1 struct{ x, X int }
   316  				S2 struct{ x, X int }
   317  				S  struct {
   318  					S1
   319  					S2
   320  				}
   321  			)
   322  			return S{S1{1, 2}, S2{3, 4}}
   323  		},
   324  		want: `{}`,
   325  	}, {
   326  		label: "DominantField",
   327  		// Both S1 and S2 have a field named X, but since S has an X field as
   328  		// well, it takes precedence over S1.X and S2.X.
   329  		makeInput: func() any {
   330  			type (
   331  				S1 struct{ x, X int }
   332  				S2 struct{ x, X int }
   333  				S  struct {
   334  					S1
   335  					S2
   336  					x, X int
   337  				}
   338  			)
   339  			return S{S1{1, 2}, S2{3, 4}, 5, 6}
   340  		},
   341  		want: `{"X":6}`,
   342  	}, {
   343  		// Unexported embedded field of non-struct type should not be serialized.
   344  		label: "UnexportedEmbeddedInt",
   345  		makeInput: func() any {
   346  			type (
   347  				myInt int
   348  				S     struct{ myInt }
   349  			)
   350  			return S{5}
   351  		},
   352  		want: `{}`,
   353  	}, {
   354  		// Exported embedded field of non-struct type should be serialized.
   355  		label: "ExportedEmbeddedInt",
   356  		makeInput: func() any {
   357  			type (
   358  				MyInt int
   359  				S     struct{ MyInt }
   360  			)
   361  			return S{5}
   362  		},
   363  		want: `{"MyInt":5}`,
   364  	}, {
   365  		// Unexported embedded field of pointer to non-struct type
   366  		// should not be serialized.
   367  		label: "UnexportedEmbeddedIntPointer",
   368  		makeInput: func() any {
   369  			type (
   370  				myInt int
   371  				S     struct{ *myInt }
   372  			)
   373  			s := S{new(myInt)}
   374  			*s.myInt = 5
   375  			return s
   376  		},
   377  		want: `{}`,
   378  	}, {
   379  		// Exported embedded field of pointer to non-struct type
   380  		// should be serialized.
   381  		label: "ExportedEmbeddedIntPointer",
   382  		makeInput: func() any {
   383  			type (
   384  				MyInt int
   385  				S     struct{ *MyInt }
   386  			)
   387  			s := S{new(MyInt)}
   388  			*s.MyInt = 5
   389  			return s
   390  		},
   391  		want: `{"MyInt":5}`,
   392  	}, {
   393  		// Exported fields of embedded structs should have their
   394  		// exported fields be serialized regardless of whether the struct types
   395  		// themselves are exported.
   396  		label: "EmbeddedStruct",
   397  		makeInput: func() any {
   398  			type (
   399  				s1 struct{ x, X int }
   400  				S2 struct{ y, Y int }
   401  				S  struct {
   402  					s1
   403  					S2
   404  				}
   405  			)
   406  			return S{s1{1, 2}, S2{3, 4}}
   407  		},
   408  		want: `{"X":2,"Y":4}`,
   409  	}, {
   410  		// Exported fields of pointers to embedded structs should have their
   411  		// exported fields be serialized regardless of whether the struct types
   412  		// themselves are exported.
   413  		label: "EmbeddedStructPointer",
   414  		makeInput: func() any {
   415  			type (
   416  				s1 struct{ x, X int }
   417  				S2 struct{ y, Y int }
   418  				S  struct {
   419  					*s1
   420  					*S2
   421  				}
   422  			)
   423  			return S{&s1{1, 2}, &S2{3, 4}}
   424  		},
   425  		want: `{"X":2,"Y":4}`,
   426  	}, {
   427  		// Exported fields on embedded unexported structs at multiple levels
   428  		// of nesting should still be serialized.
   429  		label: "NestedStructAndInts",
   430  		makeInput: func() any {
   431  			type (
   432  				MyInt1 int
   433  				MyInt2 int
   434  				myInt  int
   435  				s2     struct {
   436  					MyInt2
   437  					myInt
   438  				}
   439  				s1 struct {
   440  					MyInt1
   441  					myInt
   442  					s2
   443  				}
   444  				S struct {
   445  					s1
   446  					myInt
   447  				}
   448  			)
   449  			return S{s1{1, 2, s2{3, 4}}, 6}
   450  		},
   451  		want: `{"MyInt1":1,"MyInt2":3}`,
   452  	}, {
   453  		// If an anonymous struct pointer field is nil, we should ignore
   454  		// the embedded fields behind it. Not properly doing so may
   455  		// result in the wrong output or reflect panics.
   456  		label: "EmbeddedFieldBehindNilPointer",
   457  		makeInput: func() any {
   458  			type (
   459  				S2 struct{ Field string }
   460  				S  struct{ *S2 }
   461  			)
   462  			return S{}
   463  		},
   464  		want: `{}`,
   465  	}}
   466  
   467  	for _, tt := range tests {
   468  		t.Run(tt.label, func(t *testing.T) {
   469  			b, err := Marshal(tt.makeInput())
   470  			if err != nil {
   471  				t.Fatalf("Marshal() = %v, want nil error", err)
   472  			}
   473  			if string(b) != tt.want {
   474  				t.Fatalf("Marshal() = %q, want %q", b, tt.want)
   475  			}
   476  		})
   477  	}
   478  }
   479  
   480  type BugA struct {
   481  	S string
   482  }
   483  
   484  type BugB struct {
   485  	BugA
   486  	S string
   487  }
   488  
   489  type BugC struct {
   490  	S string
   491  }
   492  
   493  // Legal Go: We never use the repeated embedded field (S).
   494  type BugX struct {
   495  	A int
   496  	BugA
   497  	BugB
   498  }
   499  
   500  // golang.org/issue/16042.
   501  // Even if a nil interface value is passed in, as long as
   502  // it implements Marshaler, it should be marshaled.
   503  type nilJSONMarshaler string
   504  
   505  func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
   506  	if nm == nil {
   507  		return Marshal("0zenil0")
   508  	}
   509  	return Marshal("zenil:" + string(*nm))
   510  }
   511  
   512  // golang.org/issue/34235.
   513  // Even if a nil interface value is passed in, as long as
   514  // it implements encoding.TextMarshaler, it should be marshaled.
   515  type nilTextMarshaler string
   516  
   517  func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
   518  	if nm == nil {
   519  		return []byte("0zenil0"), nil
   520  	}
   521  	return []byte("zenil:" + string(*nm)), nil
   522  }
   523  
   524  // See golang.org/issue/16042 and golang.org/issue/34235.
   525  func TestNilMarshal(t *testing.T) {
   526  	testCases := []struct {
   527  		v    any
   528  		want string
   529  	}{
   530  		{v: nil, want: `null`},
   531  		{v: new(float64), want: `0`},
   532  		{v: []any(nil), want: `null`},
   533  		{v: []string(nil), want: `null`},
   534  		{v: map[string]string(nil), want: `null`},
   535  		{v: []byte(nil), want: `null`},
   536  		{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
   537  		{v: struct{ M Marshaler }{}, want: `{"M":null}`},
   538  		{v: struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
   539  		{v: struct{ M any }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
   540  		{v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
   541  		{v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
   542  		{v: struct{ M any }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
   543  	}
   544  
   545  	for _, tt := range testCases {
   546  		out, err := Marshal(tt.v)
   547  		if err != nil || string(out) != tt.want {
   548  			t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want)
   549  			continue
   550  		}
   551  	}
   552  }
   553  
   554  // Issue 5245.
   555  func TestEmbeddedBug(t *testing.T) {
   556  	v := BugB{
   557  		BugA{"A"},
   558  		"B",
   559  	}
   560  	b, err := Marshal(v)
   561  	if err != nil {
   562  		t.Fatal("Marshal:", err)
   563  	}
   564  	want := `{"S":"B"}`
   565  	got := string(b)
   566  	if got != want {
   567  		t.Fatalf("Marshal: got %s want %s", got, want)
   568  	}
   569  	// Now check that the duplicate field, S, does not appear.
   570  	x := BugX{
   571  		A: 23,
   572  	}
   573  	b, err = Marshal(x)
   574  	if err != nil {
   575  		t.Fatal("Marshal:", err)
   576  	}
   577  	want = `{"A":23}`
   578  	got = string(b)
   579  	if got != want {
   580  		t.Fatalf("Marshal: got %s want %s", got, want)
   581  	}
   582  }
   583  
   584  type BugD struct { // Same as BugA after tagging.
   585  	XXX string `json:"S"`
   586  }
   587  
   588  // BugD's tagged S field should dominate BugA's.
   589  type BugY struct {
   590  	BugA
   591  	BugD
   592  }
   593  
   594  // Test that a field with a tag dominates untagged fields.
   595  func TestTaggedFieldDominates(t *testing.T) {
   596  	v := BugY{
   597  		BugA{"BugA"},
   598  		BugD{"BugD"},
   599  	}
   600  	b, err := Marshal(v)
   601  	if err != nil {
   602  		t.Fatal("Marshal:", err)
   603  	}
   604  	want := `{"S":"BugD"}`
   605  	got := string(b)
   606  	if got != want {
   607  		t.Fatalf("Marshal: got %s want %s", got, want)
   608  	}
   609  }
   610  
   611  // There are no tags here, so S should not appear.
   612  type BugZ struct {
   613  	BugA
   614  	BugC
   615  	BugY // Contains a tagged S field through BugD; should not dominate.
   616  }
   617  
   618  func TestDuplicatedFieldDisappears(t *testing.T) {
   619  	v := BugZ{
   620  		BugA{"BugA"},
   621  		BugC{"BugC"},
   622  		BugY{
   623  			BugA{"nested BugA"},
   624  			BugD{"nested BugD"},
   625  		},
   626  	}
   627  	b, err := Marshal(v)
   628  	if err != nil {
   629  		t.Fatal("Marshal:", err)
   630  	}
   631  	want := `{}`
   632  	got := string(b)
   633  	if got != want {
   634  		t.Fatalf("Marshal: got %s want %s", got, want)
   635  	}
   636  }
   637  
   638  func TestIssue10281(t *testing.T) {
   639  	type Foo struct {
   640  		N Number
   641  	}
   642  	x := Foo{Number(`invalid`)}
   643  
   644  	b, err := Marshal(&x)
   645  	if err == nil {
   646  		t.Errorf("Marshal(&x) = %#q; want error", b)
   647  	}
   648  }
   649  
   650  var encodeStringTests = []struct {
   651  	in  string
   652  	out string
   653  }{
   654  	{"\x00", `"\u0000"`},
   655  	{"\x01", `"\u0001"`},
   656  	{"\x02", `"\u0002"`},
   657  	{"\x03", `"\u0003"`},
   658  	{"\x04", `"\u0004"`},
   659  	{"\x05", `"\u0005"`},
   660  	{"\x06", `"\u0006"`},
   661  	{"\x07", `"\u0007"`},
   662  	{"\x08", `"\u0008"`},
   663  	{"\x09", `"\t"`},
   664  	{"\x0a", `"\n"`},
   665  	{"\x0b", `"\u000b"`},
   666  	{"\x0c", `"\u000c"`},
   667  	{"\x0d", `"\r"`},
   668  	{"\x0e", `"\u000e"`},
   669  	{"\x0f", `"\u000f"`},
   670  	{"\x10", `"\u0010"`},
   671  	{"\x11", `"\u0011"`},
   672  	{"\x12", `"\u0012"`},
   673  	{"\x13", `"\u0013"`},
   674  	{"\x14", `"\u0014"`},
   675  	{"\x15", `"\u0015"`},
   676  	{"\x16", `"\u0016"`},
   677  	{"\x17", `"\u0017"`},
   678  	{"\x18", `"\u0018"`},
   679  	{"\x19", `"\u0019"`},
   680  	{"\x1a", `"\u001a"`},
   681  	{"\x1b", `"\u001b"`},
   682  	{"\x1c", `"\u001c"`},
   683  	{"\x1d", `"\u001d"`},
   684  	{"\x1e", `"\u001e"`},
   685  	{"\x1f", `"\u001f"`},
   686  }
   687  
   688  func TestEncodeString(t *testing.T) {
   689  	for _, tt := range encodeStringTests {
   690  		b, err := Marshal(tt.in)
   691  		if err != nil {
   692  			t.Errorf("Marshal(%q): %v", tt.in, err)
   693  			continue
   694  		}
   695  		out := string(b)
   696  		if out != tt.out {
   697  			t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
   698  		}
   699  	}
   700  }
   701  
   702  type jsonbyte byte
   703  
   704  func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
   705  
   706  type textbyte byte
   707  
   708  func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
   709  
   710  type jsonint int
   711  
   712  func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
   713  
   714  type textint int
   715  
   716  func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
   717  
   718  func tenc(format string, a ...any) ([]byte, error) {
   719  	var buf bytes.Buffer
   720  	fmt.Fprintf(&buf, format, a...)
   721  	return buf.Bytes(), nil
   722  }
   723  
   724  type textfloat float64
   725  
   726  func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
   727  
   728  // Issue 13783
   729  func TestEncodeBytekind(t *testing.T) {
   730  	testdata := []struct {
   731  		data any
   732  		want string
   733  	}{
   734  		{byte(7), "7"},
   735  		{jsonbyte(7), `{"JB":7}`},
   736  		{textbyte(4), `"TB:4"`},
   737  		{jsonint(5), `{"JI":5}`},
   738  		{textint(1), `"TI:1"`},
   739  		{[]byte{0, 1}, `"AAE="`},
   740  		{[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
   741  		{[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
   742  		{[]textbyte{2, 3}, `["TB:2","TB:3"]`},
   743  		{[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
   744  		{[]textint{9, 3}, `["TI:9","TI:3"]`},
   745  		{[]int{9, 3}, `[9,3]`},
   746  		{[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
   747  	}
   748  	for _, d := range testdata {
   749  		js, err := Marshal(d.data)
   750  		if err != nil {
   751  			t.Error(err)
   752  			continue
   753  		}
   754  		got, want := string(js), d.want
   755  		if got != want {
   756  			t.Errorf("got %s, want %s", got, want)
   757  		}
   758  	}
   759  }
   760  
   761  var re = regexp.MustCompile
   762  
   763  // syntactic checks on form of marshaled floating point numbers.
   764  var badFloatREs = []*regexp.Regexp{
   765  	re(`p`),                     // no binary exponential notation
   766  	re(`^\+`),                   // no leading + sign
   767  	re(`^-?0[^.]`),              // no unnecessary leading zeros
   768  	re(`^-?\.`),                 // leading zero required before decimal point
   769  	re(`\.(e|$)`),               // no trailing decimal
   770  	re(`\.[0-9]+0(e|$)`),        // no trailing zero in fraction
   771  	re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa
   772  	re(`e[0-9]`),                // positive exponent must be signed
   773  	re(`e[+-]0`),                // exponent must not have leading zeros
   774  	re(`e-[1-6]$`),              // not tiny enough for exponential notation
   775  	re(`e+(.|1.|20)$`),          // not big enough for exponential notation
   776  	re(`^-?0\.0000000`),         // too tiny, should use exponential notation
   777  	re(`^-?[0-9]{22}`),          // too big, should use exponential notation
   778  	re(`[1-9][0-9]{16}[1-9]`),   // too many significant digits in integer
   779  	re(`[1-9][0-9.]{17}[1-9]`),  // too many significant digits in decimal
   780  	// below here for float32 only
   781  	re(`[1-9][0-9]{8}[1-9]`),  // too many significant digits in integer
   782  	re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal
   783  }
   784  
   785  func TestMarshalFloat(t *testing.T) {
   786  	t.Parallel()
   787  	nfail := 0
   788  	test := func(f float64, bits int) {
   789  		vf := any(f)
   790  		if bits == 32 {
   791  			f = float64(float32(f)) // round
   792  			vf = float32(f)
   793  		}
   794  		bout, err := Marshal(vf)
   795  		if err != nil {
   796  			t.Errorf("Marshal(%T(%g)): %v", vf, vf, err)
   797  			nfail++
   798  			return
   799  		}
   800  		out := string(bout)
   801  
   802  		// result must convert back to the same float
   803  		g, err := strconv.ParseFloat(out, bits)
   804  		if err != nil {
   805  			t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err)
   806  			nfail++
   807  			return
   808  		}
   809  		if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0
   810  			t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf)
   811  			nfail++
   812  			return
   813  		}
   814  
   815  		bad := badFloatREs
   816  		if bits == 64 {
   817  			bad = bad[:len(bad)-2]
   818  		}
   819  		for _, re := range bad {
   820  			if re.MatchString(out) {
   821  				t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re)
   822  				nfail++
   823  				return
   824  			}
   825  		}
   826  	}
   827  
   828  	var (
   829  		bigger  = math.Inf(+1)
   830  		smaller = math.Inf(-1)
   831  	)
   832  
   833  	var digits = "1.2345678901234567890123"
   834  	for i := len(digits); i >= 2; i-- {
   835  		if testing.Short() && i < len(digits)-4 {
   836  			break
   837  		}
   838  		for exp := -30; exp <= 30; exp++ {
   839  			for _, sign := range "+-" {
   840  				for bits := 32; bits <= 64; bits += 32 {
   841  					s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
   842  					f, err := strconv.ParseFloat(s, bits)
   843  					if err != nil {
   844  						log.Fatal(err)
   845  					}
   846  					next := math.Nextafter
   847  					if bits == 32 {
   848  						next = func(g, h float64) float64 {
   849  							return float64(math.Nextafter32(float32(g), float32(h)))
   850  						}
   851  					}
   852  					test(f, bits)
   853  					test(next(f, bigger), bits)
   854  					test(next(f, smaller), bits)
   855  					if nfail > 50 {
   856  						t.Fatalf("stopping test early")
   857  					}
   858  				}
   859  			}
   860  		}
   861  	}
   862  	test(0, 64)
   863  	test(math.Copysign(0, -1), 64)
   864  	test(0, 32)
   865  	test(math.Copysign(0, -1), 32)
   866  }
   867  
   868  type marshalPanic struct{}
   869  
   870  func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
   871  
   872  func TestMarshalPanic(t *testing.T) {
   873  	defer func() {
   874  		if got := recover(); !reflect.DeepEqual(got, 0xdead) {
   875  			t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
   876  		}
   877  	}()
   878  	Marshal(&marshalPanic{})
   879  	t.Error("Marshal should have panicked")
   880  }
   881  
   882  func TestMarshalUncommonFieldNames(t *testing.T) {
   883  	v := struct {
   884  		A0, À, Aβ int
   885  	}{}
   886  	b, err := Marshal(v)
   887  	if err != nil {
   888  		t.Fatal("Marshal:", err)
   889  	}
   890  	want := `{"A0":0,"À":0,"Aβ":0}`
   891  	got := string(b)
   892  	if got != want {
   893  		t.Fatalf("Marshal: got %s want %s", got, want)
   894  	}
   895  }
   896  
   897  type marshalTruncate struct {
   898  	Sr string `json:"sr"`
   899  
   900  	Blr []byte `json:"blr,random"`
   901  
   902  	Slr []string `json:"slr,random"`
   903  
   904  	Mr map[string]*marshalTruncate `json:"mr"`
   905  
   906  	Str *marshalTruncate `json:"str"`
   907  }
   908  
   909  var truncateExpected = `{
   910   "sr": "ab...26 chars",
   911   "blr": "YWI=...52 bytes",
   912   "slr": [
   913    "0 ...28 chars",
   914    "1 ...54 chars",
   915    "...7 elems"
   916   ],
   917   "mr": {
   918    "a": {
   919     "sr": "ab...26 chars",
   920     "blr": "YWI=...26 bytes",
   921     "slr": [
   922      "0 ...28 chars",
   923      "1 ...54 chars",
   924      "...7 elems"
   925     ],
   926     "mr": null,
   927     "str": null
   928    },
   929    "b": null,
   930    "...4 pairs": "4"
   931   },
   932   "str": {
   933    "sr": "ab...26 chars",
   934    "blr": "YWI=...26 bytes",
   935    "slr": [
   936     "0 ...28 chars",
   937     "1 ...54 chars",
   938     "...7 elems"
   939    ],
   940    "mr": null,
   941    "str": null
   942   }
   943  }`
   944  
   945  func TestTruncateMarshal(t *testing.T) {
   946  	var o = marshalTruncate{
   947  		Sr:  "abcdefghihklmnopqrstuvwxyz",
   948  		Blr: []byte("abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
   949  		Slr: []string{"0 abcdefghihklmnopqrstuvwxyz",
   950  			"1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   951  			"2 abcdefghihklmnopqrstuvwxyzA",
   952  			"3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   953  			"4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   954  			"5 abcdefghihklmnopqrstuvwxyzA",
   955  			"6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"},
   956  		Mr: map[string]*marshalTruncate{
   957  			"a": {
   958  				Sr:  "abcdefghihklmnopqrstuvwxyz",
   959  				Blr: []byte("abcdefghihklmnopqrstuvwxyz"),
   960  				Slr: []string{"0 abcdefghihklmnopqrstuvwxyz",
   961  					"1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   962  					"2 abcdefghihklmnopqrstuvwxyzA",
   963  					"3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   964  					"4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   965  					"5 abcdefghihklmnopqrstuvwxyzA",
   966  					"6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"},
   967  				Mr:  nil,
   968  				Str: nil,
   969  			},
   970  			"b": nil,
   971  			"c": nil,
   972  			"d": nil,
   973  		},
   974  		Str: &marshalTruncate{
   975  			Sr:  "abcdefghihklmnopqrstuvwxyz",
   976  			Blr: []byte("abcdefghihklmnopqrstuvwxyz"),
   977  			Slr: []string{"0 abcdefghihklmnopqrstuvwxyz",
   978  				"1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   979  				"2 abcdefghihklmnopqrstuvwxyzA",
   980  				"3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   981  				"4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   982  				"5 abcdefghihklmnopqrstuvwxyzA",
   983  				"6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"},
   984  			Mr:  nil,
   985  			Str: nil,
   986  		},
   987  	}
   988  
   989  	got, err := MarshalIndent(&o, "", " ", WithEncOptsTruncate(2))
   990  	if err != nil {
   991  		t.Fatal(err)
   992  	}
   993  	if got := string(got); got != truncateExpected {
   994  		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
   995  	}
   996  }