1// Copyright 2009 The Go Authors. 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 5package fmt_test 6 7import ( 8 "bufio" 9 "bytes" 10 "errors" 11 . "fmt" 12 "io" 13 "math" 14 "reflect" 15 "regexp" 16 "strings" 17 "testing" 18 "testing/iotest" 19 "unicode/utf8" 20) 21 22type ScanTest struct { 23 text string 24 in any 25 out any 26} 27 28type ScanfTest struct { 29 format string 30 text string 31 in any 32 out any 33} 34 35type ScanfMultiTest struct { 36 format string 37 text string 38 in []any 39 out []any 40 err string 41} 42 43var ( 44 boolVal bool 45 intVal int 46 int8Val int8 47 int16Val int16 48 int32Val int32 49 int64Val int64 50 uintVal uint 51 uint8Val uint8 52 uint16Val uint16 53 uint32Val uint32 54 uint64Val uint64 55 uintptrVal uintptr 56 float32Val float32 57 float64Val float64 58 stringVal string 59 bytesVal []byte 60 runeVal rune 61 complex64Val complex64 62 complex128Val complex128 63 renamedBoolVal renamedBool 64 renamedIntVal renamedInt 65 renamedInt8Val renamedInt8 66 renamedInt16Val renamedInt16 67 renamedInt32Val renamedInt32 68 renamedInt64Val renamedInt64 69 renamedUintVal renamedUint 70 renamedUint8Val renamedUint8 71 renamedUint16Val renamedUint16 72 renamedUint32Val renamedUint32 73 renamedUint64Val renamedUint64 74 renamedUintptrVal renamedUintptr 75 renamedStringVal renamedString 76 renamedBytesVal renamedBytes 77 renamedFloat32Val renamedFloat32 78 renamedFloat64Val renamedFloat64 79 renamedComplex64Val renamedComplex64 80 renamedComplex128Val renamedComplex128 81) 82 83// Xs accepts any non-empty run of the verb character 84type Xs string 85 86func (x *Xs) Scan(state ScanState, verb rune) error { 87 tok, err := state.Token(true, func(r rune) bool { return r == verb }) 88 if err != nil { 89 return err 90 } 91 s := string(tok) 92 if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) { 93 return errors.New("syntax error for xs") 94 } 95 *x = Xs(s) 96 return nil 97} 98 99var xVal Xs 100 101// IntString accepts an integer followed immediately by a string. 102// It tests the embedding of a scan within a scan. 103type IntString struct { 104 i int 105 s string 106} 107 108func (s *IntString) Scan(state ScanState, verb rune) error { 109 if _, err := Fscan(state, &s.i); err != nil { 110 return err 111 } 112 113 tok, err := state.Token(true, nil) 114 if err != nil { 115 return err 116 } 117 s.s = string(tok) 118 return nil 119} 120 121var intStringVal IntString 122 123var scanTests = []ScanTest{ 124 // Basic types 125 {"T\n", &boolVal, true}, // boolean test vals toggle to be sure they are written 126 {"F\n", &boolVal, false}, // restored to zero value 127 {"21\n", &intVal, 21}, 128 {"2_1\n", &intVal, 21}, 129 {"0\n", &intVal, 0}, 130 {"000\n", &intVal, 0}, 131 {"0x10\n", &intVal, 0x10}, 132 {"0x_1_0\n", &intVal, 0x10}, 133 {"-0x10\n", &intVal, -0x10}, 134 {"0377\n", &intVal, 0377}, 135 {"0_3_7_7\n", &intVal, 0377}, 136 {"0o377\n", &intVal, 0377}, 137 {"0o_3_7_7\n", &intVal, 0377}, 138 {"-0377\n", &intVal, -0377}, 139 {"-0o377\n", &intVal, -0377}, 140 {"0\n", &uintVal, uint(0)}, 141 {"000\n", &uintVal, uint(0)}, 142 {"0x10\n", &uintVal, uint(0x10)}, 143 {"0377\n", &uintVal, uint(0377)}, 144 {"22\n", &int8Val, int8(22)}, 145 {"23\n", &int16Val, int16(23)}, 146 {"24\n", &int32Val, int32(24)}, 147 {"25\n", &int64Val, int64(25)}, 148 {"127\n", &int8Val, int8(127)}, 149 {"-21\n", &intVal, -21}, 150 {"-22\n", &int8Val, int8(-22)}, 151 {"-23\n", &int16Val, int16(-23)}, 152 {"-24\n", &int32Val, int32(-24)}, 153 {"-25\n", &int64Val, int64(-25)}, 154 {"-128\n", &int8Val, int8(-128)}, 155 {"+21\n", &intVal, +21}, 156 {"+22\n", &int8Val, int8(+22)}, 157 {"+23\n", &int16Val, int16(+23)}, 158 {"+24\n", &int32Val, int32(+24)}, 159 {"+25\n", &int64Val, int64(+25)}, 160 {"+127\n", &int8Val, int8(+127)}, 161 {"26\n", &uintVal, uint(26)}, 162 {"27\n", &uint8Val, uint8(27)}, 163 {"28\n", &uint16Val, uint16(28)}, 164 {"29\n", &uint32Val, uint32(29)}, 165 {"30\n", &uint64Val, uint64(30)}, 166 {"31\n", &uintptrVal, uintptr(31)}, 167 {"255\n", &uint8Val, uint8(255)}, 168 {"32767\n", &int16Val, int16(32767)}, 169 {"2.3\n", &float64Val, 2.3}, 170 {"2.3e1\n", &float32Val, float32(2.3e1)}, 171 {"2.3e2\n", &float64Val, 2.3e2}, 172 {"2.3p2\n", &float64Val, 2.3 * 4}, 173 {"2.3p+2\n", &float64Val, 2.3 * 4}, 174 {"2.3p+66\n", &float64Val, 2.3 * (1 << 66)}, 175 {"2.3p-66\n", &float64Val, 2.3 / (1 << 66)}, 176 {"0x2.3p-66\n", &float64Val, float64(0x23) / (1 << 70)}, 177 {"2_3.4_5\n", &float64Val, 23.45}, 178 {"2.35\n", &stringVal, "2.35"}, 179 {"2345678\n", &bytesVal, []byte("2345678")}, 180 {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i}, 181 {"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)}, 182 {"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)}, 183 {"-.4_5e1-1E2i\n", &complex128Val, complex128(-.45e1 - 100i)}, 184 {"0x1.0p1+0x1.0P2i\n", &complex128Val, complex128(2 + 4i)}, 185 {"-0x1p1-0x1p2i\n", &complex128Val, complex128(-2 - 4i)}, 186 {"-0x1ep-1-0x1p2i\n", &complex128Val, complex128(-15 - 4i)}, 187 {"-0x1_Ep-1-0x1p0_2i\n", &complex128Val, complex128(-15 - 4i)}, 188 {"hello\n", &stringVal, "hello"}, 189 190 // Carriage-return followed by newline. (We treat \r\n as \n always.) 191 {"hello\r\n", &stringVal, "hello"}, 192 {"27\r\n", &uint8Val, uint8(27)}, 193 194 // Renamed types 195 {"true\n", &renamedBoolVal, renamedBool(true)}, 196 {"F\n", &renamedBoolVal, renamedBool(false)}, 197 {"101\n", &renamedIntVal, renamedInt(101)}, 198 {"102\n", &renamedIntVal, renamedInt(102)}, 199 {"103\n", &renamedUintVal, renamedUint(103)}, 200 {"104\n", &renamedUintVal, renamedUint(104)}, 201 {"105\n", &renamedInt8Val, renamedInt8(105)}, 202 {"106\n", &renamedInt16Val, renamedInt16(106)}, 203 {"107\n", &renamedInt32Val, renamedInt32(107)}, 204 {"108\n", &renamedInt64Val, renamedInt64(108)}, 205 {"109\n", &renamedUint8Val, renamedUint8(109)}, 206 {"110\n", &renamedUint16Val, renamedUint16(110)}, 207 {"111\n", &renamedUint32Val, renamedUint32(111)}, 208 {"112\n", &renamedUint64Val, renamedUint64(112)}, 209 {"113\n", &renamedUintptrVal, renamedUintptr(113)}, 210 {"114\n", &renamedStringVal, renamedString("114")}, 211 {"115\n", &renamedBytesVal, renamedBytes([]byte("115"))}, 212 213 // Custom scanners. 214 {" vvv ", &xVal, Xs("vvv")}, 215 {" 1234hello", &intStringVal, IntString{1234, "hello"}}, 216 217 // Fixed bugs 218 {"2147483648\n", &int64Val, int64(2147483648)}, // was: integer overflow 219} 220 221var scanfTests = []ScanfTest{ 222 {"%v", "TRUE\n", &boolVal, true}, 223 {"%t", "false\n", &boolVal, false}, 224 {"%v", "-71\n", &intVal, -71}, 225 {"%v", "-7_1\n", &intVal, -71}, 226 {"%v", "0b111\n", &intVal, 7}, 227 {"%v", "0b_1_1_1\n", &intVal, 7}, 228 {"%v", "0377\n", &intVal, 0377}, 229 {"%v", "0_3_7_7\n", &intVal, 0377}, 230 {"%v", "0o377\n", &intVal, 0377}, 231 {"%v", "0o_3_7_7\n", &intVal, 0377}, 232 {"%v", "0x44\n", &intVal, 0x44}, 233 {"%v", "0x_4_4\n", &intVal, 0x44}, 234 {"%d", "72\n", &intVal, 72}, 235 {"%c", "a\n", &runeVal, 'a'}, 236 {"%c", "\u5072\n", &runeVal, '\u5072'}, 237 {"%c", "\u1234\n", &runeVal, '\u1234'}, 238 {"%d", "73\n", &int8Val, int8(73)}, 239 {"%d", "+74\n", &int16Val, int16(74)}, 240 {"%d", "75\n", &int32Val, int32(75)}, 241 {"%d", "76\n", &int64Val, int64(76)}, 242 {"%b", "1001001\n", &intVal, 73}, 243 {"%o", "075\n", &intVal, 075}, 244 {"%x", "a75\n", &intVal, 0xa75}, 245 {"%v", "71\n", &uintVal, uint(71)}, 246 {"%d", "72\n", &uintVal, uint(72)}, 247 {"%d", "7_2\n", &uintVal, uint(7)}, // only %v takes underscores 248 {"%d", "73\n", &uint8Val, uint8(73)}, 249 {"%d", "74\n", &uint16Val, uint16(74)}, 250 {"%d", "75\n", &uint32Val, uint32(75)}, 251 {"%d", "76\n", &uint64Val, uint64(76)}, 252 {"%d", "77\n", &uintptrVal, uintptr(77)}, 253 {"%b", "1001001\n", &uintVal, uint(73)}, 254 {"%b", "100_1001\n", &uintVal, uint(4)}, 255 {"%o", "075\n", &uintVal, uint(075)}, 256 {"%o", "07_5\n", &uintVal, uint(07)}, // only %v takes underscores 257 {"%x", "a75\n", &uintVal, uint(0xa75)}, 258 {"%x", "A75\n", &uintVal, uint(0xa75)}, 259 {"%x", "A7_5\n", &uintVal, uint(0xa7)}, // only %v takes underscores 260 {"%U", "U+1234\n", &intVal, int(0x1234)}, 261 {"%U", "U+4567\n", &uintVal, uint(0x4567)}, 262 263 {"%e", "2.3\n", &float64Val, 2.3}, 264 {"%E", "2.3e1\n", &float32Val, float32(2.3e1)}, 265 {"%f", "2.3e2\n", &float64Val, 2.3e2}, 266 {"%g", "2.3p2\n", &float64Val, 2.3 * 4}, 267 {"%G", "2.3p+2\n", &float64Val, 2.3 * 4}, 268 {"%v", "2.3p+66\n", &float64Val, 2.3 * (1 << 66)}, 269 {"%f", "2.3p-66\n", &float64Val, 2.3 / (1 << 66)}, 270 {"%G", "0x2.3p-66\n", &float64Val, float64(0x23) / (1 << 70)}, 271 {"%E", "2_3.4_5\n", &float64Val, 23.45}, 272 273 // Strings 274 {"%s", "using-%s\n", &stringVal, "using-%s"}, 275 {"%x", "7573696e672d2578\n", &stringVal, "using-%x"}, 276 {"%X", "7573696E672D2558\n", &stringVal, "using-%X"}, 277 {"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"}, 278 {"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"}, 279 280 // Byte slices 281 {"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")}, 282 {"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")}, 283 {"%X", "62797465732D2558\n", &bytesVal, []byte("bytes-%X")}, 284 {"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")}, 285 {"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")}, 286 287 // Renamed types 288 {"%v\n", "true\n", &renamedBoolVal, renamedBool(true)}, 289 {"%t\n", "F\n", &renamedBoolVal, renamedBool(false)}, 290 {"%v", "101\n", &renamedIntVal, renamedInt(101)}, 291 {"%c", "\u0101\n", &renamedIntVal, renamedInt('\u0101')}, 292 {"%o", "0146\n", &renamedIntVal, renamedInt(102)}, 293 {"%v", "103\n", &renamedUintVal, renamedUint(103)}, 294 {"%d", "104\n", &renamedUintVal, renamedUint(104)}, 295 {"%d", "105\n", &renamedInt8Val, renamedInt8(105)}, 296 {"%d", "106\n", &renamedInt16Val, renamedInt16(106)}, 297 {"%d", "107\n", &renamedInt32Val, renamedInt32(107)}, 298 {"%d", "108\n", &renamedInt64Val, renamedInt64(108)}, 299 {"%x", "6D\n", &renamedUint8Val, renamedUint8(109)}, 300 {"%o", "0156\n", &renamedUint16Val, renamedUint16(110)}, 301 {"%d", "111\n", &renamedUint32Val, renamedUint32(111)}, 302 {"%d", "112\n", &renamedUint64Val, renamedUint64(112)}, 303 {"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)}, 304 {"%s", "114\n", &renamedStringVal, renamedString("114")}, 305 {"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))}, 306 {"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)}, 307 {"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)}, 308 {"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)}, 309 {"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)}, 310 311 // Interesting formats 312 {"here is\tthe value:%d", "here is the\tvalue:118\n", &intVal, 118}, 313 {"%% %%:%d", "% %:119\n", &intVal, 119}, 314 {"%d%%", "42%", &intVal, 42}, // %% at end of string. 315 316 // Corner cases 317 {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)}, 318 319 // Custom scanner. 320 {"%s", " sss ", &xVal, Xs("sss")}, 321 {"%2s", "sssss", &xVal, Xs("ss")}, 322 323 // Fixed bugs 324 {"%d\n", "27\n", &intVal, 27}, // ok 325 {"%d\n", "28 \n", &intVal, 28}, // was: "unexpected newline" 326 {"%v", "0", &intVal, 0}, // was: "EOF"; 0 was taken as base prefix and not counted. 327 {"%v", "0", &uintVal, uint(0)}, // was: "EOF"; 0 was taken as base prefix and not counted. 328 {"%c", " ", &uintVal, uint(' ')}, // %c must accept a blank. 329 {"%c", "\t", &uintVal, uint('\t')}, // %c must accept any space. 330 {"%c", "\n", &uintVal, uint('\n')}, // %c must accept any space. 331 {"%d%%", "23%\n", &uintVal, uint(23)}, // %% matches literal %. 332 {"%%%d", "%23\n", &uintVal, uint(23)}, // %% matches literal %. 333 334 // space handling 335 {"%d", "27", &intVal, 27}, 336 {"%d", "27 ", &intVal, 27}, 337 {"%d", " 27", &intVal, 27}, 338 {"%d", " 27 ", &intVal, 27}, 339 340 {"X%d", "X27", &intVal, 27}, 341 {"X%d", "X27 ", &intVal, 27}, 342 {"X%d", "X 27", &intVal, 27}, 343 {"X%d", "X 27 ", &intVal, 27}, 344 345 {"X %d", "X27", &intVal, nil}, // expected space in input to match format 346 {"X %d", "X27 ", &intVal, nil}, // expected space in input to match format 347 {"X %d", "X 27", &intVal, 27}, 348 {"X %d", "X 27 ", &intVal, 27}, 349 350 {"%dX", "27X", &intVal, 27}, 351 {"%dX", "27 X", &intVal, nil}, // input does not match format 352 {"%dX", " 27X", &intVal, 27}, 353 {"%dX", " 27 X", &intVal, nil}, // input does not match format 354 355 {"%d X", "27X", &intVal, nil}, // expected space in input to match format 356 {"%d X", "27 X", &intVal, 27}, 357 {"%d X", " 27X", &intVal, nil}, // expected space in input to match format 358 {"%d X", " 27 X", &intVal, 27}, 359 360 {"X %d X", "X27X", &intVal, nil}, // expected space in input to match format 361 {"X %d X", "X27 X", &intVal, nil}, // expected space in input to match format 362 {"X %d X", "X 27X", &intVal, nil}, // expected space in input to match format 363 {"X %d X", "X 27 X", &intVal, 27}, 364 365 {"X %s X", "X27X", &stringVal, nil}, // expected space in input to match format 366 {"X %s X", "X27 X", &stringVal, nil}, // expected space in input to match format 367 {"X %s X", "X 27X", &stringVal, nil}, // unexpected EOF 368 {"X %s X", "X 27 X", &stringVal, "27"}, 369 370 {"X%sX", "X27X", &stringVal, nil}, // unexpected EOF 371 {"X%sX", "X27 X", &stringVal, nil}, // input does not match format 372 {"X%sX", "X 27X", &stringVal, nil}, // unexpected EOF 373 {"X%sX", "X 27 X", &stringVal, nil}, // input does not match format 374 375 {"X%s", "X27", &stringVal, "27"}, 376 {"X%s", "X27 ", &stringVal, "27"}, 377 {"X%s", "X 27", &stringVal, "27"}, 378 {"X%s", "X 27 ", &stringVal, "27"}, 379 380 {"X%dX", "X27X", &intVal, 27}, 381 {"X%dX", "X27 X", &intVal, nil}, // input does not match format 382 {"X%dX", "X 27X", &intVal, 27}, 383 {"X%dX", "X 27 X", &intVal, nil}, // input does not match format 384 385 {"X%dX", "X27X", &intVal, 27}, 386 {"X%dX", "X27X ", &intVal, 27}, 387 {"X%dX", " X27X", &intVal, nil}, // input does not match format 388 {"X%dX", " X27X ", &intVal, nil}, // input does not match format 389 390 {"X%dX\n", "X27X", &intVal, 27}, 391 {"X%dX \n", "X27X ", &intVal, 27}, 392 {"X%dX\n", "X27X\n", &intVal, 27}, 393 {"X%dX\n", "X27X \n", &intVal, 27}, 394 395 {"X%dX \n", "X27X", &intVal, 27}, 396 {"X%dX \n", "X27X ", &intVal, 27}, 397 {"X%dX \n", "X27X\n", &intVal, 27}, 398 {"X%dX \n", "X27X \n", &intVal, 27}, 399 400 {"X%c", "X\n", &runeVal, '\n'}, 401 {"X%c", "X \n", &runeVal, ' '}, 402 {"X %c", "X!", &runeVal, nil}, // expected space in input to match format 403 {"X %c", "X\n", &runeVal, nil}, // newline in input does not match format 404 {"X %c", "X !", &runeVal, '!'}, 405 {"X %c", "X \n", &runeVal, '\n'}, 406 407 {" X%dX", "X27X", &intVal, nil}, // expected space in input to match format 408 {" X%dX", "X27X ", &intVal, nil}, // expected space in input to match format 409 {" X%dX", " X27X", &intVal, 27}, 410 {" X%dX", " X27X ", &intVal, 27}, 411 412 {"X%dX ", "X27X", &intVal, 27}, 413 {"X%dX ", "X27X ", &intVal, 27}, 414 {"X%dX ", " X27X", &intVal, nil}, // input does not match format 415 {"X%dX ", " X27X ", &intVal, nil}, // input does not match format 416 417 {" X%dX ", "X27X", &intVal, nil}, // expected space in input to match format 418 {" X%dX ", "X27X ", &intVal, nil}, // expected space in input to match format 419 {" X%dX ", " X27X", &intVal, 27}, 420 {" X%dX ", " X27X ", &intVal, 27}, 421 422 {"%d\nX", "27\nX", &intVal, 27}, 423 {"%dX\n X", "27X\n X", &intVal, 27}, 424} 425 426var overflowTests = []ScanTest{ 427 {"128", &int8Val, 0}, 428 {"32768", &int16Val, 0}, 429 {"-129", &int8Val, 0}, 430 {"-32769", &int16Val, 0}, 431 {"256", &uint8Val, 0}, 432 {"65536", &uint16Val, 0}, 433 {"1e100", &float32Val, 0}, 434 {"1e500", &float64Val, 0}, 435 {"(1e100+0i)", &complex64Val, 0}, 436 {"(1+1e100i)", &complex64Val, 0}, 437 {"(1-1e500i)", &complex128Val, 0}, 438} 439 440var truth bool 441var i, j, k int 442var f float64 443var s, t string 444var c complex128 445var x, y Xs 446var z IntString 447var r1, r2, r3 rune 448 449var multiTests = []ScanfMultiTest{ 450 {"", "", []any{}, []any{}, ""}, 451 {"%d", "23", args(&i), args(23), ""}, 452 {"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""}, 453 {"%2d%3d", "44555", args(&i, &j), args(44, 555), ""}, 454 {"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""}, 455 {"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""}, 456 {"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""}, 457 {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""}, 458 {"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""}, 459 {"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""}, 460 {"%5s%d", " 1234567 ", args(&s, &i), args("12345", 67), ""}, 461 {"%5s%d", " 12 34 567 ", args(&s, &i), args("12", 34), ""}, 462 463 // Custom scanners. 464 {"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""}, 465 {"%4v%s", "12abcd", args(&z, &s), args(IntString{12, "ab"}, "cd"), ""}, 466 467 // Errors 468 {"%t", "23 18", args(&i), nil, "bad verb"}, 469 {"%d %d %d", "23 18", args(&i, &j), args(23, 18), "too few operands"}, 470 {"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"}, 471 {"%c", "\u0100", args(&int8Val), nil, "overflow"}, 472 {"X%d", "10X", args(&intVal), nil, "input does not match format"}, 473 {"%d%", "42%", args(&intVal), args(42), "missing verb: % at end of format string"}, 474 {"%d% ", "42%", args(&intVal), args(42), "too few operands for format '% '"}, // Slightly odd error, but correct. 475 {"%%%d", "xxx 42", args(&intVal), args(42), "missing literal %"}, 476 {"%%%d", "x42", args(&intVal), args(42), "missing literal %"}, 477 {"%%%d", "42", args(&intVal), args(42), "missing literal %"}, 478 479 // Bad UTF-8: should see every byte. 480 {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""}, 481 482 // Fixed bugs 483 {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""}, 484} 485 486var readers = []struct { 487 name string 488 f func(string) io.Reader 489}{ 490 {"StringReader", func(s string) io.Reader { 491 return strings.NewReader(s) 492 }}, 493 {"ReaderOnly", func(s string) io.Reader { 494 return struct{ io.Reader }{strings.NewReader(s)} 495 }}, 496 {"OneByteReader", func(s string) io.Reader { 497 return iotest.OneByteReader(strings.NewReader(s)) 498 }}, 499 {"DataErrReader", func(s string) io.Reader { 500 return iotest.DataErrReader(strings.NewReader(s)) 501 }}, 502} 503 504func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a ...any) (int, error)) { 505 for _, test := range scanTests { 506 r := f(test.text) 507 n, err := scan(r, test.in) 508 if err != nil { 509 m := "" 510 if n > 0 { 511 m = Sprintf(" (%d fields ok)", n) 512 } 513 t.Errorf("got error scanning %q: %s%s", test.text, err, m) 514 continue 515 } 516 if n != 1 { 517 t.Errorf("count error on entry %q: got %d", test.text, n) 518 continue 519 } 520 // The incoming value may be a pointer 521 v := reflect.ValueOf(test.in) 522 if p := v; p.Kind() == reflect.Pointer { 523 v = p.Elem() 524 } 525 val := v.Interface() 526 if !reflect.DeepEqual(val, test.out) { 527 t.Errorf("scanning %q: expected %#v got %#v, type %T", test.text, test.out, val, val) 528 } 529 } 530} 531 532func TestScan(t *testing.T) { 533 for _, r := range readers { 534 t.Run(r.name, func(t *testing.T) { 535 testScan(t, r.f, Fscan) 536 }) 537 } 538} 539 540func TestScanln(t *testing.T) { 541 for _, r := range readers { 542 t.Run(r.name, func(t *testing.T) { 543 testScan(t, r.f, Fscanln) 544 }) 545 } 546} 547 548func TestScanf(t *testing.T) { 549 for _, test := range scanfTests { 550 n, err := Sscanf(test.text, test.format, test.in) 551 if err != nil { 552 if test.out != nil { 553 t.Errorf("Sscanf(%q, %q): unexpected error: %v", test.text, test.format, err) 554 } 555 continue 556 } 557 if test.out == nil { 558 t.Errorf("Sscanf(%q, %q): unexpected success", test.text, test.format) 559 continue 560 } 561 if n != 1 { 562 t.Errorf("Sscanf(%q, %q): parsed %d field, want 1", test.text, test.format, n) 563 continue 564 } 565 // The incoming value may be a pointer 566 v := reflect.ValueOf(test.in) 567 if p := v; p.Kind() == reflect.Pointer { 568 v = p.Elem() 569 } 570 val := v.Interface() 571 if !reflect.DeepEqual(val, test.out) { 572 t.Errorf("Sscanf(%q, %q): parsed value %T(%#v), want %T(%#v)", test.text, test.format, val, val, test.out, test.out) 573 } 574 } 575} 576 577func TestScanOverflow(t *testing.T) { 578 // different machines and different types report errors with different strings. 579 re := regexp.MustCompile("overflow|too large|out of range|not representable") 580 for _, test := range overflowTests { 581 _, err := Sscan(test.text, test.in) 582 if err == nil { 583 t.Errorf("expected overflow scanning %q", test.text) 584 continue 585 } 586 if !re.MatchString(err.Error()) { 587 t.Errorf("expected overflow error scanning %q: %s", test.text, err) 588 } 589 } 590} 591 592func verifyNaN(str string, t *testing.T) { 593 var f float64 594 var f32 float32 595 var f64 float64 596 text := str + " " + str + " " + str 597 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64) 598 if err != nil { 599 t.Errorf("got error scanning %q: %s", text, err) 600 } 601 if n != 3 { 602 t.Errorf("count error scanning %q: got %d", text, n) 603 } 604 if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) { 605 t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64) 606 } 607} 608 609func TestNaN(t *testing.T) { 610 for _, s := range []string{"nan", "NAN", "NaN"} { 611 verifyNaN(s, t) 612 } 613} 614 615func verifyInf(str string, t *testing.T) { 616 var f float64 617 var f32 float32 618 var f64 float64 619 text := str + " " + str + " " + str 620 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64) 621 if err != nil { 622 t.Errorf("got error scanning %q: %s", text, err) 623 } 624 if n != 3 { 625 t.Errorf("count error scanning %q: got %d", text, n) 626 } 627 sign := 1 628 if str[0] == '-' { 629 sign = -1 630 } 631 if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) { 632 t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64) 633 } 634} 635 636func TestInf(t *testing.T) { 637 for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} { 638 verifyInf(s, t) 639 } 640} 641 642func testScanfMulti(t *testing.T, f func(string) io.Reader) { 643 sliceType := reflect.TypeOf(make([]any, 1)) 644 for _, test := range multiTests { 645 r := f(test.text) 646 n, err := Fscanf(r, test.format, test.in...) 647 if err != nil { 648 if test.err == "" { 649 t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err) 650 } else if !strings.Contains(err.Error(), test.err) { 651 t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err) 652 } 653 continue 654 } 655 if test.err != "" { 656 t.Errorf("expected error %q error scanning (%q, %q)", test.err, test.format, test.text) 657 } 658 if n != len(test.out) { 659 t.Errorf("count error on entry (%q, %q): expected %d got %d", test.format, test.text, len(test.out), n) 660 continue 661 } 662 // Convert the slice of pointers into a slice of values 663 resultVal := reflect.MakeSlice(sliceType, n, n) 664 for i := 0; i < n; i++ { 665 v := reflect.ValueOf(test.in[i]).Elem() 666 resultVal.Index(i).Set(v) 667 } 668 result := resultVal.Interface() 669 if !reflect.DeepEqual(result, test.out) { 670 t.Errorf("scanning (%q, %q): expected %#v got %#v", test.format, test.text, test.out, result) 671 } 672 } 673} 674 675func TestScanfMulti(t *testing.T) { 676 for _, r := range readers { 677 t.Run(r.name, func(t *testing.T) { 678 testScanfMulti(t, r.f) 679 }) 680 } 681} 682 683func TestScanMultiple(t *testing.T) { 684 var a int 685 var s string 686 n, err := Sscan("123abc", &a, &s) 687 if n != 2 { 688 t.Errorf("Sscan count error: expected 2: got %d", n) 689 } 690 if err != nil { 691 t.Errorf("Sscan expected no error; got %s", err) 692 } 693 if a != 123 || s != "abc" { 694 t.Errorf("Sscan wrong values: got (%d %q) expected (123 \"abc\")", a, s) 695 } 696 n, err = Sscan("asdf", &s, &a) 697 if n != 1 { 698 t.Errorf("Sscan count error: expected 1: got %d", n) 699 } 700 if err == nil { 701 t.Errorf("Sscan expected error; got none: %s", err) 702 } 703 if s != "asdf" { 704 t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s) 705 } 706} 707 708// Empty strings are not valid input when scanning a string. 709func TestScanEmpty(t *testing.T) { 710 var s1, s2 string 711 n, err := Sscan("abc", &s1, &s2) 712 if n != 1 { 713 t.Errorf("Sscan count error: expected 1: got %d", n) 714 } 715 if err == nil { 716 t.Error("Sscan <one item> expected error; got none") 717 } 718 if s1 != "abc" { 719 t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1) 720 } 721 n, err = Sscan("", &s1, &s2) 722 if n != 0 { 723 t.Errorf("Sscan count error: expected 0: got %d", n) 724 } 725 if err == nil { 726 t.Error("Sscan <empty> expected error; got none") 727 } 728 // Quoted empty string is OK. 729 n, err = Sscanf(`""`, "%q", &s1) 730 if n != 1 { 731 t.Errorf("Sscanf count error: expected 1: got %d", n) 732 } 733 if err != nil { 734 t.Errorf("Sscanf <empty> expected no error with quoted string; got %s", err) 735 } 736} 737 738func TestScanNotPointer(t *testing.T) { 739 r := strings.NewReader("1") 740 var a int 741 _, err := Fscan(r, a) 742 if err == nil { 743 t.Error("expected error scanning non-pointer") 744 } else if !strings.Contains(err.Error(), "pointer") { 745 t.Errorf("expected pointer error scanning non-pointer, got: %s", err) 746 } 747} 748 749func TestScanlnNoNewline(t *testing.T) { 750 var a int 751 _, err := Sscanln("1 x\n", &a) 752 if err == nil { 753 t.Error("expected error scanning string missing newline") 754 } else if !strings.Contains(err.Error(), "newline") { 755 t.Errorf("expected newline error scanning string missing newline, got: %s", err) 756 } 757} 758 759func TestScanlnWithMiddleNewline(t *testing.T) { 760 r := strings.NewReader("123\n456\n") 761 var a, b int 762 _, err := Fscanln(r, &a, &b) 763 if err == nil { 764 t.Error("expected error scanning string with extra newline") 765 } else if !strings.Contains(err.Error(), "newline") { 766 t.Errorf("expected newline error scanning string with extra newline, got: %s", err) 767 } 768} 769 770// eofCounter is a special Reader that counts reads at end of file. 771type eofCounter struct { 772 reader *strings.Reader 773 eofCount int 774} 775 776func (ec *eofCounter) Read(b []byte) (n int, err error) { 777 n, err = ec.reader.Read(b) 778 if n == 0 { 779 ec.eofCount++ 780 } 781 return 782} 783 784// TestEOF verifies that when we scan, we see at most EOF once per call to a 785// Scan function, and then only when it's really an EOF. 786func TestEOF(t *testing.T) { 787 ec := &eofCounter{strings.NewReader("123\n"), 0} 788 var a int 789 n, err := Fscanln(ec, &a) 790 if err != nil { 791 t.Error("unexpected error", err) 792 } 793 if n != 1 { 794 t.Error("expected to scan one item, got", n) 795 } 796 if ec.eofCount != 0 { 797 t.Error("expected zero EOFs", ec.eofCount) 798 ec.eofCount = 0 // reset for next test 799 } 800 n, err = Fscanln(ec, &a) 801 if err == nil { 802 t.Error("expected error scanning empty string") 803 } 804 if n != 0 { 805 t.Error("expected to scan zero items, got", n) 806 } 807 if ec.eofCount != 1 { 808 t.Error("expected one EOF, got", ec.eofCount) 809 } 810} 811 812// TestEOFAtEndOfInput verifies that we see an EOF error if we run out of input. 813// This was a buglet: we used to get "expected integer". 814func TestEOFAtEndOfInput(t *testing.T) { 815 var i, j int 816 n, err := Sscanf("23", "%d %d", &i, &j) 817 if n != 1 || i != 23 { 818 t.Errorf("Sscanf expected one value of 23; got %d %d", n, i) 819 } 820 if err != io.EOF { 821 t.Errorf("Sscanf expected EOF; got %q", err) 822 } 823 n, err = Sscan("234", &i, &j) 824 if n != 1 || i != 234 { 825 t.Errorf("Sscan expected one value of 234; got %d %d", n, i) 826 } 827 if err != io.EOF { 828 t.Errorf("Sscan expected EOF; got %q", err) 829 } 830 // Trailing space is tougher. 831 n, err = Sscan("234 ", &i, &j) 832 if n != 1 || i != 234 { 833 t.Errorf("Sscan expected one value of 234; got %d %d", n, i) 834 } 835 if err != io.EOF { 836 t.Errorf("Sscan expected EOF; got %q", err) 837 } 838} 839 840var eofTests = []struct { 841 format string 842 v any 843}{ 844 {"%s", &stringVal}, 845 {"%q", &stringVal}, 846 {"%x", &stringVal}, 847 {"%v", &stringVal}, 848 {"%v", &bytesVal}, 849 {"%v", &intVal}, 850 {"%v", &uintVal}, 851 {"%v", &boolVal}, 852 {"%v", &float32Val}, 853 {"%v", &complex64Val}, 854 {"%v", &renamedStringVal}, 855 {"%v", &renamedBytesVal}, 856 {"%v", &renamedIntVal}, 857 {"%v", &renamedUintVal}, 858 {"%v", &renamedBoolVal}, 859 {"%v", &renamedFloat32Val}, 860 {"%v", &renamedComplex64Val}, 861} 862 863func TestEOFAllTypes(t *testing.T) { 864 for i, test := range eofTests { 865 if _, err := Sscanf("", test.format, test.v); err != io.EOF { 866 t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err) 867 } 868 if _, err := Sscanf(" ", test.format, test.v); err != io.EOF { 869 t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err) 870 } 871 } 872} 873 874// TestUnreadRuneWithBufio verifies that, at least when using bufio, successive 875// calls to Fscan do not lose runes. 876func TestUnreadRuneWithBufio(t *testing.T) { 877 r := bufio.NewReader(strings.NewReader("123αb")) 878 var i int 879 var a string 880 n, err := Fscanf(r, "%d", &i) 881 if n != 1 || err != nil { 882 t.Errorf("reading int expected one item, no errors; got %d %q", n, err) 883 } 884 if i != 123 { 885 t.Errorf("expected 123; got %d", i) 886 } 887 n, err = Fscanf(r, "%s", &a) 888 if n != 1 || err != nil { 889 t.Errorf("reading string expected one item, no errors; got %d %q", n, err) 890 } 891 if a != "αb" { 892 t.Errorf("expected αb; got %q", a) 893 } 894} 895 896type TwoLines string 897 898// Scan attempts to read two lines into the object. Scanln should prevent this 899// because it stops at newline; Scan and Scanf should be fine. 900func (t *TwoLines) Scan(state ScanState, verb rune) error { 901 chars := make([]rune, 0, 100) 902 for nlCount := 0; nlCount < 2; { 903 c, _, err := state.ReadRune() 904 if err != nil { 905 return err 906 } 907 chars = append(chars, c) 908 if c == '\n' { 909 nlCount++ 910 } 911 } 912 *t = TwoLines(string(chars)) 913 return nil 914} 915 916func TestMultiLine(t *testing.T) { 917 input := "abc\ndef\n" 918 // Sscan should work 919 var tscan TwoLines 920 n, err := Sscan(input, &tscan) 921 if n != 1 { 922 t.Errorf("Sscan: expected 1 item; got %d", n) 923 } 924 if err != nil { 925 t.Errorf("Sscan: expected no error; got %s", err) 926 } 927 if string(tscan) != input { 928 t.Errorf("Sscan: expected %q; got %q", input, tscan) 929 } 930 // Sscanf should work 931 var tscanf TwoLines 932 n, err = Sscanf(input, "%s", &tscanf) 933 if n != 1 { 934 t.Errorf("Sscanf: expected 1 item; got %d", n) 935 } 936 if err != nil { 937 t.Errorf("Sscanf: expected no error; got %s", err) 938 } 939 if string(tscanf) != input { 940 t.Errorf("Sscanf: expected %q; got %q", input, tscanf) 941 } 942 // Sscanln should not work 943 var tscanln TwoLines 944 n, err = Sscanln(input, &tscanln) 945 if n != 0 { 946 t.Errorf("Sscanln: expected 0 items; got %d: %q", n, tscanln) 947 } 948 if err == nil { 949 t.Error("Sscanln: expected error; got none") 950 } else if err != io.ErrUnexpectedEOF { 951 t.Errorf("Sscanln: expected io.ErrUnexpectedEOF (ha!); got %s", err) 952 } 953} 954 955// TestLineByLineFscanf tests that Fscanf does not read past newline. Issue 956// 3481. 957func TestLineByLineFscanf(t *testing.T) { 958 r := struct{ io.Reader }{strings.NewReader("1\n2\n")} 959 var i, j int 960 n, err := Fscanf(r, "%v\n", &i) 961 if n != 1 || err != nil { 962 t.Fatalf("first read: %d %q", n, err) 963 } 964 n, err = Fscanf(r, "%v\n", &j) 965 if n != 1 || err != nil { 966 t.Fatalf("second read: %d %q", n, err) 967 } 968 if i != 1 || j != 2 { 969 t.Errorf("wrong values; wanted 1 2 got %d %d", i, j) 970 } 971} 972 973// TestScanStateCount verifies the correct byte count is returned. Issue 8512. 974 975// runeScanner implements the Scanner interface for TestScanStateCount. 976type runeScanner struct { 977 rune rune 978 size int 979} 980 981func (rs *runeScanner) Scan(state ScanState, verb rune) error { 982 r, size, err := state.ReadRune() 983 rs.rune = r 984 rs.size = size 985 return err 986} 987 988func TestScanStateCount(t *testing.T) { 989 var a, b, c runeScanner 990 n, err := Sscanf("12➂", "%c%c%c", &a, &b, &c) 991 if err != nil { 992 t.Fatal(err) 993 } 994 if n != 3 { 995 t.Fatalf("expected 3 items consumed, got %d", n) 996 } 997 if a.rune != '1' || b.rune != '2' || c.rune != '➂' { 998 t.Errorf("bad scan rune: %q %q %q should be '1' '2' '➂'", a.rune, b.rune, c.rune) 999 } 1000 if a.size != 1 || b.size != 1 || c.size != 3 { 1001 t.Errorf("bad scan size: %q %q %q should be 1 1 3", a.size, b.size, c.size) 1002 } 1003} 1004 1005// RecursiveInt accepts a string matching %d.%d.%d.... 1006// and parses it into a linked list. 1007// It allows us to benchmark recursive descent style scanners. 1008type RecursiveInt struct { 1009 i int 1010 next *RecursiveInt 1011} 1012 1013func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) { 1014 _, err = Fscan(state, &r.i) 1015 if err != nil { 1016 return 1017 } 1018 next := new(RecursiveInt) 1019 _, err = Fscanf(state, ".%v", next) 1020 if err != nil { 1021 if err == io.ErrUnexpectedEOF { 1022 err = nil 1023 } 1024 return 1025 } 1026 r.next = next 1027 return 1028} 1029 1030// scanInts performs the same scanning task as RecursiveInt.Scan 1031// but without recurring through scanner, so we can compare 1032// performance more directly. 1033func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) { 1034 r.next = nil 1035 _, err = Fscan(b, &r.i) 1036 if err != nil { 1037 return 1038 } 1039 c, _, err := b.ReadRune() 1040 if err != nil { 1041 if err == io.EOF { 1042 err = nil 1043 } 1044 return 1045 } 1046 if c != '.' { 1047 return 1048 } 1049 next := new(RecursiveInt) 1050 err = scanInts(next, b) 1051 if err == nil { 1052 r.next = next 1053 } 1054 return 1055} 1056 1057func makeInts(n int) []byte { 1058 var buf bytes.Buffer 1059 Fprintf(&buf, "1") 1060 for i := 1; i < n; i++ { 1061 Fprintf(&buf, ".%d", i+1) 1062 } 1063 return buf.Bytes() 1064} 1065 1066func TestScanInts(t *testing.T) { 1067 testScanInts(t, scanInts) 1068 testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err error) { 1069 _, err = Fscan(b, r) 1070 return 1071 }) 1072} 1073 1074// 800 is small enough to not overflow the stack when using gccgo on a 1075// platform that does not support split stack. 1076const intCount = 800 1077 1078func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) error) { 1079 r := new(RecursiveInt) 1080 ints := makeInts(intCount) 1081 buf := bytes.NewBuffer(ints) 1082 err := scan(r, buf) 1083 if err != nil { 1084 t.Error("unexpected error", err) 1085 } 1086 i := 1 1087 for ; r != nil; r = r.next { 1088 if r.i != i { 1089 t.Fatalf("bad scan: expected %d got %d", i, r.i) 1090 } 1091 i++ 1092 } 1093 if i-1 != intCount { 1094 t.Fatalf("bad scan count: expected %d got %d", intCount, i-1) 1095 } 1096} 1097 1098func BenchmarkScanInts(b *testing.B) { 1099 b.StopTimer() 1100 ints := makeInts(intCount) 1101 var r RecursiveInt 1102 for i := 0; i < b.N; i++ { 1103 buf := bytes.NewBuffer(ints) 1104 b.StartTimer() 1105 scanInts(&r, buf) 1106 b.StopTimer() 1107 } 1108} 1109 1110func BenchmarkScanRecursiveInt(b *testing.B) { 1111 b.StopTimer() 1112 ints := makeInts(intCount) 1113 var r RecursiveInt 1114 for i := 0; i < b.N; i++ { 1115 buf := bytes.NewBuffer(ints) 1116 b.StartTimer() 1117 Fscan(buf, &r) 1118 b.StopTimer() 1119 } 1120} 1121 1122func BenchmarkScanRecursiveIntReaderWrapper(b *testing.B) { 1123 b.StopTimer() 1124 ints := makeInts(intCount) 1125 var r RecursiveInt 1126 for i := 0; i < b.N; i++ { 1127 buf := struct{ io.Reader }{strings.NewReader(string(ints))} 1128 b.StartTimer() 1129 Fscan(buf, &r) 1130 b.StopTimer() 1131 } 1132} 1133 1134// Issue 9124. 1135// %x on bytes couldn't handle non-space bytes terminating the scan. 1136func TestHexBytes(t *testing.T) { 1137 var a, b []byte 1138 n, err := Sscanf("00010203", "%x", &a) 1139 if n != 1 || err != nil { 1140 t.Errorf("simple: got count, err = %d, %v; expected 1, nil", n, err) 1141 } 1142 check := func(msg string, x []byte) { 1143 if len(x) != 4 { 1144 t.Errorf("%s: bad length %d", msg, len(x)) 1145 } 1146 for i, b := range x { 1147 if int(b) != i { 1148 t.Errorf("%s: bad x[%d] = %x", msg, i, x[i]) 1149 } 1150 } 1151 } 1152 check("simple", a) 1153 a = nil 1154 1155 n, err = Sscanf("00010203 00010203", "%x %x", &a, &b) 1156 if n != 2 || err != nil { 1157 t.Errorf("simple pair: got count, err = %d, %v; expected 2, nil", n, err) 1158 } 1159 check("simple pair a", a) 1160 check("simple pair b", b) 1161 a = nil 1162 b = nil 1163 1164 n, err = Sscanf("00010203:", "%x", &a) 1165 if n != 1 || err != nil { 1166 t.Errorf("colon: got count, err = %d, %v; expected 1, nil", n, err) 1167 } 1168 check("colon", a) 1169 a = nil 1170 1171 n, err = Sscanf("00010203:00010203", "%x:%x", &a, &b) 1172 if n != 2 || err != nil { 1173 t.Errorf("colon pair: got count, err = %d, %v; expected 2, nil", n, err) 1174 } 1175 check("colon pair a", a) 1176 check("colon pair b", b) 1177 a = nil 1178 b = nil 1179 1180 // This one fails because there is a hex byte after the data, 1181 // that is, an odd number of hex input bytes. 1182 n, err = Sscanf("000102034:", "%x", &a) 1183 if n != 0 || err == nil { 1184 t.Errorf("odd count: got count, err = %d, %v; expected 0, error", n, err) 1185 } 1186} 1187 1188func TestScanNewlinesAreSpaces(t *testing.T) { 1189 var a, b int 1190 var tests = []struct { 1191 name string 1192 text string 1193 count int 1194 }{ 1195 {"newlines", "1\n2\n", 2}, 1196 {"no final newline", "1\n2", 2}, 1197 {"newlines with spaces ", "1 \n 2 \n", 2}, 1198 {"no final newline with spaces", "1 \n 2", 2}, 1199 } 1200 for _, test := range tests { 1201 n, err := Sscan(test.text, &a, &b) 1202 if n != test.count { 1203 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n) 1204 } 1205 if err != nil { 1206 t.Errorf("%s: unexpected error: %s", test.name, err) 1207 } 1208 } 1209} 1210 1211func TestScanlnNewlinesTerminate(t *testing.T) { 1212 var a, b int 1213 var tests = []struct { 1214 name string 1215 text string 1216 count int 1217 ok bool 1218 }{ 1219 {"one line one item", "1\n", 1, false}, 1220 {"one line two items with spaces ", " 1 2 \n", 2, true}, 1221 {"one line two items no newline", " 1 2", 2, true}, 1222 {"two lines two items", "1\n2\n", 1, false}, 1223 } 1224 for _, test := range tests { 1225 n, err := Sscanln(test.text, &a, &b) 1226 if n != test.count { 1227 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n) 1228 } 1229 if test.ok && err != nil { 1230 t.Errorf("%s: unexpected error: %s", test.name, err) 1231 } 1232 if !test.ok && err == nil { 1233 t.Errorf("%s: expected error; got none", test.name) 1234 } 1235 } 1236} 1237 1238func TestScanfNewlineMatchFormat(t *testing.T) { 1239 var a, b int 1240 var tests = []struct { 1241 name string 1242 text string 1243 format string 1244 count int 1245 ok bool 1246 }{ 1247 {"newline in both", "1\n2", "%d\n%d\n", 2, true}, 1248 {"newline in input", "1\n2", "%d %d", 1, false}, 1249 {"space-newline in input", "1 \n2", "%d %d", 1, false}, 1250 {"newline in format", "1 2", "%d\n%d", 1, false}, 1251 {"space-newline in format", "1 2", "%d \n%d", 1, false}, 1252 {"space-newline in both", "1 \n2", "%d \n%d", 2, true}, 1253 {"extra space in format", "1\n2", "%d\n %d", 2, true}, 1254 {"two extra spaces in format", "1\n2", "%d \n %d", 2, true}, 1255 {"space vs newline 0000", "1\n2", "%d\n%d", 2, true}, 1256 {"space vs newline 0001", "1\n2", "%d\n %d", 2, true}, 1257 {"space vs newline 0010", "1\n2", "%d \n%d", 2, true}, 1258 {"space vs newline 0011", "1\n2", "%d \n %d", 2, true}, 1259 {"space vs newline 0100", "1\n 2", "%d\n%d", 2, true}, 1260 {"space vs newline 0101", "1\n 2", "%d\n%d ", 2, true}, 1261 {"space vs newline 0110", "1\n 2", "%d \n%d", 2, true}, 1262 {"space vs newline 0111", "1\n 2", "%d \n %d", 2, true}, 1263 {"space vs newline 1000", "1 \n2", "%d\n%d", 2, true}, 1264 {"space vs newline 1001", "1 \n2", "%d\n %d", 2, true}, 1265 {"space vs newline 1010", "1 \n2", "%d \n%d", 2, true}, 1266 {"space vs newline 1011", "1 \n2", "%d \n %d", 2, true}, 1267 {"space vs newline 1100", "1 \n 2", "%d\n%d", 2, true}, 1268 {"space vs newline 1101", "1 \n 2", "%d\n %d", 2, true}, 1269 {"space vs newline 1110", "1 \n 2", "%d \n%d", 2, true}, 1270 {"space vs newline 1111", "1 \n 2", "%d \n %d", 2, true}, 1271 {"space vs newline no-percent 0000", "1\n2", "1\n2", 0, true}, 1272 {"space vs newline no-percent 0001", "1\n2", "1\n 2", 0, true}, 1273 {"space vs newline no-percent 0010", "1\n2", "1 \n2", 0, true}, 1274 {"space vs newline no-percent 0011", "1\n2", "1 \n 2", 0, true}, 1275 {"space vs newline no-percent 0100", "1\n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern 1276 {"space vs newline no-percent 0101", "1\n 2", "1\n2 ", 0, false}, // fails: space after nl in input but not pattern 1277 {"space vs newline no-percent 0110", "1\n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern 1278 {"space vs newline no-percent 0111", "1\n 2", "1 \n 2", 0, true}, 1279 {"space vs newline no-percent 1000", "1 \n2", "1\n2", 0, true}, 1280 {"space vs newline no-percent 1001", "1 \n2", "1\n 2", 0, true}, 1281 {"space vs newline no-percent 1010", "1 \n2", "1 \n2", 0, true}, 1282 {"space vs newline no-percent 1011", "1 \n2", "1 \n 2", 0, true}, 1283 {"space vs newline no-percent 1100", "1 \n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern 1284 {"space vs newline no-percent 1101", "1 \n 2", "1\n 2", 0, true}, 1285 {"space vs newline no-percent 1110", "1 \n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern 1286 {"space vs newline no-percent 1111", "1 \n 2", "1 \n 2", 0, true}, 1287 } 1288 for _, test := range tests { 1289 var n int 1290 var err error 1291 if strings.Contains(test.format, "%") { 1292 n, err = Sscanf(test.text, test.format, &a, &b) 1293 } else { 1294 n, err = Sscanf(test.text, test.format) 1295 } 1296 if n != test.count { 1297 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n) 1298 } 1299 if test.ok && err != nil { 1300 t.Errorf("%s: unexpected error: %s", test.name, err) 1301 } 1302 if !test.ok && err == nil { 1303 t.Errorf("%s: expected error; got none", test.name) 1304 } 1305 } 1306} 1307 1308// Test for issue 12090: Was unreading at EOF, double-scanning a byte. 1309 1310type hexBytes [2]byte 1311 1312func (h *hexBytes) Scan(ss ScanState, verb rune) error { 1313 var b []byte 1314 _, err := Fscanf(ss, "%4x", &b) 1315 if err != nil { 1316 panic(err) // Really shouldn't happen. 1317 } 1318 copy((*h)[:], b) 1319 return err 1320} 1321 1322func TestHexByte(t *testing.T) { 1323 var h hexBytes 1324 n, err := Sscanln("0123\n", &h) 1325 if err != nil { 1326 t.Fatal(err) 1327 } 1328 if n != 1 { 1329 t.Fatalf("expected 1 item; scanned %d", n) 1330 } 1331 if h[0] != 0x01 || h[1] != 0x23 { 1332 t.Fatalf("expected 0123 got %x", h) 1333 } 1334} 1335