|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package csv | 
|  |  | 
|  | import ( | 
|  | "io" | 
|  | "reflect" | 
|  | "strings" | 
|  | "testing" | 
|  | "unicode/utf8" | 
|  | ) | 
|  |  | 
|  | func TestRead(t *testing.T) { | 
|  | tests := []struct { | 
|  | Name   string | 
|  | Input  string | 
|  | Output [][]string | 
|  | Error  error | 
|  |  | 
|  | // These fields are copied into the Reader | 
|  | Comma              rune | 
|  | Comment            rune | 
|  | UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1 | 
|  | FieldsPerRecord    int | 
|  | LazyQuotes         bool | 
|  | TrimLeadingSpace   bool | 
|  | ReuseRecord        bool | 
|  | }{{ | 
|  | Name:   "Simple", | 
|  | Input:  "a,b,c\n", | 
|  | Output: [][]string{{"a", "b", "c"}}, | 
|  | }, { | 
|  | Name:   "CRLF", | 
|  | Input:  "a,b\r\nc,d\r\n", | 
|  | Output: [][]string{{"a", "b"}, {"c", "d"}}, | 
|  | }, { | 
|  | Name:   "BareCR", | 
|  | Input:  "a,b\rc,d\r\n", | 
|  | Output: [][]string{{"a", "b\rc", "d"}}, | 
|  | }, { | 
|  | Name: "RFC4180test", | 
|  | Input: `#field1,field2,field3 | 
|  | "aaa","bb | 
|  | b","ccc" | 
|  | "a,a","b""bb","ccc" | 
|  | zzz,yyy,xxx | 
|  | `, | 
|  | Output: [][]string{ | 
|  | {"#field1", "field2", "field3"}, | 
|  | {"aaa", "bb\nb", "ccc"}, | 
|  | {"a,a", `b"bb`, "ccc"}, | 
|  | {"zzz", "yyy", "xxx"}, | 
|  | }, | 
|  | UseFieldsPerRecord: true, | 
|  | FieldsPerRecord:    0, | 
|  | }, { | 
|  | Name:   "NoEOLTest", | 
|  | Input:  "a,b,c", | 
|  | Output: [][]string{{"a", "b", "c"}}, | 
|  | }, { | 
|  | Name:   "Semicolon", | 
|  | Input:  "a;b;c\n", | 
|  | Output: [][]string{{"a", "b", "c"}}, | 
|  | Comma:  ';', | 
|  | }, { | 
|  | Name: "MultiLine", | 
|  | Input: `"two | 
|  | line","one line","three | 
|  | line | 
|  | field"`, | 
|  | Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}}, | 
|  | }, { | 
|  | Name:  "BlankLine", | 
|  | Input: "a,b,c\n\nd,e,f\n\n", | 
|  | Output: [][]string{ | 
|  | {"a", "b", "c"}, | 
|  | {"d", "e", "f"}, | 
|  | }, | 
|  | }, { | 
|  | Name:  "BlankLineFieldCount", | 
|  | Input: "a,b,c\n\nd,e,f\n\n", | 
|  | Output: [][]string{ | 
|  | {"a", "b", "c"}, | 
|  | {"d", "e", "f"}, | 
|  | }, | 
|  | UseFieldsPerRecord: true, | 
|  | FieldsPerRecord:    0, | 
|  | }, { | 
|  | Name:             "TrimSpace", | 
|  | Input:            " a,  b,   c\n", | 
|  | Output:           [][]string{{"a", "b", "c"}}, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:   "LeadingSpace", | 
|  | Input:  " a,  b,   c\n", | 
|  | Output: [][]string{{" a", "  b", "   c"}}, | 
|  | }, { | 
|  | Name:    "Comment", | 
|  | Input:   "#1,2,3\na,b,c\n#comment", | 
|  | Output:  [][]string{{"a", "b", "c"}}, | 
|  | Comment: '#', | 
|  | }, { | 
|  | Name:   "NoComment", | 
|  | Input:  "#1,2,3\na,b,c", | 
|  | Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}}, | 
|  | }, { | 
|  | Name:       "LazyQuotes", | 
|  | Input:      `a "word","1"2",a","b`, | 
|  | Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}}, | 
|  | LazyQuotes: true, | 
|  | }, { | 
|  | Name:       "BareQuotes", | 
|  | Input:      `a "word","1"2",a"`, | 
|  | Output:     [][]string{{`a "word"`, `1"2`, `a"`}}, | 
|  | LazyQuotes: true, | 
|  | }, { | 
|  | Name:       "BareDoubleQuotes", | 
|  | Input:      `a""b,c`, | 
|  | Output:     [][]string{{`a""b`, `c`}}, | 
|  | LazyQuotes: true, | 
|  | }, { | 
|  | Name:  "BadDoubleQuotes", | 
|  | Input: `a""b,c`, | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 1, Err: ErrBareQuote}, | 
|  | }, { | 
|  | Name:             "TrimQuote", | 
|  | Input:            ` "a"," b",c`, | 
|  | Output:           [][]string{{"a", " b", "c"}}, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:  "BadBareQuote", | 
|  | Input: `a "word","b"`, | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 2, Err: ErrBareQuote}, | 
|  | }, { | 
|  | Name:  "BadTrailingQuote", | 
|  | Input: `"a word",b"`, | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 10, Err: ErrBareQuote}, | 
|  | }, { | 
|  | Name:  "ExtraneousQuote", | 
|  | Input: `"a "word","b"`, | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 3, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:               "BadFieldCount", | 
|  | Input:              "a,b,c\nd,e", | 
|  | Error:              &ParseError{StartLine: 2, Line: 2, Err: ErrFieldCount}, | 
|  | UseFieldsPerRecord: true, | 
|  | FieldsPerRecord:    0, | 
|  | }, { | 
|  | Name:               "BadFieldCount1", | 
|  | Input:              `a,b,c`, | 
|  | Error:              &ParseError{StartLine: 1, Line: 1, Err: ErrFieldCount}, | 
|  | UseFieldsPerRecord: true, | 
|  | FieldsPerRecord:    2, | 
|  | }, { | 
|  | Name:   "FieldCount", | 
|  | Input:  "a,b,c\nd,e", | 
|  | Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, | 
|  | }, { | 
|  | Name:   "TrailingCommaEOF", | 
|  | Input:  "a,b,c,", | 
|  | Output: [][]string{{"a", "b", "c", ""}}, | 
|  | }, { | 
|  | Name:   "TrailingCommaEOL", | 
|  | Input:  "a,b,c,\n", | 
|  | Output: [][]string{{"a", "b", "c", ""}}, | 
|  | }, { | 
|  | Name:             "TrailingCommaSpaceEOF", | 
|  | Input:            "a,b,c, ", | 
|  | Output:           [][]string{{"a", "b", "c", ""}}, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:             "TrailingCommaSpaceEOL", | 
|  | Input:            "a,b,c, \n", | 
|  | Output:           [][]string{{"a", "b", "c", ""}}, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:             "TrailingCommaLine3", | 
|  | Input:            "a,b,c\nd,e,f\ng,hi,", | 
|  | Output:           [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}}, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:   "NotTrailingComma3", | 
|  | Input:  "a,b,c, \n", | 
|  | Output: [][]string{{"a", "b", "c", " "}}, | 
|  | }, { | 
|  | Name: "CommaFieldTest", | 
|  | Input: `x,y,z,w | 
|  | x,y,z, | 
|  | x,y,, | 
|  | x,,, | 
|  | ,,, | 
|  | "x","y","z","w" | 
|  | "x","y","z","" | 
|  | "x","y","","" | 
|  | "x","","","" | 
|  | "","","","" | 
|  | `, | 
|  | Output: [][]string{ | 
|  | {"x", "y", "z", "w"}, | 
|  | {"x", "y", "z", ""}, | 
|  | {"x", "y", "", ""}, | 
|  | {"x", "", "", ""}, | 
|  | {"", "", "", ""}, | 
|  | {"x", "y", "z", "w"}, | 
|  | {"x", "y", "z", ""}, | 
|  | {"x", "y", "", ""}, | 
|  | {"x", "", "", ""}, | 
|  | {"", "", "", ""}, | 
|  | }, | 
|  | }, { | 
|  | Name:  "TrailingCommaIneffective1", | 
|  | Input: "a,b,\nc,d,e", | 
|  | Output: [][]string{ | 
|  | {"a", "b", ""}, | 
|  | {"c", "d", "e"}, | 
|  | }, | 
|  | TrimLeadingSpace: true, | 
|  | }, { | 
|  | Name:  "ReadAllReuseRecord", | 
|  | Input: "a,b\nc,d", | 
|  | Output: [][]string{ | 
|  | {"a", "b"}, | 
|  | {"c", "d"}, | 
|  | }, | 
|  | ReuseRecord: true, | 
|  | }, { | 
|  | Name:  "StartLine1", // Issue 19019 | 
|  | Input: "a,\"b\nc\"d,e", | 
|  | Error: &ParseError{StartLine: 1, Line: 2, Column: 1, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:  "StartLine2", | 
|  | Input: "a,b\n\"d\n\n,e", | 
|  | Error: &ParseError{StartLine: 2, Line: 5, Column: 0, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:  "CRLFInQuotedField", // Issue 21201 | 
|  | Input: "A,\"Hello\r\nHi\",B\r\n", | 
|  | Output: [][]string{ | 
|  | {"A", "Hello\nHi", "B"}, | 
|  | }, | 
|  | }, { | 
|  | Name:   "BinaryBlobField", // Issue 19410 | 
|  | Input:  "x09\x41\xb4\x1c,aktau", | 
|  | Output: [][]string{{"x09A\xb4\x1c", "aktau"}}, | 
|  | }, { | 
|  | Name:   "TrailingCR", | 
|  | Input:  "field1,field2\r", | 
|  | Output: [][]string{{"field1", "field2"}}, | 
|  | }, { | 
|  | Name:   "QuotedTrailingCR", | 
|  | Input:  "\"field\"\r", | 
|  | Output: [][]string{{"field"}}, | 
|  | }, { | 
|  | Name:  "QuotedTrailingCRCR", | 
|  | Input: "\"field\"\r\r", | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 6, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:   "FieldCR", | 
|  | Input:  "field\rfield\r", | 
|  | Output: [][]string{{"field\rfield"}}, | 
|  | }, { | 
|  | Name:   "FieldCRCR", | 
|  | Input:  "field\r\rfield\r\r", | 
|  | Output: [][]string{{"field\r\rfield\r"}}, | 
|  | }, { | 
|  | Name:   "FieldCRCRLF", | 
|  | Input:  "field\r\r\nfield\r\r\n", | 
|  | Output: [][]string{{"field\r"}, {"field\r"}}, | 
|  | }, { | 
|  | Name:   "FieldCRCRLFCR", | 
|  | Input:  "field\r\r\n\rfield\r\r\n\r", | 
|  | Output: [][]string{{"field\r"}, {"\rfield\r"}}, | 
|  | }, { | 
|  | Name:   "FieldCRCRLFCRCR", | 
|  | Input:  "field\r\r\n\r\rfield\r\r\n\r\r", | 
|  | Output: [][]string{{"field\r"}, {"\r\rfield\r"}, {"\r"}}, | 
|  | }, { | 
|  | Name:  "MultiFieldCRCRLFCRCR", | 
|  | Input: "field1,field2\r\r\n\r\rfield1,field2\r\r\n\r\r,", | 
|  | Output: [][]string{ | 
|  | {"field1", "field2\r"}, | 
|  | {"\r\rfield1", "field2\r"}, | 
|  | {"\r\r", ""}, | 
|  | }, | 
|  | }, { | 
|  | Name:             "NonASCIICommaAndComment", | 
|  | Input:            "a£b,c£ \td,e\n€ comment\n", | 
|  | Output:           [][]string{{"a", "b,c", "d,e"}}, | 
|  | TrimLeadingSpace: true, | 
|  | Comma:            '£', | 
|  | Comment:          '€', | 
|  | }, { | 
|  | Name:    "NonASCIICommaAndCommentWithQuotes", | 
|  | Input:   "a€\"  b,\"€ c\nλ comment\n", | 
|  | Output:  [][]string{{"a", "  b,", " c"}}, | 
|  | Comma:   '€', | 
|  | Comment: 'λ', | 
|  | }, { | 
|  | // λ and θ start with the same byte. | 
|  | // This tests that the parser doesn't confuse such characters. | 
|  | Name:    "NonASCIICommaConfusion", | 
|  | Input:   "\"abθcd\"λefθgh", | 
|  | Output:  [][]string{{"abθcd", "efθgh"}}, | 
|  | Comma:   'λ', | 
|  | Comment: '€', | 
|  | }, { | 
|  | Name:    "NonASCIICommentConfusion", | 
|  | Input:   "λ\nλ\nθ\nλ\n", | 
|  | Output:  [][]string{{"λ"}, {"λ"}, {"λ"}}, | 
|  | Comment: 'θ', | 
|  | }, { | 
|  | Name:   "QuotedFieldMultipleLF", | 
|  | Input:  "\"\n\n\n\n\"", | 
|  | Output: [][]string{{"\n\n\n\n"}}, | 
|  | }, { | 
|  | Name:  "MultipleCRLF", | 
|  | Input: "\r\n\r\n\r\n\r\n", | 
|  | }, { | 
|  | // The implementation may read each line in several chunks if it doesn't fit entirely | 
|  | // in the read buffer, so we should test the code to handle that condition. | 
|  | Name:    "HugeLines", | 
|  | Input:   strings.Repeat("#ignore\n", 10000) + strings.Repeat("@", 5000) + "," + strings.Repeat("*", 5000), | 
|  | Output:  [][]string{{strings.Repeat("@", 5000), strings.Repeat("*", 5000)}}, | 
|  | Comment: '#', | 
|  | }, { | 
|  | Name:  "QuoteWithTrailingCRLF", | 
|  | Input: "\"foo\"bar\"\r\n", | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 4, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:       "LazyQuoteWithTrailingCRLF", | 
|  | Input:      "\"foo\"bar\"\r\n", | 
|  | Output:     [][]string{{`foo"bar`}}, | 
|  | LazyQuotes: true, | 
|  | }, { | 
|  | Name:   "DoubleQuoteWithTrailingCRLF", | 
|  | Input:  "\"foo\"\"bar\"\r\n", | 
|  | Output: [][]string{{`foo"bar`}}, | 
|  | }, { | 
|  | Name:   "EvenQuotes", | 
|  | Input:  `""""""""`, | 
|  | Output: [][]string{{`"""`}}, | 
|  | }, { | 
|  | Name:  "OddQuotes", | 
|  | Input: `"""""""`, | 
|  | Error: &ParseError{StartLine: 1, Line: 1, Column: 7, Err: ErrQuote}, | 
|  | }, { | 
|  | Name:       "LazyOddQuotes", | 
|  | Input:      `"""""""`, | 
|  | Output:     [][]string{{`"""`}}, | 
|  | LazyQuotes: true, | 
|  | }, { | 
|  | Name:  "BadComma1", | 
|  | Comma: '\n', | 
|  | Error: errInvalidDelim, | 
|  | }, { | 
|  | Name:  "BadComma2", | 
|  | Comma: '\r', | 
|  | Error: errInvalidDelim, | 
|  | }, { | 
|  | Name:  "BadComma3", | 
|  | Comma: '"', | 
|  | Error: errInvalidDelim, | 
|  | }, { | 
|  | Name:  "BadComma4", | 
|  | Comma: utf8.RuneError, | 
|  | Error: errInvalidDelim, | 
|  | }, { | 
|  | Name:    "BadComment1", | 
|  | Comment: '\n', | 
|  | Error:   errInvalidDelim, | 
|  | }, { | 
|  | Name:    "BadComment2", | 
|  | Comment: '\r', | 
|  | Error:   errInvalidDelim, | 
|  | }, { | 
|  | Name:    "BadComment3", | 
|  | Comment: utf8.RuneError, | 
|  | Error:   errInvalidDelim, | 
|  | }, { | 
|  | Name:    "BadCommaComment", | 
|  | Comma:   'X', | 
|  | Comment: 'X', | 
|  | Error:   errInvalidDelim, | 
|  | }} | 
|  |  | 
|  | for _, tt := range tests { | 
|  | t.Run(tt.Name, func(t *testing.T) { | 
|  | r := NewReader(strings.NewReader(tt.Input)) | 
|  |  | 
|  | if tt.Comma != 0 { | 
|  | r.Comma = tt.Comma | 
|  | } | 
|  | r.Comment = tt.Comment | 
|  | if tt.UseFieldsPerRecord { | 
|  | r.FieldsPerRecord = tt.FieldsPerRecord | 
|  | } else { | 
|  | r.FieldsPerRecord = -1 | 
|  | } | 
|  | r.LazyQuotes = tt.LazyQuotes | 
|  | r.TrimLeadingSpace = tt.TrimLeadingSpace | 
|  | r.ReuseRecord = tt.ReuseRecord | 
|  |  | 
|  | out, err := r.ReadAll() | 
|  | if !reflect.DeepEqual(err, tt.Error) { | 
|  | t.Errorf("ReadAll() error:\ngot  %v\nwant %v", err, tt.Error) | 
|  | } else if !reflect.DeepEqual(out, tt.Output) { | 
|  | t.Errorf("ReadAll() output:\ngot  %q\nwant %q", out, tt.Output) | 
|  | } | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | // nTimes is an io.Reader which yields the string s n times. | 
|  | type nTimes struct { | 
|  | s   string | 
|  | n   int | 
|  | off int | 
|  | } | 
|  |  | 
|  | func (r *nTimes) Read(p []byte) (n int, err error) { | 
|  | for { | 
|  | if r.n <= 0 || r.s == "" { | 
|  | return n, io.EOF | 
|  | } | 
|  | n0 := copy(p, r.s[r.off:]) | 
|  | p = p[n0:] | 
|  | n += n0 | 
|  | r.off += n0 | 
|  | if r.off == len(r.s) { | 
|  | r.off = 0 | 
|  | r.n-- | 
|  | } | 
|  | if len(p) == 0 { | 
|  | return | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // benchmarkRead measures reading the provided CSV rows data. | 
|  | // initReader, if non-nil, modifies the Reader before it's used. | 
|  | func benchmarkRead(b *testing.B, initReader func(*Reader), rows string) { | 
|  | b.ReportAllocs() | 
|  | r := NewReader(&nTimes{s: rows, n: b.N}) | 
|  | if initReader != nil { | 
|  | initReader(r) | 
|  | } | 
|  | for { | 
|  | _, err := r.Read() | 
|  | if err == io.EOF { | 
|  | break | 
|  | } | 
|  | if err != nil { | 
|  | b.Fatal(err) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | const benchmarkCSVData = `x,y,z,w | 
|  | x,y,z, | 
|  | x,y,, | 
|  | x,,, | 
|  | ,,, | 
|  | "x","y","z","w" | 
|  | "x","y","z","" | 
|  | "x","y","","" | 
|  | "x","","","" | 
|  | "","","","" | 
|  | ` | 
|  |  | 
|  | func BenchmarkRead(b *testing.B) { | 
|  | benchmarkRead(b, nil, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadWithFieldsPerRecord(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.FieldsPerRecord = 4 }, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadWithoutFieldsPerRecord(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.FieldsPerRecord = -1 }, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadLargeFields(b *testing.B) { | 
|  | benchmarkRead(b, nil, strings.Repeat(`xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | xxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvv | 
|  | ,,zzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | `, 3)) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadReuseRecord(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.ReuseRecord = true }, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadReuseRecordWithFieldsPerRecord(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.ReuseRecord = true; r.FieldsPerRecord = 4 }, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadReuseRecordWithoutFieldsPerRecord(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.ReuseRecord = true; r.FieldsPerRecord = -1 }, benchmarkCSVData) | 
|  | } | 
|  |  | 
|  | func BenchmarkReadReuseRecordLargeFields(b *testing.B) { | 
|  | benchmarkRead(b, func(r *Reader) { r.ReuseRecord = true }, strings.Repeat(`xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | xxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvv | 
|  | ,,zzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 
|  | `, 3)) | 
|  | } |