github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/encoding/csv/reader_test.go (about)

     1  // Copyright 2011 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.
     4  
     5  package csv
     6  
     7  import (
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  var readTests = []struct {
    14  	Name               string
    15  	Input              string
    16  	Output             [][]string
    17  	UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
    18  
    19  	// These fields are copied into the Reader
    20  	Comma            rune
    21  	Comment          rune
    22  	FieldsPerRecord  int
    23  	LazyQuotes       bool
    24  	TrailingComma    bool
    25  	TrimLeadingSpace bool
    26  
    27  	Error  string
    28  	Line   int // Expected error line if != 0
    29  	Column int // Expected error column if line != 0
    30  }{
    31  	{
    32  		Name:   "Simple",
    33  		Input:  "a,b,c\n",
    34  		Output: [][]string{{"a", "b", "c"}},
    35  	},
    36  	{
    37  		Name:   "CRLF",
    38  		Input:  "a,b\r\nc,d\r\n",
    39  		Output: [][]string{{"a", "b"}, {"c", "d"}},
    40  	},
    41  	{
    42  		Name:   "BareCR",
    43  		Input:  "a,b\rc,d\r\n",
    44  		Output: [][]string{{"a", "b\rc", "d"}},
    45  	},
    46  	{
    47  		Name:               "RFC4180test",
    48  		UseFieldsPerRecord: true,
    49  		Input: `#field1,field2,field3
    50  "aaa","bb
    51  b","ccc"
    52  "a,a","b""bb","ccc"
    53  zzz,yyy,xxx
    54  `,
    55  		Output: [][]string{
    56  			{"#field1", "field2", "field3"},
    57  			{"aaa", "bb\nb", "ccc"},
    58  			{"a,a", `b"bb`, "ccc"},
    59  			{"zzz", "yyy", "xxx"},
    60  		},
    61  	},
    62  	{
    63  		Name:   "NoEOLTest",
    64  		Input:  "a,b,c",
    65  		Output: [][]string{{"a", "b", "c"}},
    66  	},
    67  	{
    68  		Name:   "Semicolon",
    69  		Comma:  ';',
    70  		Input:  "a;b;c\n",
    71  		Output: [][]string{{"a", "b", "c"}},
    72  	},
    73  	{
    74  		Name: "MultiLine",
    75  		Input: `"two
    76  line","one line","three
    77  line
    78  field"`,
    79  		Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
    80  	},
    81  	{
    82  		Name:  "BlankLine",
    83  		Input: "a,b,c\n\nd,e,f\n\n",
    84  		Output: [][]string{
    85  			{"a", "b", "c"},
    86  			{"d", "e", "f"},
    87  		},
    88  	},
    89  	{
    90  		Name:             "TrimSpace",
    91  		Input:            " a,  b,   c\n",
    92  		TrimLeadingSpace: true,
    93  		Output:           [][]string{{"a", "b", "c"}},
    94  	},
    95  	{
    96  		Name:   "LeadingSpace",
    97  		Input:  " a,  b,   c\n",
    98  		Output: [][]string{{" a", "  b", "   c"}},
    99  	},
   100  	{
   101  		Name:    "Comment",
   102  		Comment: '#',
   103  		Input:   "#1,2,3\na,b,c\n#comment",
   104  		Output:  [][]string{{"a", "b", "c"}},
   105  	},
   106  	{
   107  		Name:   "NoComment",
   108  		Input:  "#1,2,3\na,b,c",
   109  		Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
   110  	},
   111  	{
   112  		Name:       "LazyQuotes",
   113  		LazyQuotes: true,
   114  		Input:      `a "word","1"2",a","b`,
   115  		Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
   116  	},
   117  	{
   118  		Name:       "BareQuotes",
   119  		LazyQuotes: true,
   120  		Input:      `a "word","1"2",a"`,
   121  		Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
   122  	},
   123  	{
   124  		Name:       "BareDoubleQuotes",
   125  		LazyQuotes: true,
   126  		Input:      `a""b,c`,
   127  		Output:     [][]string{{`a""b`, `c`}},
   128  	},
   129  	{
   130  		Name:  "BadDoubleQuotes",
   131  		Input: `a""b,c`,
   132  		Error: `bare " in non-quoted-field`, Line: 1, Column: 1,
   133  	},
   134  	{
   135  		Name:             "TrimQuote",
   136  		Input:            ` "a"," b",c`,
   137  		TrimLeadingSpace: true,
   138  		Output:           [][]string{{"a", " b", "c"}},
   139  	},
   140  	{
   141  		Name:  "BadBareQuote",
   142  		Input: `a "word","b"`,
   143  		Error: `bare " in non-quoted-field`, Line: 1, Column: 2,
   144  	},
   145  	{
   146  		Name:  "BadTrailingQuote",
   147  		Input: `"a word",b"`,
   148  		Error: `bare " in non-quoted-field`, Line: 1, Column: 10,
   149  	},
   150  	{
   151  		Name:  "ExtraneousQuote",
   152  		Input: `"a "word","b"`,
   153  		Error: `extraneous " in field`, Line: 1, Column: 3,
   154  	},
   155  	{
   156  		Name:               "BadFieldCount",
   157  		UseFieldsPerRecord: true,
   158  		Input:              "a,b,c\nd,e",
   159  		Error:              "wrong number of fields", Line: 2,
   160  	},
   161  	{
   162  		Name:               "BadFieldCount1",
   163  		UseFieldsPerRecord: true,
   164  		FieldsPerRecord:    2,
   165  		Input:              `a,b,c`,
   166  		Error:              "wrong number of fields", Line: 1,
   167  	},
   168  	{
   169  		Name:   "FieldCount",
   170  		Input:  "a,b,c\nd,e",
   171  		Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
   172  	},
   173  	{
   174  		Name:   "TrailingCommaEOF",
   175  		Input:  "a,b,c,",
   176  		Output: [][]string{{"a", "b", "c", ""}},
   177  	},
   178  	{
   179  		Name:   "TrailingCommaEOL",
   180  		Input:  "a,b,c,\n",
   181  		Output: [][]string{{"a", "b", "c", ""}},
   182  	},
   183  	{
   184  		Name:             "TrailingCommaSpaceEOF",
   185  		TrimLeadingSpace: true,
   186  		Input:            "a,b,c, ",
   187  		Output:           [][]string{{"a", "b", "c", ""}},
   188  	},
   189  	{
   190  		Name:             "TrailingCommaSpaceEOL",
   191  		TrimLeadingSpace: true,
   192  		Input:            "a,b,c, \n",
   193  		Output:           [][]string{{"a", "b", "c", ""}},
   194  	},
   195  	{
   196  		Name:             "TrailingCommaLine3",
   197  		TrimLeadingSpace: true,
   198  		Input:            "a,b,c\nd,e,f\ng,hi,",
   199  		Output:           [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}},
   200  	},
   201  	{
   202  		Name:   "NotTrailingComma3",
   203  		Input:  "a,b,c, \n",
   204  		Output: [][]string{{"a", "b", "c", " "}},
   205  	},
   206  	{
   207  		Name:          "CommaFieldTest",
   208  		TrailingComma: true,
   209  		Input: `x,y,z,w
   210  x,y,z,
   211  x,y,,
   212  x,,,
   213  ,,,
   214  "x","y","z","w"
   215  "x","y","z",""
   216  "x","y","",""
   217  "x","","",""
   218  "","","",""
   219  `,
   220  		Output: [][]string{
   221  			{"x", "y", "z", "w"},
   222  			{"x", "y", "z", ""},
   223  			{"x", "y", "", ""},
   224  			{"x", "", "", ""},
   225  			{"", "", "", ""},
   226  			{"x", "y", "z", "w"},
   227  			{"x", "y", "z", ""},
   228  			{"x", "y", "", ""},
   229  			{"x", "", "", ""},
   230  			{"", "", "", ""},
   231  		},
   232  	},
   233  	{
   234  		Name:             "TrailingCommaIneffective1",
   235  		TrailingComma:    true,
   236  		TrimLeadingSpace: true,
   237  		Input:            "a,b,\nc,d,e",
   238  		Output: [][]string{
   239  			{"a", "b", ""},
   240  			{"c", "d", "e"},
   241  		},
   242  	},
   243  	{
   244  		Name:             "TrailingCommaIneffective2",
   245  		TrailingComma:    false,
   246  		TrimLeadingSpace: true,
   247  		Input:            "a,b,\nc,d,e",
   248  		Output: [][]string{
   249  			{"a", "b", ""},
   250  			{"c", "d", "e"},
   251  		},
   252  	},
   253  }
   254  
   255  func TestRead(t *testing.T) {
   256  	for _, tt := range readTests {
   257  		r := NewReader(strings.NewReader(tt.Input))
   258  		r.Comment = tt.Comment
   259  		if tt.UseFieldsPerRecord {
   260  			r.FieldsPerRecord = tt.FieldsPerRecord
   261  		} else {
   262  			r.FieldsPerRecord = -1
   263  		}
   264  		r.LazyQuotes = tt.LazyQuotes
   265  		r.TrailingComma = tt.TrailingComma
   266  		r.TrimLeadingSpace = tt.TrimLeadingSpace
   267  		if tt.Comma != 0 {
   268  			r.Comma = tt.Comma
   269  		}
   270  		out, err := r.ReadAll()
   271  		perr, _ := err.(*ParseError)
   272  		if tt.Error != "" {
   273  			if err == nil || !strings.Contains(err.Error(), tt.Error) {
   274  				t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error)
   275  			} else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) {
   276  				t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column)
   277  			}
   278  		} else if err != nil {
   279  			t.Errorf("%s: unexpected error %v", tt.Name, err)
   280  		} else if !reflect.DeepEqual(out, tt.Output) {
   281  			t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output)
   282  		}
   283  	}
   284  }