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 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
84 type Xs string
85
86 func (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
99 var xVal Xs
100
101
102
103 type IntString struct {
104 i int
105 s string
106 }
107
108 func (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
121 var intStringVal IntString
122
123 var scanTests = []ScanTest{
124
125 {"T\n", &boolVal, true},
126 {"F\n", &boolVal, false},
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
191 {"hello\r\n", &stringVal, "hello"},
192 {"27\r\n", &uint8Val, uint8(27)},
193
194
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
214 {" vvv ", &xVal, Xs("vvv")},
215 {" 1234hello", &intStringVal, IntString{1234, "hello"}},
216
217
218 {"2147483648\n", &int64Val, int64(2147483648)},
219 }
220
221 var 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)},
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)},
257 {"%x", "a75\n", &uintVal, uint(0xa75)},
258 {"%x", "A75\n", &uintVal, uint(0xa75)},
259 {"%x", "A7_5\n", &uintVal, uint(0xa7)},
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
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
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
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
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},
315
316
317 {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)},
318
319
320 {"%s", " sss ", &xVal, Xs("sss")},
321 {"%2s", "sssss", &xVal, Xs("ss")},
322
323
324 {"%d\n", "27\n", &intVal, 27},
325 {"%d\n", "28 \n", &intVal, 28},
326 {"%v", "0", &intVal, 0},
327 {"%v", "0", &uintVal, uint(0)},
328 {"%c", " ", &uintVal, uint(' ')},
329 {"%c", "\t", &uintVal, uint('\t')},
330 {"%c", "\n", &uintVal, uint('\n')},
331 {"%d%%", "23%\n", &uintVal, uint(23)},
332 {"%%%d", "%23\n", &uintVal, uint(23)},
333
334
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},
346 {"X %d", "X27 ", &intVal, nil},
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},
352 {"%dX", " 27X", &intVal, 27},
353 {"%dX", " 27 X", &intVal, nil},
354
355 {"%d X", "27X", &intVal, nil},
356 {"%d X", "27 X", &intVal, 27},
357 {"%d X", " 27X", &intVal, nil},
358 {"%d X", " 27 X", &intVal, 27},
359
360 {"X %d X", "X27X", &intVal, nil},
361 {"X %d X", "X27 X", &intVal, nil},
362 {"X %d X", "X 27X", &intVal, nil},
363 {"X %d X", "X 27 X", &intVal, 27},
364
365 {"X %s X", "X27X", &stringVal, nil},
366 {"X %s X", "X27 X", &stringVal, nil},
367 {"X %s X", "X 27X", &stringVal, nil},
368 {"X %s X", "X 27 X", &stringVal, "27"},
369
370 {"X%sX", "X27X", &stringVal, nil},
371 {"X%sX", "X27 X", &stringVal, nil},
372 {"X%sX", "X 27X", &stringVal, nil},
373 {"X%sX", "X 27 X", &stringVal, nil},
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},
382 {"X%dX", "X 27X", &intVal, 27},
383 {"X%dX", "X 27 X", &intVal, nil},
384
385 {"X%dX", "X27X", &intVal, 27},
386 {"X%dX", "X27X ", &intVal, 27},
387 {"X%dX", " X27X", &intVal, nil},
388 {"X%dX", " X27X ", &intVal, nil},
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},
403 {"X %c", "X\n", &runeVal, nil},
404 {"X %c", "X !", &runeVal, '!'},
405 {"X %c", "X \n", &runeVal, '\n'},
406
407 {" X%dX", "X27X", &intVal, nil},
408 {" X%dX", "X27X ", &intVal, nil},
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},
415 {"X%dX ", " X27X ", &intVal, nil},
416
417 {" X%dX ", "X27X", &intVal, nil},
418 {" X%dX ", "X27X ", &intVal, nil},
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
426 var 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
440 var truth bool
441 var i, j, k int
442 var f float64
443 var s, t string
444 var c complex128
445 var x, y Xs
446 var z IntString
447 var r1, r2, r3 rune
448
449 var 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
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
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 '% '"},
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
480 {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
481
482
483 {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""},
484 }
485
486 var 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
504 func 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
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
532 func 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
540 func 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
548 func 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
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
577 func TestScanOverflow(t *testing.T) {
578
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
592 func 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
609 func TestNaN(t *testing.T) {
610 for _, s := range []string{"nan", "NAN", "NaN"} {
611 verifyNaN(s, t)
612 }
613 }
614
615 func 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
636 func 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
642 func 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
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
675 func 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
683 func 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
709 func 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
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
738 func 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
749 func 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
759 func 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
771 type eofCounter struct {
772 reader *strings.Reader
773 eofCount int
774 }
775
776 func (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
785
786 func 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
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
813
814 func 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
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
840 var 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
863 func 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
875
876 func 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
896 type TwoLines string
897
898
899
900 func (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
916 func TestMultiLine(t *testing.T) {
917 input := "abc\ndef\n"
918
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
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
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
956
957 func 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
974
975
976 type runeScanner struct {
977 rune rune
978 size int
979 }
980
981 func (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
988 func 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
1006
1007
1008 type RecursiveInt struct {
1009 i int
1010 next *RecursiveInt
1011 }
1012
1013 func (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
1031
1032
1033 func 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
1057 func 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
1066 func 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
1075
1076 const intCount = 800
1077
1078 func 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
1098 func 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
1110 func 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
1122 func 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
1135
1136 func 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
1181
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
1188 func 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
1211 func 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
1238 func 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},
1276 {"space vs newline no-percent 0101", "1\n 2", "1\n2 ", 0, false},
1277 {"space vs newline no-percent 0110", "1\n 2", "1 \n2", 0, false},
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},
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},
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
1309
1310 type hexBytes [2]byte
1311
1312 func (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)
1317 }
1318 copy((*h)[:], b)
1319 return err
1320 }
1321
1322 func 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
View as plain text