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 }