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.
21 type ScanTest struct {
27 type ScanfTest struct {
34 type ScanfMultiTest struct {
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 type FloatTest struct {
88 // Xs accepts any non-empty run of the verb character
91 func (x *Xs) Scan(state ScanState, verb rune) error {
92 tok, err := state.Token(true, func(r rune) bool { return r == verb })
97 if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) {
98 return errors.New("syntax error for xs")
106 // IntString accepts an integer followed immediately by a string.
107 // It tests the embedding of a scan within a scan.
108 type IntString struct {
113 func (s *IntString) Scan(state ScanState, verb rune) error {
114 if _, err := Fscan(state, &s.i); err != nil {
118 tok, err := state.Token(true, nil)
126 var intStringVal IntString
128 // myStringReader implements Read but not ReadRune, allowing us to test our readRune wrapper
129 // type that creates something that can read runes given only Read().
130 type myStringReader struct {
134 func (s *myStringReader) Read(p []byte) (n int, err error) {
138 func newReader(s string) *myStringReader {
139 return &myStringReader{strings.NewReader(s)}
142 var scanTests = []ScanTest{
144 {"T\n", &boolVal, true}, // boolean test vals toggle to be sure they are written
145 {"F\n", &boolVal, false}, // restored to zero value
146 {"21\n", &intVal, 21},
148 {"000\n", &intVal, 0},
149 {"0x10\n", &intVal, 0x10},
150 {"-0x10\n", &intVal, -0x10},
151 {"0377\n", &intVal, 0377},
152 {"-0377\n", &intVal, -0377},
153 {"0\n", &uintVal, uint(0)},
154 {"000\n", &uintVal, uint(0)},
155 {"0x10\n", &uintVal, uint(0x10)},
156 {"0377\n", &uintVal, uint(0377)},
157 {"22\n", &int8Val, int8(22)},
158 {"23\n", &int16Val, int16(23)},
159 {"24\n", &int32Val, int32(24)},
160 {"25\n", &int64Val, int64(25)},
161 {"127\n", &int8Val, int8(127)},
162 {"-21\n", &intVal, -21},
163 {"-22\n", &int8Val, int8(-22)},
164 {"-23\n", &int16Val, int16(-23)},
165 {"-24\n", &int32Val, int32(-24)},
166 {"-25\n", &int64Val, int64(-25)},
167 {"-128\n", &int8Val, int8(-128)},
168 {"+21\n", &intVal, +21},
169 {"+22\n", &int8Val, int8(+22)},
170 {"+23\n", &int16Val, int16(+23)},
171 {"+24\n", &int32Val, int32(+24)},
172 {"+25\n", &int64Val, int64(+25)},
173 {"+127\n", &int8Val, int8(+127)},
174 {"26\n", &uintVal, uint(26)},
175 {"27\n", &uint8Val, uint8(27)},
176 {"28\n", &uint16Val, uint16(28)},
177 {"29\n", &uint32Val, uint32(29)},
178 {"30\n", &uint64Val, uint64(30)},
179 {"255\n", &uint8Val, uint8(255)},
180 {"32767\n", &int16Val, int16(32767)},
181 {"2.3\n", &float64Val, 2.3},
182 {"2.3e1\n", &float32Val, float32(2.3e1)},
183 {"2.3e2\n", &float64Val, 2.3e2},
184 {"2.3p2\n", &float64Val, 2.3 * 4},
185 {"2.3p+2\n", &float64Val, 2.3 * 4},
186 {"2.3p+66\n", &float64Val, 2.3 * (1 << 32) * (1 << 32) * 4},
187 {"2.3p-66\n", &float64Val, 2.3 / ((1 << 32) * (1 << 32) * 4)},
188 {"2.35\n", &stringVal, "2.35"},
189 {"2345678\n", &bytesVal, []byte("2345678")},
190 {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i},
191 {"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
192 {"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
193 {"hello\n", &stringVal, "hello"},
196 {"true\n", &renamedBoolVal, renamedBool(true)},
197 {"F\n", &renamedBoolVal, renamedBool(false)},
198 {"101\n", &renamedIntVal, renamedInt(101)},
199 {"102\n", &renamedIntVal, renamedInt(102)},
200 {"103\n", &renamedUintVal, renamedUint(103)},
201 {"104\n", &renamedUintVal, renamedUint(104)},
202 {"105\n", &renamedInt8Val, renamedInt8(105)},
203 {"106\n", &renamedInt16Val, renamedInt16(106)},
204 {"107\n", &renamedInt32Val, renamedInt32(107)},
205 {"108\n", &renamedInt64Val, renamedInt64(108)},
206 {"109\n", &renamedUint8Val, renamedUint8(109)},
207 {"110\n", &renamedUint16Val, renamedUint16(110)},
208 {"111\n", &renamedUint32Val, renamedUint32(111)},
209 {"112\n", &renamedUint64Val, renamedUint64(112)},
210 {"113\n", &renamedUintptrVal, renamedUintptr(113)},
211 {"114\n", &renamedStringVal, renamedString("114")},
212 {"115\n", &renamedBytesVal, renamedBytes([]byte("115"))},
215 {" vvv ", &xVal, Xs("vvv")},
216 {" 1234hello", &intStringVal, IntString{1234, "hello"}},
219 {"2147483648\n", &int64Val, int64(2147483648)}, // was: integer overflow
222 var scanfTests = []ScanfTest{
223 {"%v", "TRUE\n", &boolVal, true},
224 {"%t", "false\n", &boolVal, false},
225 {"%v", "-71\n", &intVal, -71},
226 {"%v", "0377\n", &intVal, 0377},
227 {"%v", "0x44\n", &intVal, 0x44},
228 {"%d", "72\n", &intVal, 72},
229 {"%c", "a\n", &runeVal, 'a'},
230 {"%c", "\u5072\n", &runeVal, '\u5072'},
231 {"%c", "\u1234\n", &runeVal, '\u1234'},
232 {"%d", "73\n", &int8Val, int8(73)},
233 {"%d", "+74\n", &int16Val, int16(74)},
234 {"%d", "75\n", &int32Val, int32(75)},
235 {"%d", "76\n", &int64Val, int64(76)},
236 {"%b", "1001001\n", &intVal, 73},
237 {"%o", "075\n", &intVal, 075},
238 {"%x", "a75\n", &intVal, 0xa75},
239 {"%v", "71\n", &uintVal, uint(71)},
240 {"%d", "72\n", &uintVal, uint(72)},
241 {"%d", "73\n", &uint8Val, uint8(73)},
242 {"%d", "74\n", &uint16Val, uint16(74)},
243 {"%d", "75\n", &uint32Val, uint32(75)},
244 {"%d", "76\n", &uint64Val, uint64(76)},
245 {"%b", "1001001\n", &uintVal, uint(73)},
246 {"%o", "075\n", &uintVal, uint(075)},
247 {"%x", "a75\n", &uintVal, uint(0xa75)},
248 {"%x", "A75\n", &uintVal, uint(0xa75)},
249 {"%U", "U+1234\n", &intVal, int(0x1234)},
250 {"%U", "U+4567\n", &uintVal, uint(0x4567)},
253 {"%s", "using-%s\n", &stringVal, "using-%s"},
254 {"%x", "7573696e672d2578\n", &stringVal, "using-%x"},
255 {"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
256 {"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
259 {"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
260 {"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
261 {"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
262 {"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
265 {"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
266 {"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
267 {"%v", "101\n", &renamedIntVal, renamedInt(101)},
268 {"%c", "\u0101\n", &renamedIntVal, renamedInt('\u0101')},
269 {"%o", "0146\n", &renamedIntVal, renamedInt(102)},
270 {"%v", "103\n", &renamedUintVal, renamedUint(103)},
271 {"%d", "104\n", &renamedUintVal, renamedUint(104)},
272 {"%d", "105\n", &renamedInt8Val, renamedInt8(105)},
273 {"%d", "106\n", &renamedInt16Val, renamedInt16(106)},
274 {"%d", "107\n", &renamedInt32Val, renamedInt32(107)},
275 {"%d", "108\n", &renamedInt64Val, renamedInt64(108)},
276 {"%x", "6D\n", &renamedUint8Val, renamedUint8(109)},
277 {"%o", "0156\n", &renamedUint16Val, renamedUint16(110)},
278 {"%d", "111\n", &renamedUint32Val, renamedUint32(111)},
279 {"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
280 {"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
281 {"%s", "114\n", &renamedStringVal, renamedString("114")},
282 {"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
283 {"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
284 {"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
285 {"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)},
286 {"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)},
288 // Interesting formats
289 {"here is\tthe value:%d", "here is the\tvalue:118\n", &intVal, 118},
290 {"%% %%:%d", "% %:119\n", &intVal, 119},
293 {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)},
296 {"%s", " sss ", &xVal, Xs("sss")},
297 {"%2s", "sssss", &xVal, Xs("ss")},
300 {"%d\n", "27\n", &intVal, 27}, // ok
301 {"%d\n", "28 \n", &intVal, 28}, // was: "unexpected newline"
302 {"%v", "0", &intVal, 0}, // was: "EOF"; 0 was taken as base prefix and not counted.
303 {"%v", "0", &uintVal, uint(0)}, // was: "EOF"; 0 was taken as base prefix and not counted.
306 var overflowTests = []ScanTest{
307 {"128", &int8Val, 0},
308 {"32768", &int16Val, 0},
309 {"-129", &int8Val, 0},
310 {"-32769", &int16Val, 0},
311 {"256", &uint8Val, 0},
312 {"65536", &uint16Val, 0},
313 {"1e100", &float32Val, 0},
314 {"1e500", &float64Val, 0},
315 {"(1e100+0i)", &complex64Val, 0},
316 {"(1+1e100i)", &complex64Val, 0},
317 {"(1-1e500i)", &complex128Val, 0},
329 var multiTests = []ScanfMultiTest{
330 {"", "", []interface{}{}, []interface{}{}, ""},
331 {"%d", "23", args(&i), args(23), ""},
332 {"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""},
333 {"%2d%3d", "44555", args(&i, &j), args(44, 555), ""},
334 {"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""},
335 {"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""},
336 {"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
337 {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
338 {"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
339 {"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
342 {"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
343 {"%4v%s", "12abcd", args(&z, &s), args(IntString{12, "ab"}, "cd"), ""},
346 {"%t", "23 18", args(&i), nil, "bad verb"},
347 {"%d %d %d", "23 18", args(&i, &j), args(23, 18), "too few operands"},
348 {"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"},
349 {"%c", "\u0100", args(&int8Val), nil, "overflow"},
350 {"X%d", "10X", args(&intVal), nil, "input does not match format"},
352 // Bad UTF-8: should see every byte.
353 {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
356 {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""},
359 func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {
360 for _, test := range scanTests {
362 if name == "StringReader" {
363 r = strings.NewReader(test.text)
365 r = newReader(test.text)
367 n, err := scan(r, test.in)
371 m = Sprintf(" (%d fields ok)", n)
373 t.Errorf("%s got error scanning %q: %s%s", name, test.text, err, m)
377 t.Errorf("%s count error on entry %q: got %d", name, test.text, n)
380 // The incoming value may be a pointer
381 v := reflect.ValueOf(test.in)
382 if p := v; p.Kind() == reflect.Ptr {
386 if !reflect.DeepEqual(val, test.out) {
387 t.Errorf("%s scanning %q: expected %#v got %#v, type %T", name, test.text, test.out, val, val)
392 func TestScan(t *testing.T) {
393 testScan("StringReader", t, Fscan)
396 func TestMyReaderScan(t *testing.T) {
397 testScan("myStringReader", t, Fscan)
400 func TestScanln(t *testing.T) {
401 testScan("StringReader", t, Fscanln)
404 func TestMyReaderScanln(t *testing.T) {
405 testScan("myStringReader", t, Fscanln)
408 func TestScanf(t *testing.T) {
409 for _, test := range scanfTests {
410 n, err := Sscanf(test.text, test.format, test.in)
412 t.Errorf("got error scanning (%q, %q): %s", test.format, test.text, err)
416 t.Errorf("count error on entry (%q, %q): got %d", test.format, test.text, n)
419 // The incoming value may be a pointer
420 v := reflect.ValueOf(test.in)
421 if p := v; p.Kind() == reflect.Ptr {
425 if !reflect.DeepEqual(val, test.out) {
426 t.Errorf("scanning (%q, %q): expected %#v got %#v, type %T", test.format, test.text, test.out, val, val)
431 func TestScanOverflow(t *testing.T) {
432 // different machines and different types report errors with different strings.
433 re := regexp.MustCompile("overflow|too large|out of range|not representable")
434 for _, test := range overflowTests {
435 _, err := Sscan(test.text, test.in)
437 t.Errorf("expected overflow scanning %q", test.text)
440 if !re.MatchString(err.Error()) {
441 t.Errorf("expected overflow error scanning %q: %s", test.text, err)
446 func verifyNaN(str string, t *testing.T) {
450 text := str + " " + str + " " + str
451 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
453 t.Errorf("got error scanning %q: %s", text, err)
456 t.Errorf("count error scanning %q: got %d", text, n)
458 if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) {
459 t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64)
463 func TestNaN(t *testing.T) {
464 for _, s := range []string{"nan", "NAN", "NaN"} {
469 func verifyInf(str string, t *testing.T) {
473 text := str + " " + str + " " + str
474 n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
476 t.Errorf("got error scanning %q: %s", text, err)
479 t.Errorf("count error scanning %q: got %d", text, n)
485 if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) {
486 t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64)
490 func TestInf(t *testing.T) {
491 for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} {
496 func testScanfMulti(name string, t *testing.T) {
497 sliceType := reflect.TypeOf(make([]interface{}, 1))
498 for _, test := range multiTests {
500 if name == "StringReader" {
501 r = strings.NewReader(test.text)
503 r = newReader(test.text)
505 n, err := Fscanf(r, test.format, test.in...)
508 t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err)
509 } else if strings.Index(err.Error(), test.err) < 0 {
510 t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err)
515 t.Errorf("expected error %q error scanning (%q, %q)", test.err, test.format, test.text)
517 if n != len(test.out) {
518 t.Errorf("count error on entry (%q, %q): expected %d got %d", test.format, test.text, len(test.out), n)
521 // Convert the slice of pointers into a slice of values
522 resultVal := reflect.MakeSlice(sliceType, n, n)
523 for i := 0; i < n; i++ {
524 v := reflect.ValueOf(test.in[i]).Elem()
525 resultVal.Index(i).Set(v)
527 result := resultVal.Interface()
528 if !reflect.DeepEqual(result, test.out) {
529 t.Errorf("scanning (%q, %q): expected %#v got %#v", test.format, test.text, test.out, result)
534 func TestScanfMulti(t *testing.T) {
535 testScanfMulti("StringReader", t)
538 func TestMyReaderScanfMulti(t *testing.T) {
539 testScanfMulti("myStringReader", t)
542 func TestScanMultiple(t *testing.T) {
545 n, err := Sscan("123abc", &a, &s)
547 t.Errorf("Sscan count error: expected 2: got %d", n)
550 t.Errorf("Sscan expected no error; got %s", err)
552 if a != 123 || s != "abc" {
553 t.Errorf("Sscan wrong values: got (%d %q) expected (123 \"abc\")", a, s)
555 n, err = Sscan("asdf", &s, &a)
557 t.Errorf("Sscan count error: expected 1: got %d", n)
560 t.Errorf("Sscan expected error; got none: %s", err)
563 t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s)
567 // Empty strings are not valid input when scanning a string.
568 func TestScanEmpty(t *testing.T) {
570 n, err := Sscan("abc", &s1, &s2)
572 t.Errorf("Sscan count error: expected 1: got %d", n)
575 t.Error("Sscan <one item> expected error; got none")
578 t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1)
580 n, err = Sscan("", &s1, &s2)
582 t.Errorf("Sscan count error: expected 0: got %d", n)
585 t.Error("Sscan <empty> expected error; got none")
587 // Quoted empty string is OK.
588 n, err = Sscanf(`""`, "%q", &s1)
590 t.Errorf("Sscanf count error: expected 1: got %d", n)
593 t.Errorf("Sscanf <empty> expected no error with quoted string; got %s", err)
597 func TestScanNotPointer(t *testing.T) {
598 r := strings.NewReader("1")
600 _, err := Fscan(r, a)
602 t.Error("expected error scanning non-pointer")
603 } else if strings.Index(err.Error(), "pointer") < 0 {
604 t.Errorf("expected pointer error scanning non-pointer, got: %s", err)
608 func TestScanlnNoNewline(t *testing.T) {
610 _, err := Sscanln("1 x\n", &a)
612 t.Error("expected error scanning string missing newline")
613 } else if strings.Index(err.Error(), "newline") < 0 {
614 t.Errorf("expected newline error scanning string missing newline, got: %s", err)
618 func TestScanlnWithMiddleNewline(t *testing.T) {
619 r := strings.NewReader("123\n456\n")
621 _, err := Fscanln(r, &a, &b)
623 t.Error("expected error scanning string with extra newline")
624 } else if strings.Index(err.Error(), "newline") < 0 {
625 t.Errorf("expected newline error scanning string with extra newline, got: %s", err)
629 // Special Reader that counts reads at end of file.
630 type eofCounter struct {
631 reader *strings.Reader
635 func (ec *eofCounter) Read(b []byte) (n int, err error) {
636 n, err = ec.reader.Read(b)
643 // Verify that when we scan, we see at most EOF once per call to a Scan function,
644 // and then only when it's really an EOF
645 func TestEOF(t *testing.T) {
646 ec := &eofCounter{strings.NewReader("123\n"), 0}
648 n, err := Fscanln(ec, &a)
650 t.Error("unexpected error", err)
653 t.Error("expected to scan one item, got", n)
655 if ec.eofCount != 0 {
656 t.Error("expected zero EOFs", ec.eofCount)
657 ec.eofCount = 0 // reset for next test
659 n, err = Fscanln(ec, &a)
661 t.Error("expected error scanning empty string")
664 t.Error("expected to scan zero items, got", n)
666 if ec.eofCount != 1 {
667 t.Error("expected one EOF, got", ec.eofCount)
671 // Verify that we see an EOF error if we run out of input.
672 // This was a buglet: we used to get "expected integer".
673 func TestEOFAtEndOfInput(t *testing.T) {
675 n, err := Sscanf("23", "%d %d", &i, &j)
676 if n != 1 || i != 23 {
677 t.Errorf("Sscanf expected one value of 23; got %d %d", n, i)
680 t.Errorf("Sscanf expected EOF; got %q", err)
682 n, err = Sscan("234", &i, &j)
683 if n != 1 || i != 234 {
684 t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
687 t.Errorf("Sscan expected EOF; got %q", err)
689 // Trailing space is tougher.
690 n, err = Sscan("234 ", &i, &j)
691 if n != 1 || i != 234 {
692 t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
695 t.Errorf("Sscan expected EOF; got %q", err)
699 var eofTests = []struct {
712 {"%v", &complex64Val},
713 {"%v", &renamedStringVal},
714 {"%v", &renamedBytesVal},
715 {"%v", &renamedIntVal},
716 {"%v", &renamedUintVal},
717 {"%v", &renamedBoolVal},
718 {"%v", &renamedFloat32Val},
719 {"%v", &renamedComplex64Val},
722 func TestEOFAllTypes(t *testing.T) {
723 for i, test := range eofTests {
724 if _, err := Sscanf("", test.format, test.v); err != io.EOF {
725 t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err)
727 if _, err := Sscanf(" ", test.format, test.v); err != io.EOF {
728 t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err)
733 // Verify that, at least when using bufio, successive calls to Fscan do not lose runes.
734 func TestUnreadRuneWithBufio(t *testing.T) {
735 r := bufio.NewReader(strings.NewReader("123αb"))
738 n, err := Fscanf(r, "%d", &i)
739 if n != 1 || err != nil {
740 t.Errorf("reading int expected one item, no errors; got %d %q", n, err)
743 t.Errorf("expected 123; got %d", i)
745 n, err = Fscanf(r, "%s", &a)
746 if n != 1 || err != nil {
747 t.Errorf("reading string expected one item, no errors; got %d %q", n, err)
750 t.Errorf("expected αb; got %q", a)
756 // Attempt to read two lines into the object. Scanln should prevent this
757 // because it stops at newline; Scan and Scanf should be fine.
758 func (t *TwoLines) Scan(state ScanState, verb rune) error {
759 chars := make([]rune, 0, 100)
760 for nlCount := 0; nlCount < 2; {
761 c, _, err := state.ReadRune()
765 chars = append(chars, c)
770 *t = TwoLines(string(chars))
774 func TestMultiLine(t *testing.T) {
775 input := "abc\ndef\n"
778 n, err := Sscan(input, &tscan)
780 t.Errorf("Sscan: expected 1 item; got %d", n)
783 t.Errorf("Sscan: expected no error; got %s", err)
785 if string(tscan) != input {
786 t.Errorf("Sscan: expected %q; got %q", input, tscan)
788 // Sscanf should work
790 n, err = Sscanf(input, "%s", &tscanf)
792 t.Errorf("Sscanf: expected 1 item; got %d", n)
795 t.Errorf("Sscanf: expected no error; got %s", err)
797 if string(tscanf) != input {
798 t.Errorf("Sscanf: expected %q; got %q", input, tscanf)
800 // Sscanln should not work
802 n, err = Sscanln(input, &tscanln)
804 t.Errorf("Sscanln: expected 0 items; got %d: %q", n, tscanln)
807 t.Error("Sscanln: expected error; got none")
808 } else if err != io.ErrUnexpectedEOF {
809 t.Errorf("Sscanln: expected io.ErrUnexpectedEOF (ha!); got %s", err)
813 // RecursiveInt accepts a string matching %d.%d.%d....
814 // and parses it into a linked list.
815 // It allows us to benchmark recursive descent style scanners.
816 type RecursiveInt struct {
821 func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
822 _, err = Fscan(state, &r.i)
826 next := new(RecursiveInt)
827 _, err = Fscanf(state, ".%v", next)
829 if err == io.ErrUnexpectedEOF {
838 // Perform the same scanning task as RecursiveInt.Scan
839 // but without recurring through scanner, so we can compare
840 // performance more directly.
841 func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) {
843 _, err = Fscan(b, &r.i)
847 c, _, err := b.ReadRune()
857 next := new(RecursiveInt)
858 err = scanInts(next, b)
865 func makeInts(n int) []byte {
868 for i := 1; i < n; i++ {
869 Fprintf(&buf, ".%d", i+1)
874 func TestScanInts(t *testing.T) {
875 testScanInts(t, scanInts)
876 testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err error) {
882 // 800 is small enough to not overflow the stack when using gccgo on a
883 // platform that does not support split stack.
886 func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) error) {
887 r := new(RecursiveInt)
888 ints := makeInts(intCount)
889 buf := bytes.NewBuffer(ints)
892 t.Error("unexpected error", err)
895 for ; r != nil; r = r.next {
897 t.Fatalf("bad scan: expected %d got %d", i, r.i)
902 t.Fatalf("bad scan count: expected %d got %d", intCount, i-1)
906 func BenchmarkScanInts(b *testing.B) {
908 ints := makeInts(intCount)
910 for i := b.N - 1; i >= 0; i-- {
911 buf := bytes.NewBuffer(ints)
918 func BenchmarkScanRecursiveInt(b *testing.B) {
920 ints := makeInts(intCount)
922 for i := b.N - 1; i >= 0; i-- {
923 buf := bytes.NewBuffer(ints)