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