16
# Following tests are my interpretation of the
17
# {CSV RCF}[http://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that
16
# Following tests are my interpretation of the
17
# {CSV RCF}[http://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that
18
18
# document in one place (intentionally) and that is to make the default row
19
19
# separator <tt>$/</tt>.
21
21
class TestCSVParsing < Test::Unit::TestCase
22
22
BIG_DATA = "123456789\n" * 1024
24
24
def test_mastering_regex_example
25
25
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
26
26
assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
27
27
"It's \"10 Grand\", baby", "10K" ],
28
28
CSV.parse_line(ex) )
31
31
# Old Ruby 1.8 CSV library tests.
32
32
def test_std_lib_csv
102
102
assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
106
106
def test_james_edge_cases
107
107
# A read at eof? should return nil.
108
108
assert_equal(nil, CSV.parse_line(""))
110
110
# With Ruby 1.8 CSV it's impossible to tell an empty line from a line
111
111
# containing a single +nil+ field. The old CSV library returns
112
112
# <tt>[nil]</tt> in these cases, but <tt>Array.new</tt> makes more sense to
115
115
assert_equal(Array.new, CSV.parse_line("\n1,2,3\n"))
118
def test_rob_edge_cases
119
[ [%Q{"a\nb"}, ["a\nb"]],
120
[%Q{"\n\n\n"}, ["\n\n\n"]],
121
[%Q{a,"b\n\nc"}, ['a', "b\n\nc"]],
122
[%Q{,"\r\n"}, [nil,"\r\n"]],
123
[%Q{,"\r\n."}, [nil,"\r\n."]],
124
[%Q{"a\na","one newline"}, ["a\na", 'one newline']],
125
[%Q{"a\n\na","two newlines"}, ["a\n\na", 'two newlines']],
126
[%Q{"a\r\na","one CRLF"}, ["a\r\na", 'one CRLF']],
127
[%Q{"a\r\n\r\na","two CRLFs"}, ["a\r\n\r\na", 'two CRLFs']],
128
[%Q{with blank,"start\n\nfinish"\n}, ['with blank', "start\n\nfinish"]],
129
].each do |edge_case|
130
assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
134
def test_non_regex_edge_cases
135
# An early version of the non-regex parser fails this test
136
[ [ "foo,\"foo,bar,baz,foo\",\"foo\"",
137
["foo", "foo,bar,baz,foo", "foo"] ] ].each do |edge_case|
138
assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
141
assert_raise(CSV::MalformedCSVError) do
142
CSV.parse_line("1,\"23\"4\"5\", 6")
118
146
def test_malformed_csv
119
147
assert_raise(CSV::MalformedCSVError) do
120
148
CSV.parse_line("1,2\r,3", row_sep: "\n")
123
151
bad_data = <<-END_DATA.gsub(/^ +/, "")
125
153
line,2,"def\nghi"
127
155
line,4,some\rjunk
130
158
lines = bad_data.lines.to_a
131
159
assert_equal(6, lines.size)
132
160
assert_match(/\Aline,4/, lines.find { |l| l =~ /some\rjunk/ })
134
162
csv = CSV.new(bad_data)
141
169
assert_equal( "Unquoted fields do not allow \\r or \\n (line 4).",
145
173
assert_raise(CSV::MalformedCSVError) { CSV.parse_line('1,2,"3...') }
147
175
bad_data = <<-END_DATA.gsub(/^ +/, "")
149
177
line,2,"def\nghi"
154
182
lines = bad_data.lines.to_a
155
183
assert_equal(6, lines.size)
156
184
assert_match(/\Aline,4/, lines.find { |l| l =~ /8'10"/ })
158
186
csv = CSV.new(bad_data)
165
193
assert_equal("Illegal quoting on line 4.", $!.message)
169
197
def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
170
198
assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
173
201
def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
174
202
assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
177
205
def test_field_size_limit_controls_lookahead
178
206
assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
179
207
field_size_limit: 2048 )
184
212
def assert_parse_errors_out(*args)
185
213
assert_raise(CSV::MalformedCSVError) do
186
214
Timeout.timeout(0.2) do