xref: /aosp_15_r20/external/golang-protobuf/internal/encoding/text/encode_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage text_test
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"math"
9*1c12ee1eSDan Willemsen	"strings"
10*1c12ee1eSDan Willemsen	"testing"
11*1c12ee1eSDan Willemsen	"unicode/utf8"
12*1c12ee1eSDan Willemsen
13*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp"
14*1c12ee1eSDan Willemsen
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/detrand"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/text"
17*1c12ee1eSDan Willemsen)
18*1c12ee1eSDan Willemsen
19*1c12ee1eSDan Willemsen// Disable detrand to enable direct comparisons on outputs.
20*1c12ee1eSDan Willemsenfunc init() { detrand.Disable() }
21*1c12ee1eSDan Willemsen
22*1c12ee1eSDan Willemsenfunc TestEncoder(t *testing.T) {
23*1c12ee1eSDan Willemsen	tests := []encoderTestCase{
24*1c12ee1eSDan Willemsen		{
25*1c12ee1eSDan Willemsen			desc:          "no-opt",
26*1c12ee1eSDan Willemsen			write:         func(e *text.Encoder) {},
27*1c12ee1eSDan Willemsen			wantOut:       ``,
28*1c12ee1eSDan Willemsen			wantOutIndent: ``,
29*1c12ee1eSDan Willemsen		},
30*1c12ee1eSDan Willemsen		{
31*1c12ee1eSDan Willemsen			desc: "true",
32*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
33*1c12ee1eSDan Willemsen				e.WriteName("bool")
34*1c12ee1eSDan Willemsen				e.WriteBool(true)
35*1c12ee1eSDan Willemsen			},
36*1c12ee1eSDan Willemsen			wantOut:       `bool:true`,
37*1c12ee1eSDan Willemsen			wantOutIndent: `bool: true`,
38*1c12ee1eSDan Willemsen		},
39*1c12ee1eSDan Willemsen		{
40*1c12ee1eSDan Willemsen			desc: "false",
41*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
42*1c12ee1eSDan Willemsen				e.WriteName("bool")
43*1c12ee1eSDan Willemsen				e.WriteBool(false)
44*1c12ee1eSDan Willemsen			},
45*1c12ee1eSDan Willemsen			wantOut:       `bool:false`,
46*1c12ee1eSDan Willemsen			wantOutIndent: `bool: false`,
47*1c12ee1eSDan Willemsen		},
48*1c12ee1eSDan Willemsen		{
49*1c12ee1eSDan Willemsen			desc: "bracket name",
50*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
51*1c12ee1eSDan Willemsen				e.WriteName("[extension]")
52*1c12ee1eSDan Willemsen				e.WriteString("hello")
53*1c12ee1eSDan Willemsen			},
54*1c12ee1eSDan Willemsen			wantOut:       `[extension]:"hello"`,
55*1c12ee1eSDan Willemsen			wantOutIndent: `[extension]: "hello"`,
56*1c12ee1eSDan Willemsen		},
57*1c12ee1eSDan Willemsen		{
58*1c12ee1eSDan Willemsen			desc: "numeric name",
59*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
60*1c12ee1eSDan Willemsen				e.WriteName("01234")
61*1c12ee1eSDan Willemsen				e.WriteString("hello")
62*1c12ee1eSDan Willemsen			},
63*1c12ee1eSDan Willemsen			wantOut:       `01234:"hello"`,
64*1c12ee1eSDan Willemsen			wantOutIndent: `01234: "hello"`,
65*1c12ee1eSDan Willemsen		},
66*1c12ee1eSDan Willemsen		{
67*1c12ee1eSDan Willemsen			desc: "string",
68*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
69*1c12ee1eSDan Willemsen				e.WriteName("str")
70*1c12ee1eSDan Willemsen				e.WriteString("hello world")
71*1c12ee1eSDan Willemsen			},
72*1c12ee1eSDan Willemsen			wantOut:       `str:"hello world"`,
73*1c12ee1eSDan Willemsen			wantOutIndent: `str: "hello world"`,
74*1c12ee1eSDan Willemsen		},
75*1c12ee1eSDan Willemsen		{
76*1c12ee1eSDan Willemsen			desc: "enum",
77*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
78*1c12ee1eSDan Willemsen				e.WriteName("enum")
79*1c12ee1eSDan Willemsen				e.WriteLiteral("ENUM_VALUE")
80*1c12ee1eSDan Willemsen			},
81*1c12ee1eSDan Willemsen			wantOut:       `enum:ENUM_VALUE`,
82*1c12ee1eSDan Willemsen			wantOutIndent: `enum: ENUM_VALUE`,
83*1c12ee1eSDan Willemsen		},
84*1c12ee1eSDan Willemsen		{
85*1c12ee1eSDan Willemsen			desc: "float64",
86*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
87*1c12ee1eSDan Willemsen				e.WriteName("float64")
88*1c12ee1eSDan Willemsen				e.WriteFloat(1.0199999809265137, 64)
89*1c12ee1eSDan Willemsen			},
90*1c12ee1eSDan Willemsen			wantOut:       `float64:1.0199999809265137`,
91*1c12ee1eSDan Willemsen			wantOutIndent: `float64: 1.0199999809265137`,
92*1c12ee1eSDan Willemsen		},
93*1c12ee1eSDan Willemsen		{
94*1c12ee1eSDan Willemsen			desc: "float64 max value",
95*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
96*1c12ee1eSDan Willemsen				e.WriteName("float64")
97*1c12ee1eSDan Willemsen				e.WriteFloat(math.MaxFloat64, 64)
98*1c12ee1eSDan Willemsen			},
99*1c12ee1eSDan Willemsen			wantOut:       `float64:1.7976931348623157e+308`,
100*1c12ee1eSDan Willemsen			wantOutIndent: `float64: 1.7976931348623157e+308`,
101*1c12ee1eSDan Willemsen		},
102*1c12ee1eSDan Willemsen		{
103*1c12ee1eSDan Willemsen			desc: "float64 min value",
104*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
105*1c12ee1eSDan Willemsen				e.WriteName("float64")
106*1c12ee1eSDan Willemsen				e.WriteFloat(-math.MaxFloat64, 64)
107*1c12ee1eSDan Willemsen			},
108*1c12ee1eSDan Willemsen			wantOut:       `float64:-1.7976931348623157e+308`,
109*1c12ee1eSDan Willemsen			wantOutIndent: `float64: -1.7976931348623157e+308`,
110*1c12ee1eSDan Willemsen		},
111*1c12ee1eSDan Willemsen		{
112*1c12ee1eSDan Willemsen			desc: "float64 nan",
113*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
114*1c12ee1eSDan Willemsen				e.WriteName("float64")
115*1c12ee1eSDan Willemsen				e.WriteFloat(math.NaN(), 64)
116*1c12ee1eSDan Willemsen			},
117*1c12ee1eSDan Willemsen			wantOut:       `float64:nan`,
118*1c12ee1eSDan Willemsen			wantOutIndent: `float64: nan`,
119*1c12ee1eSDan Willemsen		},
120*1c12ee1eSDan Willemsen		{
121*1c12ee1eSDan Willemsen			desc: "float64 inf",
122*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
123*1c12ee1eSDan Willemsen				e.WriteName("float64")
124*1c12ee1eSDan Willemsen				e.WriteFloat(math.Inf(+1), 64)
125*1c12ee1eSDan Willemsen			},
126*1c12ee1eSDan Willemsen			wantOut:       `float64:inf`,
127*1c12ee1eSDan Willemsen			wantOutIndent: `float64: inf`,
128*1c12ee1eSDan Willemsen		},
129*1c12ee1eSDan Willemsen		{
130*1c12ee1eSDan Willemsen			desc: "float64 -inf",
131*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
132*1c12ee1eSDan Willemsen				e.WriteName("float64")
133*1c12ee1eSDan Willemsen				e.WriteFloat(math.Inf(-1), 64)
134*1c12ee1eSDan Willemsen			},
135*1c12ee1eSDan Willemsen			wantOut:       `float64:-inf`,
136*1c12ee1eSDan Willemsen			wantOutIndent: `float64: -inf`,
137*1c12ee1eSDan Willemsen		},
138*1c12ee1eSDan Willemsen		{
139*1c12ee1eSDan Willemsen			desc: "float64 negative zero",
140*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
141*1c12ee1eSDan Willemsen				e.WriteName("float64")
142*1c12ee1eSDan Willemsen				e.WriteFloat(math.Copysign(0, -1), 64)
143*1c12ee1eSDan Willemsen			},
144*1c12ee1eSDan Willemsen			wantOut:       `float64:-0`,
145*1c12ee1eSDan Willemsen			wantOutIndent: `float64: -0`,
146*1c12ee1eSDan Willemsen		},
147*1c12ee1eSDan Willemsen		{
148*1c12ee1eSDan Willemsen			desc: "float32",
149*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
150*1c12ee1eSDan Willemsen				e.WriteName("float")
151*1c12ee1eSDan Willemsen				e.WriteFloat(1.02, 32)
152*1c12ee1eSDan Willemsen			},
153*1c12ee1eSDan Willemsen			wantOut:       `float:1.02`,
154*1c12ee1eSDan Willemsen			wantOutIndent: `float: 1.02`,
155*1c12ee1eSDan Willemsen		},
156*1c12ee1eSDan Willemsen		{
157*1c12ee1eSDan Willemsen			desc: "float32 max value",
158*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
159*1c12ee1eSDan Willemsen				e.WriteName("float32")
160*1c12ee1eSDan Willemsen				e.WriteFloat(math.MaxFloat32, 32)
161*1c12ee1eSDan Willemsen			},
162*1c12ee1eSDan Willemsen			wantOut:       `float32:3.4028235e+38`,
163*1c12ee1eSDan Willemsen			wantOutIndent: `float32: 3.4028235e+38`,
164*1c12ee1eSDan Willemsen		},
165*1c12ee1eSDan Willemsen		{
166*1c12ee1eSDan Willemsen			desc: "float32 nan",
167*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
168*1c12ee1eSDan Willemsen				e.WriteName("float32")
169*1c12ee1eSDan Willemsen				e.WriteFloat(math.NaN(), 32)
170*1c12ee1eSDan Willemsen			},
171*1c12ee1eSDan Willemsen			wantOut:       `float32:nan`,
172*1c12ee1eSDan Willemsen			wantOutIndent: `float32: nan`,
173*1c12ee1eSDan Willemsen		},
174*1c12ee1eSDan Willemsen		{
175*1c12ee1eSDan Willemsen			desc: "float32 inf",
176*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
177*1c12ee1eSDan Willemsen				e.WriteName("float32")
178*1c12ee1eSDan Willemsen				e.WriteFloat(math.Inf(+1), 32)
179*1c12ee1eSDan Willemsen			},
180*1c12ee1eSDan Willemsen			wantOut:       `float32:inf`,
181*1c12ee1eSDan Willemsen			wantOutIndent: `float32: inf`,
182*1c12ee1eSDan Willemsen		},
183*1c12ee1eSDan Willemsen		{
184*1c12ee1eSDan Willemsen			desc: "float32 -inf",
185*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
186*1c12ee1eSDan Willemsen				e.WriteName("float32")
187*1c12ee1eSDan Willemsen				e.WriteFloat(math.Inf(-1), 32)
188*1c12ee1eSDan Willemsen			},
189*1c12ee1eSDan Willemsen			wantOut:       `float32:-inf`,
190*1c12ee1eSDan Willemsen			wantOutIndent: `float32: -inf`,
191*1c12ee1eSDan Willemsen		},
192*1c12ee1eSDan Willemsen		{
193*1c12ee1eSDan Willemsen			desc: "float32 negative zero",
194*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
195*1c12ee1eSDan Willemsen				e.WriteName("float32")
196*1c12ee1eSDan Willemsen				e.WriteFloat(math.Copysign(0, -1), 32)
197*1c12ee1eSDan Willemsen			},
198*1c12ee1eSDan Willemsen			wantOut:       `float32:-0`,
199*1c12ee1eSDan Willemsen			wantOutIndent: `float32: -0`,
200*1c12ee1eSDan Willemsen		},
201*1c12ee1eSDan Willemsen		{
202*1c12ee1eSDan Willemsen			desc: "int64 max value",
203*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
204*1c12ee1eSDan Willemsen				e.WriteName("int")
205*1c12ee1eSDan Willemsen				e.WriteInt(math.MaxInt64)
206*1c12ee1eSDan Willemsen			},
207*1c12ee1eSDan Willemsen			wantOut:       `int:9223372036854775807`,
208*1c12ee1eSDan Willemsen			wantOutIndent: `int: 9223372036854775807`,
209*1c12ee1eSDan Willemsen		},
210*1c12ee1eSDan Willemsen		{
211*1c12ee1eSDan Willemsen			desc: "int64 min value",
212*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
213*1c12ee1eSDan Willemsen				e.WriteName("int")
214*1c12ee1eSDan Willemsen				e.WriteInt(math.MinInt64)
215*1c12ee1eSDan Willemsen			},
216*1c12ee1eSDan Willemsen			wantOut:       `int:-9223372036854775808`,
217*1c12ee1eSDan Willemsen			wantOutIndent: `int: -9223372036854775808`,
218*1c12ee1eSDan Willemsen		},
219*1c12ee1eSDan Willemsen		{
220*1c12ee1eSDan Willemsen			desc: "uint",
221*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
222*1c12ee1eSDan Willemsen				e.WriteName("uint")
223*1c12ee1eSDan Willemsen				e.WriteUint(math.MaxUint64)
224*1c12ee1eSDan Willemsen			},
225*1c12ee1eSDan Willemsen			wantOut:       `uint:18446744073709551615`,
226*1c12ee1eSDan Willemsen			wantOutIndent: `uint: 18446744073709551615`,
227*1c12ee1eSDan Willemsen		},
228*1c12ee1eSDan Willemsen		{
229*1c12ee1eSDan Willemsen			desc: "empty message field",
230*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
231*1c12ee1eSDan Willemsen				e.WriteName("m")
232*1c12ee1eSDan Willemsen				e.StartMessage()
233*1c12ee1eSDan Willemsen				e.EndMessage()
234*1c12ee1eSDan Willemsen			},
235*1c12ee1eSDan Willemsen			wantOut:       `m:{}`,
236*1c12ee1eSDan Willemsen			wantOutIndent: `m: {}`,
237*1c12ee1eSDan Willemsen		},
238*1c12ee1eSDan Willemsen		{
239*1c12ee1eSDan Willemsen			desc: "multiple fields",
240*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
241*1c12ee1eSDan Willemsen				e.WriteName("bool")
242*1c12ee1eSDan Willemsen				e.WriteBool(true)
243*1c12ee1eSDan Willemsen				e.WriteName("str")
244*1c12ee1eSDan Willemsen				e.WriteString("hello")
245*1c12ee1eSDan Willemsen				e.WriteName("str")
246*1c12ee1eSDan Willemsen				e.WriteString("world")
247*1c12ee1eSDan Willemsen				e.WriteName("m")
248*1c12ee1eSDan Willemsen				e.StartMessage()
249*1c12ee1eSDan Willemsen				e.EndMessage()
250*1c12ee1eSDan Willemsen				e.WriteName("[int]")
251*1c12ee1eSDan Willemsen				e.WriteInt(49)
252*1c12ee1eSDan Willemsen				e.WriteName("float64")
253*1c12ee1eSDan Willemsen				e.WriteFloat(1.00023e4, 64)
254*1c12ee1eSDan Willemsen				e.WriteName("101")
255*1c12ee1eSDan Willemsen				e.WriteString("unknown")
256*1c12ee1eSDan Willemsen			},
257*1c12ee1eSDan Willemsen			wantOut: `bool:true str:"hello" str:"world" m:{} [int]:49 float64:10002.3 101:"unknown"`,
258*1c12ee1eSDan Willemsen			wantOutIndent: `bool: true
259*1c12ee1eSDan Willemsenstr: "hello"
260*1c12ee1eSDan Willemsenstr: "world"
261*1c12ee1eSDan Willemsenm: {}
262*1c12ee1eSDan Willemsen[int]: 49
263*1c12ee1eSDan Willemsenfloat64: 10002.3
264*1c12ee1eSDan Willemsen101: "unknown"`,
265*1c12ee1eSDan Willemsen		},
266*1c12ee1eSDan Willemsen		{
267*1c12ee1eSDan Willemsen			desc: "populated message fields",
268*1c12ee1eSDan Willemsen			write: func(e *text.Encoder) {
269*1c12ee1eSDan Willemsen				e.WriteName("m1")
270*1c12ee1eSDan Willemsen				e.StartMessage()
271*1c12ee1eSDan Willemsen				{
272*1c12ee1eSDan Willemsen					e.WriteName("str")
273*1c12ee1eSDan Willemsen					e.WriteString("hello")
274*1c12ee1eSDan Willemsen				}
275*1c12ee1eSDan Willemsen				e.EndMessage()
276*1c12ee1eSDan Willemsen
277*1c12ee1eSDan Willemsen				e.WriteName("bool")
278*1c12ee1eSDan Willemsen				e.WriteBool(true)
279*1c12ee1eSDan Willemsen
280*1c12ee1eSDan Willemsen				e.WriteName("m2")
281*1c12ee1eSDan Willemsen				e.StartMessage()
282*1c12ee1eSDan Willemsen				{
283*1c12ee1eSDan Willemsen					e.WriteName("str")
284*1c12ee1eSDan Willemsen					e.WriteString("world")
285*1c12ee1eSDan Willemsen					e.WriteName("m2-1")
286*1c12ee1eSDan Willemsen					e.StartMessage()
287*1c12ee1eSDan Willemsen					e.EndMessage()
288*1c12ee1eSDan Willemsen					e.WriteName("m2-2")
289*1c12ee1eSDan Willemsen					e.StartMessage()
290*1c12ee1eSDan Willemsen					{
291*1c12ee1eSDan Willemsen						e.WriteName("[int]")
292*1c12ee1eSDan Willemsen						e.WriteInt(49)
293*1c12ee1eSDan Willemsen					}
294*1c12ee1eSDan Willemsen					e.EndMessage()
295*1c12ee1eSDan Willemsen					e.WriteName("float64")
296*1c12ee1eSDan Willemsen					e.WriteFloat(1.00023e4, 64)
297*1c12ee1eSDan Willemsen				}
298*1c12ee1eSDan Willemsen				e.EndMessage()
299*1c12ee1eSDan Willemsen
300*1c12ee1eSDan Willemsen				e.WriteName("101")
301*1c12ee1eSDan Willemsen				e.WriteString("unknown")
302*1c12ee1eSDan Willemsen			},
303*1c12ee1eSDan Willemsen			wantOut: `m1:{str:"hello"} bool:true m2:{str:"world" m2-1:{} m2-2:{[int]:49} float64:10002.3} 101:"unknown"`,
304*1c12ee1eSDan Willemsen			wantOutIndent: `m1: {
305*1c12ee1eSDan Willemsen	str: "hello"
306*1c12ee1eSDan Willemsen}
307*1c12ee1eSDan Willemsenbool: true
308*1c12ee1eSDan Willemsenm2: {
309*1c12ee1eSDan Willemsen	str: "world"
310*1c12ee1eSDan Willemsen	m2-1: {}
311*1c12ee1eSDan Willemsen	m2-2: {
312*1c12ee1eSDan Willemsen		[int]: 49
313*1c12ee1eSDan Willemsen	}
314*1c12ee1eSDan Willemsen	float64: 10002.3
315*1c12ee1eSDan Willemsen}
316*1c12ee1eSDan Willemsen101: "unknown"`,
317*1c12ee1eSDan Willemsen		},
318*1c12ee1eSDan Willemsen	}
319*1c12ee1eSDan Willemsen
320*1c12ee1eSDan Willemsen	for _, tc := range tests {
321*1c12ee1eSDan Willemsen		t.Run(tc.desc, func(t *testing.T) {
322*1c12ee1eSDan Willemsen			runEncoderTest(t, tc, [2]byte{})
323*1c12ee1eSDan Willemsen
324*1c12ee1eSDan Willemsen			// Test using the angle brackets.
325*1c12ee1eSDan Willemsen			// Testcases should not contain characters '{' and '}'.
326*1c12ee1eSDan Willemsen			tc.wantOut = replaceDelims(tc.wantOut)
327*1c12ee1eSDan Willemsen			tc.wantOutIndent = replaceDelims(tc.wantOutIndent)
328*1c12ee1eSDan Willemsen			runEncoderTest(t, tc, [2]byte{'<', '>'})
329*1c12ee1eSDan Willemsen		})
330*1c12ee1eSDan Willemsen	}
331*1c12ee1eSDan Willemsen}
332*1c12ee1eSDan Willemsen
333*1c12ee1eSDan Willemsentype encoderTestCase struct {
334*1c12ee1eSDan Willemsen	desc          string
335*1c12ee1eSDan Willemsen	write         func(*text.Encoder)
336*1c12ee1eSDan Willemsen	wantOut       string
337*1c12ee1eSDan Willemsen	wantOutIndent string
338*1c12ee1eSDan Willemsen}
339*1c12ee1eSDan Willemsen
340*1c12ee1eSDan Willemsenfunc runEncoderTest(t *testing.T, tc encoderTestCase, delims [2]byte) {
341*1c12ee1eSDan Willemsen	t.Helper()
342*1c12ee1eSDan Willemsen
343*1c12ee1eSDan Willemsen	if tc.wantOut != "" {
344*1c12ee1eSDan Willemsen		enc, err := text.NewEncoder("", delims, false)
345*1c12ee1eSDan Willemsen		if err != nil {
346*1c12ee1eSDan Willemsen			t.Fatalf("NewEncoder returned error: %v", err)
347*1c12ee1eSDan Willemsen		}
348*1c12ee1eSDan Willemsen		tc.write(enc)
349*1c12ee1eSDan Willemsen		got := string(enc.Bytes())
350*1c12ee1eSDan Willemsen		if got != tc.wantOut {
351*1c12ee1eSDan Willemsen			t.Errorf("(compact)\n<got>\n%v\n<want>\n%v\n", got, tc.wantOut)
352*1c12ee1eSDan Willemsen		}
353*1c12ee1eSDan Willemsen	}
354*1c12ee1eSDan Willemsen	if tc.wantOutIndent != "" {
355*1c12ee1eSDan Willemsen		enc, err := text.NewEncoder("\t", delims, false)
356*1c12ee1eSDan Willemsen		if err != nil {
357*1c12ee1eSDan Willemsen			t.Fatalf("NewEncoder returned error: %v", err)
358*1c12ee1eSDan Willemsen		}
359*1c12ee1eSDan Willemsen		tc.write(enc)
360*1c12ee1eSDan Willemsen		got, want := string(enc.Bytes()), tc.wantOutIndent
361*1c12ee1eSDan Willemsen		if got != want {
362*1c12ee1eSDan Willemsen			t.Errorf("(multi-line)\n<got>\n%v\n<want>\n%v\n<diff -want +got>\n%v\n",
363*1c12ee1eSDan Willemsen				got, want, cmp.Diff(want, got))
364*1c12ee1eSDan Willemsen		}
365*1c12ee1eSDan Willemsen	}
366*1c12ee1eSDan Willemsen}
367*1c12ee1eSDan Willemsen
368*1c12ee1eSDan Willemsenfunc replaceDelims(s string) string {
369*1c12ee1eSDan Willemsen	s = strings.Replace(s, "{", "<", -1)
370*1c12ee1eSDan Willemsen	return strings.Replace(s, "}", ">", -1)
371*1c12ee1eSDan Willemsen}
372*1c12ee1eSDan Willemsen
373*1c12ee1eSDan Willemsen// Test for UTF-8 and ASCII outputs.
374*1c12ee1eSDan Willemsenfunc TestEncodeStrings(t *testing.T) {
375*1c12ee1eSDan Willemsen	tests := []struct {
376*1c12ee1eSDan Willemsen		in           string
377*1c12ee1eSDan Willemsen		wantOut      string
378*1c12ee1eSDan Willemsen		wantOutASCII string
379*1c12ee1eSDan Willemsen	}{
380*1c12ee1eSDan Willemsen		{
381*1c12ee1eSDan Willemsen			in:      `"`,
382*1c12ee1eSDan Willemsen			wantOut: `"\""`,
383*1c12ee1eSDan Willemsen		},
384*1c12ee1eSDan Willemsen		{
385*1c12ee1eSDan Willemsen			in:      `'`,
386*1c12ee1eSDan Willemsen			wantOut: `"'"`,
387*1c12ee1eSDan Willemsen		},
388*1c12ee1eSDan Willemsen		{
389*1c12ee1eSDan Willemsen			in:           "hello\u1234world",
390*1c12ee1eSDan Willemsen			wantOut:      "\"hello\u1234world\"",
391*1c12ee1eSDan Willemsen			wantOutASCII: `"hello\u1234world"`,
392*1c12ee1eSDan Willemsen		},
393*1c12ee1eSDan Willemsen		{
394*1c12ee1eSDan Willemsen			// String that has as few escaped characters as possible.
395*1c12ee1eSDan Willemsen			in: func() string {
396*1c12ee1eSDan Willemsen				var b []byte
397*1c12ee1eSDan Willemsen				for i := rune(0); i <= 0x00a0; i++ {
398*1c12ee1eSDan Willemsen					switch i {
399*1c12ee1eSDan Willemsen					case 0, '\\', '\n', '\'': // these must be escaped, so ignore them
400*1c12ee1eSDan Willemsen					default:
401*1c12ee1eSDan Willemsen						var r [utf8.UTFMax]byte
402*1c12ee1eSDan Willemsen						n := utf8.EncodeRune(r[:], i)
403*1c12ee1eSDan Willemsen						b = append(b, r[:n]...)
404*1c12ee1eSDan Willemsen					}
405*1c12ee1eSDan Willemsen				}
406*1c12ee1eSDan Willemsen				return string(b)
407*1c12ee1eSDan Willemsen			}(),
408*1c12ee1eSDan Willemsen			wantOut:      `"\x01\x02\x03\x04\x05\x06\x07\x08\t\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_` + "`" + `abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f` + "\u00a0" + `"`,
409*1c12ee1eSDan Willemsen			wantOutASCII: `"\x01\x02\x03\x04\x05\x06\x07\x08\t\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_` + "`" + `abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f\u00a0"`,
410*1c12ee1eSDan Willemsen		},
411*1c12ee1eSDan Willemsen		{
412*1c12ee1eSDan Willemsen			// Valid UTF-8 wire encoding of the RuneError rune.
413*1c12ee1eSDan Willemsen			in:           string(utf8.RuneError),
414*1c12ee1eSDan Willemsen			wantOut:      `"` + string(utf8.RuneError) + `"`,
415*1c12ee1eSDan Willemsen			wantOutASCII: `"\ufffd"`,
416*1c12ee1eSDan Willemsen		},
417*1c12ee1eSDan Willemsen		{
418*1c12ee1eSDan Willemsen			in:           "\"'\\?\a\b\n\r\t\v\f\x01\nS\n\xab\x12\uab8f\U0010ffff",
419*1c12ee1eSDan Willemsen			wantOut:      `"\"'\\?\x07\x08\n\r\t\x0b\x0c\x01\nS\n\xab\x12` + "\uab8f\U0010ffff" + `"`,
420*1c12ee1eSDan Willemsen			wantOutASCII: `"\"'\\?\x07\x08\n\r\t\x0b\x0c\x01\nS\n\xab\x12\uab8f\U0010ffff"`,
421*1c12ee1eSDan Willemsen		},
422*1c12ee1eSDan Willemsen		{
423*1c12ee1eSDan Willemsen			in:           "\001x",
424*1c12ee1eSDan Willemsen			wantOut:      `"\x01x"`,
425*1c12ee1eSDan Willemsen			wantOutASCII: `"\x01x"`,
426*1c12ee1eSDan Willemsen		},
427*1c12ee1eSDan Willemsen		{
428*1c12ee1eSDan Willemsen			in:           "\012x",
429*1c12ee1eSDan Willemsen			wantOut:      `"\nx"`,
430*1c12ee1eSDan Willemsen			wantOutASCII: `"\nx"`,
431*1c12ee1eSDan Willemsen		},
432*1c12ee1eSDan Willemsen		{
433*1c12ee1eSDan Willemsen			in:           "\123x",
434*1c12ee1eSDan Willemsen			wantOut:      `"Sx"`,
435*1c12ee1eSDan Willemsen			wantOutASCII: `"Sx"`,
436*1c12ee1eSDan Willemsen		},
437*1c12ee1eSDan Willemsen		{
438*1c12ee1eSDan Willemsen			in:           "\1234x",
439*1c12ee1eSDan Willemsen			wantOut:      `"S4x"`,
440*1c12ee1eSDan Willemsen			wantOutASCII: `"S4x"`,
441*1c12ee1eSDan Willemsen		},
442*1c12ee1eSDan Willemsen		{
443*1c12ee1eSDan Willemsen			in:           "\001",
444*1c12ee1eSDan Willemsen			wantOut:      `"\x01"`,
445*1c12ee1eSDan Willemsen			wantOutASCII: `"\x01"`,
446*1c12ee1eSDan Willemsen		},
447*1c12ee1eSDan Willemsen		{
448*1c12ee1eSDan Willemsen			in:           "\012",
449*1c12ee1eSDan Willemsen			wantOut:      `"\n"`,
450*1c12ee1eSDan Willemsen			wantOutASCII: `"\n"`,
451*1c12ee1eSDan Willemsen		},
452*1c12ee1eSDan Willemsen		{
453*1c12ee1eSDan Willemsen			in:           "\123",
454*1c12ee1eSDan Willemsen			wantOut:      `"S"`,
455*1c12ee1eSDan Willemsen			wantOutASCII: `"S"`,
456*1c12ee1eSDan Willemsen		},
457*1c12ee1eSDan Willemsen		{
458*1c12ee1eSDan Willemsen			in:           "\1234",
459*1c12ee1eSDan Willemsen			wantOut:      `"S4"`,
460*1c12ee1eSDan Willemsen			wantOutASCII: `"S4"`,
461*1c12ee1eSDan Willemsen		},
462*1c12ee1eSDan Willemsen		{
463*1c12ee1eSDan Willemsen			in:           "\377",
464*1c12ee1eSDan Willemsen			wantOut:      `"\xff"`,
465*1c12ee1eSDan Willemsen			wantOutASCII: `"\xff"`,
466*1c12ee1eSDan Willemsen		},
467*1c12ee1eSDan Willemsen		{
468*1c12ee1eSDan Willemsen			in:           "\x0fx",
469*1c12ee1eSDan Willemsen			wantOut:      `"\x0fx"`,
470*1c12ee1eSDan Willemsen			wantOutASCII: `"\x0fx"`,
471*1c12ee1eSDan Willemsen		},
472*1c12ee1eSDan Willemsen		{
473*1c12ee1eSDan Willemsen			in:           "\xffx",
474*1c12ee1eSDan Willemsen			wantOut:      `"\xffx"`,
475*1c12ee1eSDan Willemsen			wantOutASCII: `"\xffx"`,
476*1c12ee1eSDan Willemsen		},
477*1c12ee1eSDan Willemsen		{
478*1c12ee1eSDan Willemsen			in:           "\xfffx",
479*1c12ee1eSDan Willemsen			wantOut:      `"\xfffx"`,
480*1c12ee1eSDan Willemsen			wantOutASCII: `"\xfffx"`,
481*1c12ee1eSDan Willemsen		},
482*1c12ee1eSDan Willemsen		{
483*1c12ee1eSDan Willemsen			in:           "\x0f",
484*1c12ee1eSDan Willemsen			wantOut:      `"\x0f"`,
485*1c12ee1eSDan Willemsen			wantOutASCII: `"\x0f"`,
486*1c12ee1eSDan Willemsen		},
487*1c12ee1eSDan Willemsen		{
488*1c12ee1eSDan Willemsen			in:           "\x7f",
489*1c12ee1eSDan Willemsen			wantOut:      `"\x7f"`,
490*1c12ee1eSDan Willemsen			wantOutASCII: `"\x7f"`,
491*1c12ee1eSDan Willemsen		},
492*1c12ee1eSDan Willemsen		{
493*1c12ee1eSDan Willemsen			in:           "\xff",
494*1c12ee1eSDan Willemsen			wantOut:      `"\xff"`,
495*1c12ee1eSDan Willemsen			wantOutASCII: `"\xff"`,
496*1c12ee1eSDan Willemsen		},
497*1c12ee1eSDan Willemsen		{
498*1c12ee1eSDan Willemsen			in:           "\xfff",
499*1c12ee1eSDan Willemsen			wantOut:      `"\xfff"`,
500*1c12ee1eSDan Willemsen			wantOutASCII: `"\xfff"`,
501*1c12ee1eSDan Willemsen		},
502*1c12ee1eSDan Willemsen	}
503*1c12ee1eSDan Willemsen	for _, tc := range tests {
504*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
505*1c12ee1eSDan Willemsen			if tc.wantOut != "" {
506*1c12ee1eSDan Willemsen				runEncodeStringsTest(t, tc.in, tc.wantOut, false)
507*1c12ee1eSDan Willemsen			}
508*1c12ee1eSDan Willemsen			if tc.wantOutASCII != "" {
509*1c12ee1eSDan Willemsen				runEncodeStringsTest(t, tc.in, tc.wantOutASCII, true)
510*1c12ee1eSDan Willemsen			}
511*1c12ee1eSDan Willemsen		})
512*1c12ee1eSDan Willemsen	}
513*1c12ee1eSDan Willemsen}
514*1c12ee1eSDan Willemsen
515*1c12ee1eSDan Willemsenfunc runEncodeStringsTest(t *testing.T, in string, want string, outputASCII bool) {
516*1c12ee1eSDan Willemsen	t.Helper()
517*1c12ee1eSDan Willemsen
518*1c12ee1eSDan Willemsen	charType := "UTF-8"
519*1c12ee1eSDan Willemsen	if outputASCII {
520*1c12ee1eSDan Willemsen		charType = "ASCII"
521*1c12ee1eSDan Willemsen	}
522*1c12ee1eSDan Willemsen
523*1c12ee1eSDan Willemsen	enc, err := text.NewEncoder("", [2]byte{}, outputASCII)
524*1c12ee1eSDan Willemsen	if err != nil {
525*1c12ee1eSDan Willemsen		t.Fatalf("[%s] NewEncoder returned error: %v", charType, err)
526*1c12ee1eSDan Willemsen	}
527*1c12ee1eSDan Willemsen	enc.WriteString(in)
528*1c12ee1eSDan Willemsen	got := string(enc.Bytes())
529*1c12ee1eSDan Willemsen	if got != want {
530*1c12ee1eSDan Willemsen		t.Errorf("[%s] WriteString(%q)\n<got>\n%v\n<want>\n%v\n", charType, in, got, want)
531*1c12ee1eSDan Willemsen	}
532*1c12ee1eSDan Willemsen}
533*1c12ee1eSDan Willemsen
534*1c12ee1eSDan Willemsenfunc TestReset(t *testing.T) {
535*1c12ee1eSDan Willemsen	enc, err := text.NewEncoder("\t", [2]byte{}, false)
536*1c12ee1eSDan Willemsen	if err != nil {
537*1c12ee1eSDan Willemsen		t.Fatalf("NewEncoder returned error: %v", err)
538*1c12ee1eSDan Willemsen	}
539*1c12ee1eSDan Willemsen
540*1c12ee1eSDan Willemsen	enc.WriteName("foo")
541*1c12ee1eSDan Willemsen	pos := enc.Snapshot()
542*1c12ee1eSDan Willemsen
543*1c12ee1eSDan Willemsen	// Attempt to write a message value.
544*1c12ee1eSDan Willemsen	enc.StartMessage()
545*1c12ee1eSDan Willemsen	enc.WriteName("bar")
546*1c12ee1eSDan Willemsen	enc.WriteUint(10)
547*1c12ee1eSDan Willemsen
548*1c12ee1eSDan Willemsen	// Reset the value and decided to write a string value instead.
549*1c12ee1eSDan Willemsen	enc.Reset(pos)
550*1c12ee1eSDan Willemsen	enc.WriteString("0123456789")
551*1c12ee1eSDan Willemsen
552*1c12ee1eSDan Willemsen	got := string(enc.Bytes())
553*1c12ee1eSDan Willemsen	want := `foo: "0123456789"`
554*1c12ee1eSDan Willemsen	if got != want {
555*1c12ee1eSDan Willemsen		t.Errorf("Reset did not restore given position:\n<got>\n%v\n<want>\n%v\n", got, want)
556*1c12ee1eSDan Willemsen	}
557*1c12ee1eSDan Willemsen}
558