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