* gcc-interface/decl.c (warn_on_field_placement): Issue the warning
[official-gcc.git] / libgo / go / fmt / scan_test.go
blobd7019d943942c7d297d6f80eff1372479e3140f8
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.
5 package fmt_test
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"
22 type ScanTest struct {
23 text string
24 in interface{}
25 out interface{}
28 type ScanfTest struct {
29 format string
30 text string
31 in interface{}
32 out interface{}
35 type ScanfMultiTest struct {
36 format string
37 text string
38 in []interface{}
39 out []interface{}
40 err string
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
82 // Xs accepts any non-empty run of the verb character
83 type Xs string
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
90 s := string(tok)
91 if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) {
92 return errors.New("syntax error for xs")
94 *x = Xs(s)
95 return nil
98 var xVal Xs
100 // IntString accepts an integer followed immediately by a string.
101 // It tests the embedding of a scan within a scan.
102 type IntString struct {
103 i int
104 s string
107 func (s *IntString) Scan(state ScanState, verb rune) error {
108 if _, err := Fscan(state, &s.i); err != nil {
109 return err
112 tok, err := state.Token(true, nil)
113 if err != nil {
114 return err
116 s.s = string(tok)
117 return nil
120 var intStringVal IntString
122 var scanTests = []ScanTest{
123 // Basic types
124 {"T\n", &boolVal, true}, // boolean test vals toggle to be sure they are written
125 {"F\n", &boolVal, false}, // restored to zero value
126 {"21\n", &intVal, 21},
127 {"0\n", &intVal, 0},
128 {"000\n", &intVal, 0},
129 {"0x10\n", &intVal, 0x10},
130 {"-0x10\n", &intVal, -0x10},
131 {"0377\n", &intVal, 0377},
132 {"-0377\n", &intVal, -0377},
133 {"0\n", &uintVal, uint(0)},
134 {"000\n", &uintVal, uint(0)},
135 {"0x10\n", &uintVal, uint(0x10)},
136 {"0377\n", &uintVal, uint(0377)},
137 {"22\n", &int8Val, int8(22)},
138 {"23\n", &int16Val, int16(23)},
139 {"24\n", &int32Val, int32(24)},
140 {"25\n", &int64Val, int64(25)},
141 {"127\n", &int8Val, int8(127)},
142 {"-21\n", &intVal, -21},
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 {"-128\n", &int8Val, int8(-128)},
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 {"+127\n", &int8Val, int8(+127)},
154 {"26\n", &uintVal, uint(26)},
155 {"27\n", &uint8Val, uint8(27)},
156 {"28\n", &uint16Val, uint16(28)},
157 {"29\n", &uint32Val, uint32(29)},
158 {"30\n", &uint64Val, uint64(30)},
159 {"255\n", &uint8Val, uint8(255)},
160 {"32767\n", &int16Val, int16(32767)},
161 {"2.3\n", &float64Val, 2.3},
162 {"2.3e1\n", &float32Val, float32(2.3e1)},
163 {"2.3e2\n", &float64Val, 2.3e2},
164 {"2.3p2\n", &float64Val, 2.3 * 4},
165 {"2.3p+2\n", &float64Val, 2.3 * 4},
166 {"2.3p+66\n", &float64Val, 2.3 * (1 << 32) * (1 << 32) * 4},
167 {"2.3p-66\n", &float64Val, 2.3 / ((1 << 32) * (1 << 32) * 4)},
168 {"2.35\n", &stringVal, "2.35"},
169 {"2345678\n", &bytesVal, []byte("2345678")},
170 {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i},
171 {"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
172 {"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
173 {"hello\n", &stringVal, "hello"},
175 // Carriage-return followed by newline. (We treat \r\n as \n always.)
176 {"hello\r\n", &stringVal, "hello"},
177 {"27\r\n", &uint8Val, uint8(27)},
179 // Renamed types
180 {"true\n", &renamedBoolVal, renamedBool(true)},
181 {"F\n", &renamedBoolVal, renamedBool(false)},
182 {"101\n", &renamedIntVal, renamedInt(101)},
183 {"102\n", &renamedIntVal, renamedInt(102)},
184 {"103\n", &renamedUintVal, renamedUint(103)},
185 {"104\n", &renamedUintVal, renamedUint(104)},
186 {"105\n", &renamedInt8Val, renamedInt8(105)},
187 {"106\n", &renamedInt16Val, renamedInt16(106)},
188 {"107\n", &renamedInt32Val, renamedInt32(107)},
189 {"108\n", &renamedInt64Val, renamedInt64(108)},
190 {"109\n", &renamedUint8Val, renamedUint8(109)},
191 {"110\n", &renamedUint16Val, renamedUint16(110)},
192 {"111\n", &renamedUint32Val, renamedUint32(111)},
193 {"112\n", &renamedUint64Val, renamedUint64(112)},
194 {"113\n", &renamedUintptrVal, renamedUintptr(113)},
195 {"114\n", &renamedStringVal, renamedString("114")},
196 {"115\n", &renamedBytesVal, renamedBytes([]byte("115"))},
198 // Custom scanners.
199 {" vvv ", &xVal, Xs("vvv")},
200 {" 1234hello", &intStringVal, IntString{1234, "hello"}},
202 // Fixed bugs
203 {"2147483648\n", &int64Val, int64(2147483648)}, // was: integer overflow
206 var scanfTests = []ScanfTest{
207 {"%v", "TRUE\n", &boolVal, true},
208 {"%t", "false\n", &boolVal, false},
209 {"%v", "-71\n", &intVal, -71},
210 {"%v", "0377\n", &intVal, 0377},
211 {"%v", "0x44\n", &intVal, 0x44},
212 {"%d", "72\n", &intVal, 72},
213 {"%c", "a\n", &runeVal, 'a'},
214 {"%c", "\u5072\n", &runeVal, '\u5072'},
215 {"%c", "\u1234\n", &runeVal, '\u1234'},
216 {"%d", "73\n", &int8Val, int8(73)},
217 {"%d", "+74\n", &int16Val, int16(74)},
218 {"%d", "75\n", &int32Val, int32(75)},
219 {"%d", "76\n", &int64Val, int64(76)},
220 {"%b", "1001001\n", &intVal, 73},
221 {"%o", "075\n", &intVal, 075},
222 {"%x", "a75\n", &intVal, 0xa75},
223 {"%v", "71\n", &uintVal, uint(71)},
224 {"%d", "72\n", &uintVal, uint(72)},
225 {"%d", "73\n", &uint8Val, uint8(73)},
226 {"%d", "74\n", &uint16Val, uint16(74)},
227 {"%d", "75\n", &uint32Val, uint32(75)},
228 {"%d", "76\n", &uint64Val, uint64(76)},
229 {"%b", "1001001\n", &uintVal, uint(73)},
230 {"%o", "075\n", &uintVal, uint(075)},
231 {"%x", "a75\n", &uintVal, uint(0xa75)},
232 {"%x", "A75\n", &uintVal, uint(0xa75)},
233 {"%U", "U+1234\n", &intVal, int(0x1234)},
234 {"%U", "U+4567\n", &uintVal, uint(0x4567)},
236 // Strings
237 {"%s", "using-%s\n", &stringVal, "using-%s"},
238 {"%x", "7573696e672d2578\n", &stringVal, "using-%x"},
239 {"%X", "7573696E672D2558\n", &stringVal, "using-%X"},
240 {"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
241 {"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
243 // Byte slices
244 {"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
245 {"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
246 {"%X", "62797465732D2558\n", &bytesVal, []byte("bytes-%X")},
247 {"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
248 {"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
250 // Renamed types
251 {"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
252 {"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
253 {"%v", "101\n", &renamedIntVal, renamedInt(101)},
254 {"%c", "\u0101\n", &renamedIntVal, renamedInt('\u0101')},
255 {"%o", "0146\n", &renamedIntVal, renamedInt(102)},
256 {"%v", "103\n", &renamedUintVal, renamedUint(103)},
257 {"%d", "104\n", &renamedUintVal, renamedUint(104)},
258 {"%d", "105\n", &renamedInt8Val, renamedInt8(105)},
259 {"%d", "106\n", &renamedInt16Val, renamedInt16(106)},
260 {"%d", "107\n", &renamedInt32Val, renamedInt32(107)},
261 {"%d", "108\n", &renamedInt64Val, renamedInt64(108)},
262 {"%x", "6D\n", &renamedUint8Val, renamedUint8(109)},
263 {"%o", "0156\n", &renamedUint16Val, renamedUint16(110)},
264 {"%d", "111\n", &renamedUint32Val, renamedUint32(111)},
265 {"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
266 {"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
267 {"%s", "114\n", &renamedStringVal, renamedString("114")},
268 {"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
269 {"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
270 {"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
271 {"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)},
272 {"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)},
274 // Interesting formats
275 {"here is\tthe value:%d", "here is the\tvalue:118\n", &intVal, 118},
276 {"%% %%:%d", "% %:119\n", &intVal, 119},
277 {"%d%%", "42%", &intVal, 42}, // %% at end of string.
279 // Corner cases
280 {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)},
282 // Custom scanner.
283 {"%s", " sss ", &xVal, Xs("sss")},
284 {"%2s", "sssss", &xVal, Xs("ss")},
286 // Fixed bugs
287 {"%d\n", "27\n", &intVal, 27}, // ok
288 {"%d\n", "28 \n", &intVal, 28}, // was: "unexpected newline"
289 {"%v", "0", &intVal, 0}, // was: "EOF"; 0 was taken as base prefix and not counted.
290 {"%v", "0", &uintVal, uint(0)}, // was: "EOF"; 0 was taken as base prefix and not counted.
291 {"%c", " ", &uintVal, uint(' ')}, // %c must accept a blank.
292 {"%c", "\t", &uintVal, uint('\t')}, // %c must accept any space.
293 {"%c", "\n", &uintVal, uint('\n')}, // %c must accept any space.
295 // space handling
296 {"%d", "27", &intVal, 27},
297 {"%d", "27 ", &intVal, 27},
298 {"%d", " 27", &intVal, 27},
299 {"%d", " 27 ", &intVal, 27},
301 {"X%d", "X27", &intVal, 27},
302 {"X%d", "X27 ", &intVal, 27},
303 {"X%d", "X 27", &intVal, 27},
304 {"X%d", "X 27 ", &intVal, 27},
306 {"X %d", "X27", &intVal, nil}, // expected space in input to match format
307 {"X %d", "X27 ", &intVal, nil}, // expected space in input to match format
308 {"X %d", "X 27", &intVal, 27},
309 {"X %d", "X 27 ", &intVal, 27},
311 {"%dX", "27X", &intVal, 27},
312 {"%dX", "27 X", &intVal, nil}, // input does not match format
313 {"%dX", " 27X", &intVal, 27},
314 {"%dX", " 27 X", &intVal, nil}, // input does not match format
316 {"%d X", "27X", &intVal, nil}, // expected space in input to match format
317 {"%d X", "27 X", &intVal, 27},
318 {"%d X", " 27X", &intVal, nil}, // expected space in input to match format
319 {"%d X", " 27 X", &intVal, 27},
321 {"X %d X", "X27X", &intVal, nil}, // expected space in input to match format
322 {"X %d X", "X27 X", &intVal, nil}, // expected space in input to match format
323 {"X %d X", "X 27X", &intVal, nil}, // expected space in input to match format
324 {"X %d X", "X 27 X", &intVal, 27},
326 {"X %s X", "X27X", &stringVal, nil}, // expected space in input to match format
327 {"X %s X", "X27 X", &stringVal, nil}, // expected space in input to match format
328 {"X %s X", "X 27X", &stringVal, nil}, // unexpected EOF
329 {"X %s X", "X 27 X", &stringVal, "27"},
331 {"X%sX", "X27X", &stringVal, nil}, // unexpected EOF
332 {"X%sX", "X27 X", &stringVal, nil}, // input does not match format
333 {"X%sX", "X 27X", &stringVal, nil}, // unexpected EOF
334 {"X%sX", "X 27 X", &stringVal, nil}, // input does not match format
336 {"X%s", "X27", &stringVal, "27"},
337 {"X%s", "X27 ", &stringVal, "27"},
338 {"X%s", "X 27", &stringVal, "27"},
339 {"X%s", "X 27 ", &stringVal, "27"},
341 {"X%dX", "X27X", &intVal, 27},
342 {"X%dX", "X27 X", &intVal, nil}, // input does not match format
343 {"X%dX", "X 27X", &intVal, 27},
344 {"X%dX", "X 27 X", &intVal, nil}, // input does not match format
346 {"X%dX", "X27X", &intVal, 27},
347 {"X%dX", "X27X ", &intVal, 27},
348 {"X%dX", " X27X", &intVal, nil}, // input does not match format
349 {"X%dX", " X27X ", &intVal, nil}, // input does not match format
351 {"X%dX\n", "X27X", &intVal, 27},
352 {"X%dX \n", "X27X ", &intVal, 27},
353 {"X%dX\n", "X27X\n", &intVal, 27},
354 {"X%dX\n", "X27X \n", &intVal, 27},
356 {"X%dX \n", "X27X", &intVal, 27},
357 {"X%dX \n", "X27X ", &intVal, 27},
358 {"X%dX \n", "X27X\n", &intVal, 27},
359 {"X%dX \n", "X27X \n", &intVal, 27},
361 {"X%c", "X\n", &runeVal, '\n'},
362 {"X%c", "X \n", &runeVal, ' '},
363 {"X %c", "X!", &runeVal, nil}, // expected space in input to match format
364 {"X %c", "X\n", &runeVal, nil}, // newline in input does not match format
365 {"X %c", "X !", &runeVal, '!'},
366 {"X %c", "X \n", &runeVal, '\n'},
368 {" X%dX", "X27X", &intVal, nil}, // expected space in input to match format
369 {" X%dX", "X27X ", &intVal, nil}, // expected space in input to match format
370 {" X%dX", " X27X", &intVal, 27},
371 {" X%dX", " X27X ", &intVal, 27},
373 {"X%dX ", "X27X", &intVal, 27},
374 {"X%dX ", "X27X ", &intVal, 27},
375 {"X%dX ", " X27X", &intVal, nil}, // input does not match format
376 {"X%dX ", " X27X ", &intVal, nil}, // input does not match format
378 {" X%dX ", "X27X", &intVal, nil}, // expected space in input to match format
379 {" X%dX ", "X27X ", &intVal, nil}, // expected space in input to match format
380 {" X%dX ", " X27X", &intVal, 27},
381 {" X%dX ", " X27X ", &intVal, 27},
383 {"%d\nX", "27\nX", &intVal, 27},
384 {"%dX\n X", "27X\n X", &intVal, 27},
387 var overflowTests = []ScanTest{
388 {"128", &int8Val, 0},
389 {"32768", &int16Val, 0},
390 {"-129", &int8Val, 0},
391 {"-32769", &int16Val, 0},
392 {"256", &uint8Val, 0},
393 {"65536", &uint16Val, 0},
394 {"1e100", &float32Val, 0},
395 {"1e500", &float64Val, 0},
396 {"(1e100+0i)", &complex64Val, 0},
397 {"(1+1e100i)", &complex64Val, 0},
398 {"(1-1e500i)", &complex128Val, 0},
401 var truth bool
402 var i, j, k int
403 var f float64
404 var s, t string
405 var c complex128
406 var x, y Xs
407 var z IntString
408 var r1, r2, r3 rune
410 var multiTests = []ScanfMultiTest{
411 {"", "", []interface{}{}, []interface{}{}, ""},
412 {"%d", "23", args(&i), args(23), ""},
413 {"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""},
414 {"%2d%3d", "44555", args(&i, &j), args(44, 555), ""},
415 {"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""},
416 {"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""},
417 {"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
418 {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
419 {"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
420 {"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
421 {"%5s%d", " 1234567 ", args(&s, &i), args("12345", 67), ""},
422 {"%5s%d", " 12 34 567 ", args(&s, &i), args("12", 34), ""},
424 // Custom scanners.
425 {"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
426 {"%4v%s", "12abcd", args(&z, &s), args(IntString{12, "ab"}, "cd"), ""},
428 // Errors
429 {"%t", "23 18", args(&i), nil, "bad verb"},
430 {"%d %d %d", "23 18", args(&i, &j), args(23, 18), "too few operands"},
431 {"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"},
432 {"%c", "\u0100", args(&int8Val), nil, "overflow"},
433 {"X%d", "10X", args(&intVal), nil, "input does not match format"},
434 {"%d%", "42%", args(&intVal), args(42), "missing verb: % at end of format string"},
435 {"%d% ", "42%", args(&intVal), args(42), "too few operands for format '% '"}, // Slightly odd error, but correct.
437 // Bad UTF-8: should see every byte.
438 {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
440 // Fixed bugs
441 {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""},
444 var readers = []struct {
445 name string
446 f func(string) io.Reader
448 {"StringReader", func(s string) io.Reader {
449 return strings.NewReader(s)
451 {"ReaderOnly", func(s string) io.Reader {
452 return struct{ io.Reader }{strings.NewReader(s)}
454 {"OneByteReader", func(s string) io.Reader {
455 return iotest.OneByteReader(strings.NewReader(s))
457 {"DataErrReader", func(s string) io.Reader {
458 return iotest.DataErrReader(strings.NewReader(s))
462 func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a ...interface{}) (int, error)) {
463 for _, test := range scanTests {
464 r := f(test.text)
465 n, err := scan(r, test.in)
466 if err != nil {
467 m := ""
468 if n > 0 {
469 m = Sprintf(" (%d fields ok)", n)
471 t.Errorf("got error scanning %q: %s%s", test.text, err, m)
472 continue
474 if n != 1 {
475 t.Errorf("count error on entry %q: got %d", test.text, n)
476 continue
478 // The incoming value may be a pointer
479 v := reflect.ValueOf(test.in)
480 if p := v; p.Kind() == reflect.Ptr {
481 v = p.Elem()
483 val := v.Interface()
484 if !reflect.DeepEqual(val, test.out) {
485 t.Errorf("scanning %q: expected %#v got %#v, type %T", test.text, test.out, val, val)
490 func TestScan(t *testing.T) {
491 for _, r := range readers {
492 t.Run(r.name, func(t *testing.T) {
493 testScan(t, r.f, Fscan)
498 func TestScanln(t *testing.T) {
499 for _, r := range readers {
500 t.Run(r.name, func(t *testing.T) {
501 testScan(t, r.f, Fscanln)
506 func TestScanf(t *testing.T) {
507 for _, test := range scanfTests {
508 n, err := Sscanf(test.text, test.format, test.in)
509 if err != nil {
510 if test.out != nil {
511 t.Errorf("Sscanf(%q, %q): unexpected error: %v", test.text, test.format, err)
513 continue
515 if test.out == nil {
516 t.Errorf("Sscanf(%q, %q): unexpected success", test.text, test.format)
517 continue
519 if n != 1 {
520 t.Errorf("Sscanf(%q, %q): parsed %d field, want 1", test.text, test.format, n)
521 continue
523 // The incoming value may be a pointer
524 v := reflect.ValueOf(test.in)
525 if p := v; p.Kind() == reflect.Ptr {
526 v = p.Elem()
528 val := v.Interface()
529 if !reflect.DeepEqual(val, test.out) {
530 t.Errorf("Sscanf(%q, %q): parsed value %T(%#v), want %T(%#v)", test.text, test.format, val, val, test.out, test.out)
535 func TestScanOverflow(t *testing.T) {
536 // different machines and different types report errors with different strings.
537 re := regexp.MustCompile("overflow|too large|out of range|not representable")
538 for _, test := range overflowTests {
539 _, err := Sscan(test.text, test.in)
540 if err == nil {
541 t.Errorf("expected overflow scanning %q", test.text)
542 continue
544 if !re.MatchString(err.Error()) {
545 t.Errorf("expected overflow error scanning %q: %s", test.text, err)
550 func verifyNaN(str string, t *testing.T) {
551 var f float64
552 var f32 float32
553 var f64 float64
554 text := str + " " + str + " " + str
555 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
556 if err != nil {
557 t.Errorf("got error scanning %q: %s", text, err)
559 if n != 3 {
560 t.Errorf("count error scanning %q: got %d", text, n)
562 if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) {
563 t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64)
567 func TestNaN(t *testing.T) {
568 for _, s := range []string{"nan", "NAN", "NaN"} {
569 verifyNaN(s, t)
573 func verifyInf(str string, t *testing.T) {
574 var f float64
575 var f32 float32
576 var f64 float64
577 text := str + " " + str + " " + str
578 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
579 if err != nil {
580 t.Errorf("got error scanning %q: %s", text, err)
582 if n != 3 {
583 t.Errorf("count error scanning %q: got %d", text, n)
585 sign := 1
586 if str[0] == '-' {
587 sign = -1
589 if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) {
590 t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64)
594 func TestInf(t *testing.T) {
595 for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} {
596 verifyInf(s, t)
600 func testScanfMulti(t *testing.T, f func(string) io.Reader) {
601 sliceType := reflect.TypeOf(make([]interface{}, 1))
602 for _, test := range multiTests {
603 r := f(test.text)
604 n, err := Fscanf(r, test.format, test.in...)
605 if err != nil {
606 if test.err == "" {
607 t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err)
608 } else if !strings.Contains(err.Error(), test.err) {
609 t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err)
611 continue
613 if test.err != "" {
614 t.Errorf("expected error %q error scanning (%q, %q)", test.err, test.format, test.text)
616 if n != len(test.out) {
617 t.Errorf("count error on entry (%q, %q): expected %d got %d", test.format, test.text, len(test.out), n)
618 continue
620 // Convert the slice of pointers into a slice of values
621 resultVal := reflect.MakeSlice(sliceType, n, n)
622 for i := 0; i < n; i++ {
623 v := reflect.ValueOf(test.in[i]).Elem()
624 resultVal.Index(i).Set(v)
626 result := resultVal.Interface()
627 if !reflect.DeepEqual(result, test.out) {
628 t.Errorf("scanning (%q, %q): expected %#v got %#v", test.format, test.text, test.out, result)
633 func TestScanfMulti(t *testing.T) {
634 for _, r := range readers {
635 t.Run(r.name, func(t *testing.T) {
636 testScanfMulti(t, r.f)
641 func TestScanMultiple(t *testing.T) {
642 var a int
643 var s string
644 n, err := Sscan("123abc", &a, &s)
645 if n != 2 {
646 t.Errorf("Sscan count error: expected 2: got %d", n)
648 if err != nil {
649 t.Errorf("Sscan expected no error; got %s", err)
651 if a != 123 || s != "abc" {
652 t.Errorf("Sscan wrong values: got (%d %q) expected (123 \"abc\")", a, s)
654 n, err = Sscan("asdf", &s, &a)
655 if n != 1 {
656 t.Errorf("Sscan count error: expected 1: got %d", n)
658 if err == nil {
659 t.Errorf("Sscan expected error; got none: %s", err)
661 if s != "asdf" {
662 t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s)
666 // Empty strings are not valid input when scanning a string.
667 func TestScanEmpty(t *testing.T) {
668 var s1, s2 string
669 n, err := Sscan("abc", &s1, &s2)
670 if n != 1 {
671 t.Errorf("Sscan count error: expected 1: got %d", n)
673 if err == nil {
674 t.Error("Sscan <one item> expected error; got none")
676 if s1 != "abc" {
677 t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1)
679 n, err = Sscan("", &s1, &s2)
680 if n != 0 {
681 t.Errorf("Sscan count error: expected 0: got %d", n)
683 if err == nil {
684 t.Error("Sscan <empty> expected error; got none")
686 // Quoted empty string is OK.
687 n, err = Sscanf(`""`, "%q", &s1)
688 if n != 1 {
689 t.Errorf("Sscanf count error: expected 1: got %d", n)
691 if err != nil {
692 t.Errorf("Sscanf <empty> expected no error with quoted string; got %s", err)
696 func TestScanNotPointer(t *testing.T) {
697 r := strings.NewReader("1")
698 var a int
699 _, err := Fscan(r, a)
700 if err == nil {
701 t.Error("expected error scanning non-pointer")
702 } else if !strings.Contains(err.Error(), "pointer") {
703 t.Errorf("expected pointer error scanning non-pointer, got: %s", err)
707 func TestScanlnNoNewline(t *testing.T) {
708 var a int
709 _, err := Sscanln("1 x\n", &a)
710 if err == nil {
711 t.Error("expected error scanning string missing newline")
712 } else if !strings.Contains(err.Error(), "newline") {
713 t.Errorf("expected newline error scanning string missing newline, got: %s", err)
717 func TestScanlnWithMiddleNewline(t *testing.T) {
718 r := strings.NewReader("123\n456\n")
719 var a, b int
720 _, err := Fscanln(r, &a, &b)
721 if err == nil {
722 t.Error("expected error scanning string with extra newline")
723 } else if !strings.Contains(err.Error(), "newline") {
724 t.Errorf("expected newline error scanning string with extra newline, got: %s", err)
728 // eofCounter is a special Reader that counts reads at end of file.
729 type eofCounter struct {
730 reader *strings.Reader
731 eofCount int
734 func (ec *eofCounter) Read(b []byte) (n int, err error) {
735 n, err = ec.reader.Read(b)
736 if n == 0 {
737 ec.eofCount++
739 return
742 // TestEOF verifies that when we scan, we see at most EOF once per call to a
743 // Scan function, and then only when it's really an EOF.
744 func TestEOF(t *testing.T) {
745 ec := &eofCounter{strings.NewReader("123\n"), 0}
746 var a int
747 n, err := Fscanln(ec, &a)
748 if err != nil {
749 t.Error("unexpected error", err)
751 if n != 1 {
752 t.Error("expected to scan one item, got", n)
754 if ec.eofCount != 0 {
755 t.Error("expected zero EOFs", ec.eofCount)
756 ec.eofCount = 0 // reset for next test
758 n, err = Fscanln(ec, &a)
759 if err == nil {
760 t.Error("expected error scanning empty string")
762 if n != 0 {
763 t.Error("expected to scan zero items, got", n)
765 if ec.eofCount != 1 {
766 t.Error("expected one EOF, got", ec.eofCount)
770 // TestEOFAtEndOfInput verifies that we see an EOF error if we run out of input.
771 // This was a buglet: we used to get "expected integer".
772 func TestEOFAtEndOfInput(t *testing.T) {
773 var i, j int
774 n, err := Sscanf("23", "%d %d", &i, &j)
775 if n != 1 || i != 23 {
776 t.Errorf("Sscanf expected one value of 23; got %d %d", n, i)
778 if err != io.EOF {
779 t.Errorf("Sscanf expected EOF; got %q", err)
781 n, err = Sscan("234", &i, &j)
782 if n != 1 || i != 234 {
783 t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
785 if err != io.EOF {
786 t.Errorf("Sscan expected EOF; got %q", err)
788 // Trailing space is tougher.
789 n, err = Sscan("234 ", &i, &j)
790 if n != 1 || i != 234 {
791 t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
793 if err != io.EOF {
794 t.Errorf("Sscan expected EOF; got %q", err)
798 var eofTests = []struct {
799 format string
800 v interface{}
802 {"%s", &stringVal},
803 {"%q", &stringVal},
804 {"%x", &stringVal},
805 {"%v", &stringVal},
806 {"%v", &bytesVal},
807 {"%v", &intVal},
808 {"%v", &uintVal},
809 {"%v", &boolVal},
810 {"%v", &float32Val},
811 {"%v", &complex64Val},
812 {"%v", &renamedStringVal},
813 {"%v", &renamedBytesVal},
814 {"%v", &renamedIntVal},
815 {"%v", &renamedUintVal},
816 {"%v", &renamedBoolVal},
817 {"%v", &renamedFloat32Val},
818 {"%v", &renamedComplex64Val},
821 func TestEOFAllTypes(t *testing.T) {
822 for i, test := range eofTests {
823 if _, err := Sscanf("", test.format, test.v); err != io.EOF {
824 t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err)
826 if _, err := Sscanf(" ", test.format, test.v); err != io.EOF {
827 t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err)
832 // TestUnreadRuneWithBufio verifies that, at least when using bufio, successive
833 // calls to Fscan do not lose runes.
834 func TestUnreadRuneWithBufio(t *testing.T) {
835 r := bufio.NewReader(strings.NewReader("123αb"))
836 var i int
837 var a string
838 n, err := Fscanf(r, "%d", &i)
839 if n != 1 || err != nil {
840 t.Errorf("reading int expected one item, no errors; got %d %q", n, err)
842 if i != 123 {
843 t.Errorf("expected 123; got %d", i)
845 n, err = Fscanf(r, "%s", &a)
846 if n != 1 || err != nil {
847 t.Errorf("reading string expected one item, no errors; got %d %q", n, err)
849 if a != "αb" {
850 t.Errorf("expected αb; got %q", a)
854 type TwoLines string
856 // Scan attempts to read two lines into the object. Scanln should prevent this
857 // because it stops at newline; Scan and Scanf should be fine.
858 func (t *TwoLines) Scan(state ScanState, verb rune) error {
859 chars := make([]rune, 0, 100)
860 for nlCount := 0; nlCount < 2; {
861 c, _, err := state.ReadRune()
862 if err != nil {
863 return err
865 chars = append(chars, c)
866 if c == '\n' {
867 nlCount++
870 *t = TwoLines(string(chars))
871 return nil
874 func TestMultiLine(t *testing.T) {
875 input := "abc\ndef\n"
876 // Sscan should work
877 var tscan TwoLines
878 n, err := Sscan(input, &tscan)
879 if n != 1 {
880 t.Errorf("Sscan: expected 1 item; got %d", n)
882 if err != nil {
883 t.Errorf("Sscan: expected no error; got %s", err)
885 if string(tscan) != input {
886 t.Errorf("Sscan: expected %q; got %q", input, tscan)
888 // Sscanf should work
889 var tscanf TwoLines
890 n, err = Sscanf(input, "%s", &tscanf)
891 if n != 1 {
892 t.Errorf("Sscanf: expected 1 item; got %d", n)
894 if err != nil {
895 t.Errorf("Sscanf: expected no error; got %s", err)
897 if string(tscanf) != input {
898 t.Errorf("Sscanf: expected %q; got %q", input, tscanf)
900 // Sscanln should not work
901 var tscanln TwoLines
902 n, err = Sscanln(input, &tscanln)
903 if n != 0 {
904 t.Errorf("Sscanln: expected 0 items; got %d: %q", n, tscanln)
906 if err == nil {
907 t.Error("Sscanln: expected error; got none")
908 } else if err != io.ErrUnexpectedEOF {
909 t.Errorf("Sscanln: expected io.ErrUnexpectedEOF (ha!); got %s", err)
913 // TestLineByLineFscanf tests that Fscanf does not read past newline. Issue
914 // 3481.
915 func TestLineByLineFscanf(t *testing.T) {
916 r := struct{ io.Reader }{strings.NewReader("1\n2\n")}
917 var i, j int
918 n, err := Fscanf(r, "%v\n", &i)
919 if n != 1 || err != nil {
920 t.Fatalf("first read: %d %q", n, err)
922 n, err = Fscanf(r, "%v\n", &j)
923 if n != 1 || err != nil {
924 t.Fatalf("second read: %d %q", n, err)
926 if i != 1 || j != 2 {
927 t.Errorf("wrong values; wanted 1 2 got %d %d", i, j)
931 // TestScanStateCount verifies the correct byte count is returned. Issue 8512.
933 // runeScanner implements the Scanner interface for TestScanStateCount.
934 type runeScanner struct {
935 rune rune
936 size int
939 func (rs *runeScanner) Scan(state ScanState, verb rune) error {
940 r, size, err := state.ReadRune()
941 rs.rune = r
942 rs.size = size
943 return err
946 func TestScanStateCount(t *testing.T) {
947 var a, b, c runeScanner
948 n, err := Sscanf("12âž‚", "%c%c%c", &a, &b, &c)
949 if err != nil {
950 t.Fatal(err)
952 if n != 3 {
953 t.Fatalf("expected 3 items consumed, got %d", n)
955 if a.rune != '1' || b.rune != '2' || c.rune != 'âž‚' {
956 t.Errorf("bad scan rune: %q %q %q should be '1' '2' 'âž‚'", a.rune, b.rune, c.rune)
958 if a.size != 1 || b.size != 1 || c.size != 3 {
959 t.Errorf("bad scan size: %q %q %q should be 1 1 3", a.size, b.size, c.size)
963 // RecursiveInt accepts a string matching %d.%d.%d....
964 // and parses it into a linked list.
965 // It allows us to benchmark recursive descent style scanners.
966 type RecursiveInt struct {
967 i int
968 next *RecursiveInt
971 func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
972 _, err = Fscan(state, &r.i)
973 if err != nil {
974 return
976 next := new(RecursiveInt)
977 _, err = Fscanf(state, ".%v", next)
978 if err != nil {
979 if err == io.ErrUnexpectedEOF {
980 err = nil
982 return
984 r.next = next
985 return
988 // scanInts performs the same scanning task as RecursiveInt.Scan
989 // but without recurring through scanner, so we can compare
990 // performance more directly.
991 func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) {
992 r.next = nil
993 _, err = Fscan(b, &r.i)
994 if err != nil {
995 return
997 c, _, err := b.ReadRune()
998 if err != nil {
999 if err == io.EOF {
1000 err = nil
1002 return
1004 if c != '.' {
1005 return
1007 next := new(RecursiveInt)
1008 err = scanInts(next, b)
1009 if err == nil {
1010 r.next = next
1012 return
1015 func makeInts(n int) []byte {
1016 var buf bytes.Buffer
1017 Fprintf(&buf, "1")
1018 for i := 1; i < n; i++ {
1019 Fprintf(&buf, ".%d", i+1)
1021 return buf.Bytes()
1024 func TestScanInts(t *testing.T) {
1025 testScanInts(t, scanInts)
1026 testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err error) {
1027 _, err = Fscan(b, r)
1028 return
1032 // 800 is small enough to not overflow the stack when using gccgo on a
1033 // platform that does not support split stack.
1034 const intCount = 800
1036 func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) error) {
1037 r := new(RecursiveInt)
1038 ints := makeInts(intCount)
1039 buf := bytes.NewBuffer(ints)
1040 err := scan(r, buf)
1041 if err != nil {
1042 t.Error("unexpected error", err)
1044 i := 1
1045 for ; r != nil; r = r.next {
1046 if r.i != i {
1047 t.Fatalf("bad scan: expected %d got %d", i, r.i)
1051 if i-1 != intCount {
1052 t.Fatalf("bad scan count: expected %d got %d", intCount, i-1)
1056 func BenchmarkScanInts(b *testing.B) {
1057 b.ResetTimer()
1058 ints := makeInts(intCount)
1059 var r RecursiveInt
1060 for i := b.N - 1; i >= 0; i-- {
1061 buf := bytes.NewBuffer(ints)
1062 b.StartTimer()
1063 scanInts(&r, buf)
1064 b.StopTimer()
1068 func BenchmarkScanRecursiveInt(b *testing.B) {
1069 b.ResetTimer()
1070 ints := makeInts(intCount)
1071 var r RecursiveInt
1072 for i := b.N - 1; i >= 0; i-- {
1073 buf := bytes.NewBuffer(ints)
1074 b.StartTimer()
1075 Fscan(buf, &r)
1076 b.StopTimer()
1080 func BenchmarkScanRecursiveIntReaderWrapper(b *testing.B) {
1081 b.ResetTimer()
1082 ints := makeInts(intCount)
1083 var r RecursiveInt
1084 for i := b.N - 1; i >= 0; i-- {
1085 buf := struct{ io.Reader }{strings.NewReader(string(ints))}
1086 b.StartTimer()
1087 Fscan(buf, &r)
1088 b.StopTimer()
1092 // Issue 9124.
1093 // %x on bytes couldn't handle non-space bytes terminating the scan.
1094 func TestHexBytes(t *testing.T) {
1095 var a, b []byte
1096 n, err := Sscanf("00010203", "%x", &a)
1097 if n != 1 || err != nil {
1098 t.Errorf("simple: got count, err = %d, %v; expected 1, nil", n, err)
1100 check := func(msg string, x []byte) {
1101 if len(x) != 4 {
1102 t.Errorf("%s: bad length %d", msg, len(x))
1104 for i, b := range x {
1105 if int(b) != i {
1106 t.Errorf("%s: bad x[%d] = %x", msg, i, x[i])
1110 check("simple", a)
1111 a = nil
1113 n, err = Sscanf("00010203 00010203", "%x %x", &a, &b)
1114 if n != 2 || err != nil {
1115 t.Errorf("simple pair: got count, err = %d, %v; expected 2, nil", n, err)
1117 check("simple pair a", a)
1118 check("simple pair b", b)
1119 a = nil
1120 b = nil
1122 n, err = Sscanf("00010203:", "%x", &a)
1123 if n != 1 || err != nil {
1124 t.Errorf("colon: got count, err = %d, %v; expected 1, nil", n, err)
1126 check("colon", a)
1127 a = nil
1129 n, err = Sscanf("00010203:00010203", "%x:%x", &a, &b)
1130 if n != 2 || err != nil {
1131 t.Errorf("colon pair: got count, err = %d, %v; expected 2, nil", n, err)
1133 check("colon pair a", a)
1134 check("colon pair b", b)
1135 a = nil
1136 b = nil
1138 // This one fails because there is a hex byte after the data,
1139 // that is, an odd number of hex input bytes.
1140 n, err = Sscanf("000102034:", "%x", &a)
1141 if n != 0 || err == nil {
1142 t.Errorf("odd count: got count, err = %d, %v; expected 0, error", n, err)
1146 func TestScanNewlinesAreSpaces(t *testing.T) {
1147 var a, b int
1148 var tests = []struct {
1149 name string
1150 text string
1151 count int
1153 {"newlines", "1\n2\n", 2},
1154 {"no final newline", "1\n2", 2},
1155 {"newlines with spaces ", "1 \n 2 \n", 2},
1156 {"no final newline with spaces", "1 \n 2", 2},
1158 for _, test := range tests {
1159 n, err := Sscan(test.text, &a, &b)
1160 if n != test.count {
1161 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n)
1163 if err != nil {
1164 t.Errorf("%s: unexpected error: %s", test.name, err)
1169 func TestScanlnNewlinesTerminate(t *testing.T) {
1170 var a, b int
1171 var tests = []struct {
1172 name string
1173 text string
1174 count int
1175 ok bool
1177 {"one line one item", "1\n", 1, false},
1178 {"one line two items with spaces ", " 1 2 \n", 2, true},
1179 {"one line two items no newline", " 1 2", 2, true},
1180 {"two lines two items", "1\n2\n", 1, false},
1182 for _, test := range tests {
1183 n, err := Sscanln(test.text, &a, &b)
1184 if n != test.count {
1185 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n)
1187 if test.ok && err != nil {
1188 t.Errorf("%s: unexpected error: %s", test.name, err)
1190 if !test.ok && err == nil {
1191 t.Errorf("%s: expected error; got none", test.name)
1196 func TestScanfNewlineMatchFormat(t *testing.T) {
1197 var a, b int
1198 var tests = []struct {
1199 name string
1200 text string
1201 format string
1202 count int
1203 ok bool
1205 {"newline in both", "1\n2", "%d\n%d\n", 2, true},
1206 {"newline in input", "1\n2", "%d %d", 1, false},
1207 {"space-newline in input", "1 \n2", "%d %d", 1, false},
1208 {"newline in format", "1 2", "%d\n%d", 1, false},
1209 {"space-newline in format", "1 2", "%d \n%d", 1, false},
1210 {"space-newline in both", "1 \n2", "%d \n%d", 2, true},
1211 {"extra space in format", "1\n2", "%d\n %d", 2, true},
1212 {"two extra spaces in format", "1\n2", "%d \n %d", 2, true},
1213 {"space vs newline 0000", "1\n2", "%d\n%d", 2, true},
1214 {"space vs newline 0001", "1\n2", "%d\n %d", 2, true},
1215 {"space vs newline 0010", "1\n2", "%d \n%d", 2, true},
1216 {"space vs newline 0011", "1\n2", "%d \n %d", 2, true},
1217 {"space vs newline 0100", "1\n 2", "%d\n%d", 2, true},
1218 {"space vs newline 0101", "1\n 2", "%d\n%d ", 2, true},
1219 {"space vs newline 0110", "1\n 2", "%d \n%d", 2, true},
1220 {"space vs newline 0111", "1\n 2", "%d \n %d", 2, true},
1221 {"space vs newline 1000", "1 \n2", "%d\n%d", 2, true},
1222 {"space vs newline 1001", "1 \n2", "%d\n %d", 2, true},
1223 {"space vs newline 1010", "1 \n2", "%d \n%d", 2, true},
1224 {"space vs newline 1011", "1 \n2", "%d \n %d", 2, true},
1225 {"space vs newline 1100", "1 \n 2", "%d\n%d", 2, true},
1226 {"space vs newline 1101", "1 \n 2", "%d\n %d", 2, true},
1227 {"space vs newline 1110", "1 \n 2", "%d \n%d", 2, true},
1228 {"space vs newline 1111", "1 \n 2", "%d \n %d", 2, true},
1229 {"space vs newline no-percent 0000", "1\n2", "1\n2", 0, true},
1230 {"space vs newline no-percent 0001", "1\n2", "1\n 2", 0, true},
1231 {"space vs newline no-percent 0010", "1\n2", "1 \n2", 0, true},
1232 {"space vs newline no-percent 0011", "1\n2", "1 \n 2", 0, true},
1233 {"space vs newline no-percent 0100", "1\n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
1234 {"space vs newline no-percent 0101", "1\n 2", "1\n2 ", 0, false}, // fails: space after nl in input but not pattern
1235 {"space vs newline no-percent 0110", "1\n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
1236 {"space vs newline no-percent 0111", "1\n 2", "1 \n 2", 0, true},
1237 {"space vs newline no-percent 1000", "1 \n2", "1\n2", 0, true},
1238 {"space vs newline no-percent 1001", "1 \n2", "1\n 2", 0, true},
1239 {"space vs newline no-percent 1010", "1 \n2", "1 \n2", 0, true},
1240 {"space vs newline no-percent 1011", "1 \n2", "1 \n 2", 0, true},
1241 {"space vs newline no-percent 1100", "1 \n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
1242 {"space vs newline no-percent 1101", "1 \n 2", "1\n 2", 0, true},
1243 {"space vs newline no-percent 1110", "1 \n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
1244 {"space vs newline no-percent 1111", "1 \n 2", "1 \n 2", 0, true},
1246 for _, test := range tests {
1247 var n int
1248 var err error
1249 if strings.Contains(test.format, "%") {
1250 n, err = Sscanf(test.text, test.format, &a, &b)
1251 } else {
1252 n, err = Sscanf(test.text, test.format)
1254 if n != test.count {
1255 t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n)
1257 if test.ok && err != nil {
1258 t.Errorf("%s: unexpected error: %s", test.name, err)
1260 if !test.ok && err == nil {
1261 t.Errorf("%s: expected error; got none", test.name)
1266 // Test for issue 12090: Was unreading at EOF, double-scanning a byte.
1268 type hexBytes [2]byte
1270 func (h *hexBytes) Scan(ss ScanState, verb rune) error {
1271 var b []byte
1272 _, err := Fscanf(ss, "%4x", &b)
1273 if err != nil {
1274 panic(err) // Really shouldn't happen.
1276 copy((*h)[:], b)
1277 return err
1280 func TestHexByte(t *testing.T) {
1281 var h hexBytes
1282 n, err := Sscanln("0123\n", &h)
1283 if err != nil {
1284 t.Fatal(err)
1286 if n != 1 {
1287 t.Fatalf("expected 1 item; scanned %d", n)
1289 if h[0] != 0x01 || h[1] != 0x23 {
1290 t.Fatalf("expected 0123 got %x", h)