mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/csv.rb: Import the FasterCSV source as the new CSV class.
* test/csv/*: Added all applicable tests from FasterCSV. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0d570142ba
commit
29ba327bd1
13 changed files with 3946 additions and 0 deletions
|
@ -1,3 +1,9 @@
|
|||
Tue Dec 25 11:45:34 2007 James Edward Gray II <jeg2@ruby-lang.org>
|
||||
|
||||
* lib/csv.rb: Import the FasterCSV source as the new CSV class.
|
||||
|
||||
* test/csv/*: Added all applicable tests from FasterCSV.
|
||||
|
||||
Tue Dec 25 11:33:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* error.c (report_bug): uses ruby_description.
|
||||
|
|
1892
lib/csv.rb
Normal file
1892
lib/csv.rb
Normal file
File diff suppressed because it is too large
Load diff
BIN
test/csv/line_endings.gz
Normal file
BIN
test/csv/line_endings.gz
Normal file
Binary file not shown.
164
test/csv/tc_csv_parsing.rb
Normal file
164
test/csv/tc_csv_parsing.rb
Normal file
|
@ -0,0 +1,164 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_csv_parsing.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
#
|
||||
# Following tests are my interpretation of the
|
||||
# {CSV RCF}[http://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that
|
||||
# document in one place (intentionally) and that is to make the default row
|
||||
# separator <tt>$/</tt>.
|
||||
#
|
||||
class TestCSVParsing < Test::Unit::TestCase
|
||||
def test_mastering_regex_example
|
||||
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
|
||||
assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
|
||||
"It's \"10 Grand\", baby", "10K" ],
|
||||
CSV.parse_line(ex) )
|
||||
end
|
||||
|
||||
# Old Ruby 1.8 CSV library tests.
|
||||
def test_std_lib_csv
|
||||
[ ["\t", ["\t"]],
|
||||
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
||||
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
||||
["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
|
||||
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
||||
["\"\"", [""]],
|
||||
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
||||
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
||||
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
||||
["foo,\"\",baz", ["foo", "", "baz"]],
|
||||
["\",\"", [","]],
|
||||
["foo", ["foo"]],
|
||||
[",,", [nil, nil, nil]],
|
||||
[",", [nil, nil]],
|
||||
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
||||
["foo,,baz", ["foo", nil, "baz"]],
|
||||
["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
|
||||
["\",\",\",\"", [",", ","]],
|
||||
["foo,bar,", ["foo", "bar", nil]],
|
||||
[",foo,bar", [nil, "foo", "bar"]],
|
||||
["foo,bar", ["foo", "bar"]],
|
||||
[";", [";"]],
|
||||
["\t,\t", ["\t", "\t"]],
|
||||
["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
|
||||
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
||||
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
||||
[";,;", [";", ";"]] ].each do |csv_test|
|
||||
assert_equal(csv_test.last, CSV.parse_line(csv_test.first))
|
||||
end
|
||||
|
||||
[ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
||||
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
||||
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
||||
["\"\"", [""]],
|
||||
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
||||
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
||||
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
||||
["foo,\"\",baz", ["foo", "", "baz"]],
|
||||
["foo", ["foo"]],
|
||||
[",,", [nil, nil, nil]],
|
||||
[",", [nil, nil]],
|
||||
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
||||
["foo,,baz", ["foo", nil, "baz"]],
|
||||
["foo,bar", ["foo", "bar"]],
|
||||
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
||||
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]] ].each do |csv_test|
|
||||
assert_equal(csv_test.last, CSV.parse_line(csv_test.first))
|
||||
end
|
||||
end
|
||||
|
||||
# From: http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-core/6496
|
||||
def test_aras_edge_cases
|
||||
[ [%Q{a,b}, ["a", "b"]],
|
||||
[%Q{a,"""b"""}, ["a", "\"b\""]],
|
||||
[%Q{a,"""b"}, ["a", "\"b"]],
|
||||
[%Q{a,"b"""}, ["a", "b\""]],
|
||||
[%Q{a,"\nb"""}, ["a", "\nb\""]],
|
||||
[%Q{a,"""\nb"}, ["a", "\"\nb"]],
|
||||
[%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
|
||||
[%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]],
|
||||
[%Q{a,,,}, ["a", nil, nil, nil]],
|
||||
[%Q{,}, [nil, nil]],
|
||||
[%Q{"",""}, ["", ""]],
|
||||
[%Q{""""}, ["\""]],
|
||||
[%Q{"""",""}, ["\"",""]],
|
||||
[%Q{,""}, [nil,""]],
|
||||
[%Q{,"\r"}, [nil,"\r"]],
|
||||
[%Q{"\r\n,"}, ["\r\n,"]],
|
||||
[%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |edge_case|
|
||||
assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
|
||||
end
|
||||
end
|
||||
|
||||
def test_james_edge_cases
|
||||
# A read at eof? should return nil.
|
||||
assert_equal(nil, CSV.parse_line(""))
|
||||
#
|
||||
# With Ruby 1.8 CSV it's impossible to tell an empty line from a line
|
||||
# containing a single +nil+ field. The old CSV library returns
|
||||
# <tt>[nil]</tt> in these cases, but <tt>Array.new</tt> makes more sense to
|
||||
# me.
|
||||
#
|
||||
assert_equal(Array.new, CSV.parse_line("\n1,2,3\n"))
|
||||
end
|
||||
|
||||
def test_malformed_csv
|
||||
assert_raise(CSV::MalformedCSVError) do
|
||||
CSV.parse_line("1,2\r,3", :row_sep => "\n")
|
||||
end
|
||||
|
||||
bad_data = <<-END_DATA.gsub(/^ +/, "")
|
||||
line,1,abc
|
||||
line,2,"def\nghi"
|
||||
|
||||
line,4,some\rjunk
|
||||
line,5,jkl
|
||||
END_DATA
|
||||
lines = bad_data.to_a
|
||||
assert_equal(6, lines.size)
|
||||
assert_match(/\Aline,4/, lines.find { |l| l =~ /some\rjunk/ })
|
||||
|
||||
csv = CSV.new(bad_data)
|
||||
begin
|
||||
loop do
|
||||
assert_not_nil(csv.shift)
|
||||
assert_send([csv.lineno, :<, 4])
|
||||
end
|
||||
rescue CSV::MalformedCSVError
|
||||
assert_equal( "Unquoted fields do not allow \\r or \\n (line 4).",
|
||||
$!.message )
|
||||
end
|
||||
|
||||
assert_raise(CSV::MalformedCSVError) { CSV.parse_line('1,2,"3...') }
|
||||
|
||||
bad_data = <<-END_DATA.gsub(/^ +/, "")
|
||||
line,1,abc
|
||||
line,2,"def\nghi"
|
||||
|
||||
line,4,8'10"
|
||||
line,5,jkl
|
||||
END_DATA
|
||||
lines = bad_data.to_a
|
||||
assert_equal(6, lines.size)
|
||||
assert_match(/\Aline,4/, lines.find { |l| l =~ /8'10"/ })
|
||||
|
||||
csv = CSV.new(bad_data)
|
||||
begin
|
||||
loop do
|
||||
assert_not_nil(csv.shift)
|
||||
assert_send([csv.lineno, :<, 4])
|
||||
end
|
||||
rescue CSV::MalformedCSVError
|
||||
assert_equal("Unclosed quoted field on line 4.", $!.message)
|
||||
end
|
||||
end
|
||||
end
|
96
test/csv/tc_csv_writing.rb
Normal file
96
test/csv/tc_csv_writing.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_csv_writing.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVWriting < Test::Unit::TestCase
|
||||
def test_writing
|
||||
[ ["\t", ["\t"]],
|
||||
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
||||
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
||||
["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
|
||||
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
||||
["\"\"", [""]],
|
||||
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
||||
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
||||
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
||||
["foo,\"\",baz", ["foo", "", "baz"]],
|
||||
["\",\"", [","]],
|
||||
["foo", ["foo"]],
|
||||
[",,", [nil, nil, nil]],
|
||||
[",", [nil, nil]],
|
||||
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
||||
["foo,,baz", ["foo", nil, "baz"]],
|
||||
["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
|
||||
["\",\",\",\"", [",", ","]],
|
||||
["foo,bar,", ["foo", "bar", nil]],
|
||||
[",foo,bar", [nil, "foo", "bar"]],
|
||||
["foo,bar", ["foo", "bar"]],
|
||||
[";", [";"]],
|
||||
["\t,\t", ["\t", "\t"]],
|
||||
["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
|
||||
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
||||
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
||||
[";,;", [";", ";"]],
|
||||
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
||||
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
||||
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
||||
["\"\"", [""]],
|
||||
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
||||
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
||||
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
||||
["foo,\"\",baz", ["foo", "", "baz"]],
|
||||
["foo", ["foo"]],
|
||||
[",,", [nil, nil, nil]],
|
||||
[",", [nil, nil]],
|
||||
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
||||
["foo,,baz", ["foo", nil, "baz"]],
|
||||
["foo,bar", ["foo", "bar"]],
|
||||
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
||||
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
||||
[%Q{a,b}, ["a", "b"]],
|
||||
[%Q{a,"""b"""}, ["a", "\"b\""]],
|
||||
[%Q{a,"""b"}, ["a", "\"b"]],
|
||||
[%Q{a,"b"""}, ["a", "b\""]],
|
||||
[%Q{a,"\nb"""}, ["a", "\nb\""]],
|
||||
[%Q{a,"""\nb"}, ["a", "\"\nb"]],
|
||||
[%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
|
||||
[%Q{a,"""\nb\n""",}, ["a", "\"\nb\n\"", nil]],
|
||||
[%Q{a,,,}, ["a", nil, nil, nil]],
|
||||
[%Q{,}, [nil, nil]],
|
||||
[%Q{"",""}, ["", ""]],
|
||||
[%Q{""""}, ["\""]],
|
||||
[%Q{"""",""}, ["\"",""]],
|
||||
[%Q{,""}, [nil,""]],
|
||||
[%Q{,"\r"}, [nil,"\r"]],
|
||||
[%Q{"\r\n,"}, ["\r\n,"]],
|
||||
[%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |test_case|
|
||||
assert_equal(test_case.first + $/, CSV.generate_line(test_case.last))
|
||||
end
|
||||
end
|
||||
|
||||
def test_col_sep
|
||||
assert_equal( "a;b;;c\n", CSV.generate_line( ["a", "b", nil, "c"],
|
||||
:col_sep => ";" ) )
|
||||
assert_equal( "a\tb\t\tc\n", CSV.generate_line( ["a", "b", nil, "c"],
|
||||
:col_sep => "\t" ) )
|
||||
end
|
||||
|
||||
def test_row_sep
|
||||
assert_equal( "a,b,,c\r\n", CSV.generate_line( ["a", "b", nil, "c"],
|
||||
:row_sep => "\r\n" ) )
|
||||
end
|
||||
|
||||
def test_force_quotes
|
||||
assert_equal( %Q{"1","b","","already ""quoted"""\n},
|
||||
CSV.generate_line( [1, "b", nil, %Q{already "quoted"}],
|
||||
:force_quotes => true ) )
|
||||
end
|
||||
end
|
260
test/csv/tc_data_converters.rb
Normal file
260
test/csv/tc_data_converters.rb
Normal file
|
@ -0,0 +1,260 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_data_converters.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestDataConverters < Test::Unit::TestCase
|
||||
def setup
|
||||
@data = "Numbers,:integer,1,:float,3.015"
|
||||
@parser = CSV.new(@data)
|
||||
|
||||
@custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
||||
|
||||
@win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y")
|
||||
end
|
||||
|
||||
def test_builtin_integer_converter
|
||||
# does convert
|
||||
[-5, 1, 10000000000].each do |n|
|
||||
assert_equal(n, CSV::Converters[:integer][n.to_s])
|
||||
end
|
||||
|
||||
# does not convert
|
||||
(%w{junk 1.0} + [""]).each do |str|
|
||||
assert_equal(str, CSV::Converters[:integer][str])
|
||||
end
|
||||
end
|
||||
|
||||
def test_builtin_float_converter
|
||||
# does convert
|
||||
[-5.1234, 0, 2.3e-11].each do |n|
|
||||
assert_equal(n, CSV::Converters[:float][n.to_s])
|
||||
end
|
||||
|
||||
# does not convert
|
||||
(%w{junk 1..0 .015F} + [""]).each do |str|
|
||||
assert_equal(str, CSV::Converters[:float][str])
|
||||
end
|
||||
end
|
||||
|
||||
def test_builtin_date_converter
|
||||
# does convert
|
||||
assert_instance_of(
|
||||
Date,
|
||||
CSV::Converters[:date][@win_safe_time_str.sub(/\d+:\d+:\d+ /, "")]
|
||||
)
|
||||
|
||||
# does not convert
|
||||
assert_instance_of(String, CSV::Converters[:date]["junk"])
|
||||
end
|
||||
|
||||
def test_builtin_date_time_converter
|
||||
# does convert
|
||||
assert_instance_of( DateTime,
|
||||
CSV::Converters[:date_time][@win_safe_time_str] )
|
||||
|
||||
# does not convert
|
||||
assert_instance_of(String, CSV::Converters[:date_time]["junk"])
|
||||
end
|
||||
|
||||
def test_convert_with_builtin
|
||||
# setup parser...
|
||||
assert(@parser.respond_to?(:convert))
|
||||
assert_nothing_raised(Exception) { @parser.convert(:integer) }
|
||||
|
||||
# and use
|
||||
assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], @parser.shift)
|
||||
|
||||
setup # reset
|
||||
|
||||
# setup parser...
|
||||
assert_nothing_raised(Exception) { @parser.convert(:float) }
|
||||
|
||||
# and use
|
||||
assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], @parser.shift)
|
||||
end
|
||||
|
||||
def test_convert_order
|
||||
# floats first, then integers...
|
||||
assert_nothing_raised(Exception) do
|
||||
@parser.convert(:float)
|
||||
@parser.convert(:integer)
|
||||
end
|
||||
|
||||
# gets us nothing but floats
|
||||
assert_equal( [String, String, Float, String, Float],
|
||||
@parser.shift.map { |field| field.class } )
|
||||
|
||||
setup # reset
|
||||
|
||||
# integers have precendance...
|
||||
assert_nothing_raised(Exception) do
|
||||
@parser.convert(:integer)
|
||||
@parser.convert(:float)
|
||||
end
|
||||
|
||||
# gives us proper number conversion
|
||||
assert_equal( [String, String, Fixnum, String, Float],
|
||||
@parser.shift.map { |field| field.class } )
|
||||
end
|
||||
|
||||
def test_builtin_numeric_combo_converter
|
||||
# setup parser...
|
||||
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
||||
|
||||
# and use
|
||||
assert_equal( [String, String, Fixnum, String, Float],
|
||||
@parser.shift.map { |field| field.class } )
|
||||
end
|
||||
|
||||
def test_builtin_all_nested_combo_converter
|
||||
# setup parser...
|
||||
@data << ",#{@win_safe_time_str}" # add a DateTime field
|
||||
@parser = CSV.new(@data) # reset parser
|
||||
assert_nothing_raised(Exception) { @parser.convert(:all) }
|
||||
|
||||
# and use
|
||||
assert_equal( [String, String, Fixnum, String, Float, DateTime],
|
||||
@parser.shift.map { |field| field.class } )
|
||||
end
|
||||
|
||||
def test_convert_with_custom_code
|
||||
# define custom converter...
|
||||
assert_nothing_raised(Exception) do
|
||||
@parser.convert { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
||||
end
|
||||
|
||||
# and use
|
||||
assert_equal(["Numbers", :integer, "1", :float, "3.015"], @parser.shift)
|
||||
|
||||
setup # reset
|
||||
|
||||
# mix built-in and custom...
|
||||
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
||||
assert_nothing_raised(Exception) { @parser.convert(&@custom) }
|
||||
|
||||
# and use
|
||||
assert_equal(["Numbers", :integer, 1, :float, 3.015], @parser.shift)
|
||||
end
|
||||
|
||||
def test_convert_with_custom_code_using_field_info
|
||||
# define custom converter that uses field information...
|
||||
assert_nothing_raised(Exception) do
|
||||
@parser.convert do |field, info|
|
||||
assert_equal(1, info.line)
|
||||
info.index == 4 ? Float(field).floor : field
|
||||
end
|
||||
end
|
||||
|
||||
# and use
|
||||
assert_equal(["Numbers", ":integer", "1", ":float", 3], @parser.shift)
|
||||
end
|
||||
|
||||
def test_convert_with_custom_code_using_field_info_header
|
||||
@parser = CSV.new(@data, :headers => %w{one two three four five})
|
||||
|
||||
# define custom converter that uses field header information...
|
||||
assert_nothing_raised(Exception) do
|
||||
@parser.convert do |field, info|
|
||||
info.header == "three" ? Integer(field) * 100 : field
|
||||
end
|
||||
end
|
||||
|
||||
# and use
|
||||
assert_equal( ["Numbers", ":integer", 100, ":float", "3.015"],
|
||||
@parser.shift.fields )
|
||||
end
|
||||
|
||||
def test_shortcut_interface
|
||||
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
||||
CSV.parse_line(@data, :converters => :numeric) )
|
||||
|
||||
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
||||
CSV.parse_line(@data, :converters => [:integer, :float]) )
|
||||
|
||||
assert_equal( ["Numbers", :integer, 1, :float, 3.015],
|
||||
CSV.parse_line(@data, :converters => [:numeric, @custom]) )
|
||||
end
|
||||
|
||||
def test_unconverted_fields
|
||||
[ [ @data,
|
||||
["Numbers", :integer, 1, :float, 3.015],
|
||||
%w{Numbers :integer 1 :float 3.015} ],
|
||||
["\n", Array.new, Array.new] ].each do |test, fields, unconverted|
|
||||
row = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
row = CSV.parse_line( test,
|
||||
:converters => [:numeric, @custom],
|
||||
:unconverted_fields => true )
|
||||
end
|
||||
assert_not_nil(row)
|
||||
assert_equal(fields, row)
|
||||
assert_respond_to(row, :unconverted_fields)
|
||||
assert_equal(unconverted, row.unconverted_fields)
|
||||
end
|
||||
|
||||
data = <<-END_CSV.gsub(/^\s+/, "")
|
||||
first,second,third
|
||||
1,2,3
|
||||
END_CSV
|
||||
row = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
row = CSV.parse_line( data,
|
||||
:converters => :numeric,
|
||||
:unconverted_fields => true,
|
||||
:headers => :first_row )
|
||||
end
|
||||
assert_not_nil(row)
|
||||
assert_equal([["first", 1], ["second", 2], ["third", 3]], row.to_a)
|
||||
assert_respond_to(row, :unconverted_fields)
|
||||
assert_equal(%w{1 2 3}, row.unconverted_fields)
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
row = CSV.parse_line( data,
|
||||
:converters => :numeric,
|
||||
:unconverted_fields => true,
|
||||
:headers => :first_row,
|
||||
:return_headers => true )
|
||||
end
|
||||
assert_not_nil(row)
|
||||
assert_equal( [%w{first first}, %w{second second}, %w{third third}],
|
||||
row.to_a )
|
||||
assert_respond_to(row, :unconverted_fields)
|
||||
assert_equal(%w{first second third}, row.unconverted_fields)
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
row = CSV.parse_line( data,
|
||||
:converters => :numeric,
|
||||
:unconverted_fields => true,
|
||||
:headers => :first_row,
|
||||
:return_headers => true,
|
||||
:header_converters => :symbol )
|
||||
end
|
||||
assert_not_nil(row)
|
||||
assert_equal( [[:first, "first"], [:second, "second"], [:third, "third"]],
|
||||
row.to_a )
|
||||
assert_respond_to(row, :unconverted_fields)
|
||||
assert_equal(%w{first second third}, row.unconverted_fields)
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
row = CSV.parse_line( data,
|
||||
:converters => :numeric,
|
||||
:unconverted_fields => true,
|
||||
:headers => %w{my new headers},
|
||||
:return_headers => true,
|
||||
:header_converters => :symbol )
|
||||
end
|
||||
assert_not_nil(row)
|
||||
assert_equal( [[:my, "my"], [:new, "new"], [:headers, "headers"]],
|
||||
row.to_a )
|
||||
assert_respond_to(row, :unconverted_fields)
|
||||
assert_equal(Array.new, row.unconverted_fields)
|
||||
end
|
||||
end
|
177
test/csv/tc_features.rb
Normal file
177
test/csv/tc_features.rb
Normal file
|
@ -0,0 +1,177 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_features.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
require "zlib"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVFeatures < Test::Unit::TestCase
|
||||
TEST_CASES = [ [%Q{a,b}, ["a", "b"]],
|
||||
[%Q{a,"""b"""}, ["a", "\"b\""]],
|
||||
[%Q{a,"""b"}, ["a", "\"b"]],
|
||||
[%Q{a,"b"""}, ["a", "b\""]],
|
||||
[%Q{a,"\nb"""}, ["a", "\nb\""]],
|
||||
[%Q{a,"""\nb"}, ["a", "\"\nb"]],
|
||||
[%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
|
||||
[%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]],
|
||||
[%Q{a,,,}, ["a", nil, nil, nil]],
|
||||
[%Q{,}, [nil, nil]],
|
||||
[%Q{"",""}, ["", ""]],
|
||||
[%Q{""""}, ["\""]],
|
||||
[%Q{"""",""}, ["\"",""]],
|
||||
[%Q{,""}, [nil,""]],
|
||||
[%Q{,"\r"}, [nil,"\r"]],
|
||||
[%Q{"\r\n,"}, ["\r\n,"]],
|
||||
[%Q{"\r\n,",}, ["\r\n,", nil]] ]
|
||||
|
||||
def setup
|
||||
@sample_data = <<-END_DATA.gsub(/^ +/, "")
|
||||
line,1,abc
|
||||
line,2,"def\nghi"
|
||||
|
||||
line,4,jkl
|
||||
END_DATA
|
||||
@csv = CSV.new(@sample_data)
|
||||
end
|
||||
|
||||
def test_col_sep
|
||||
[";", "\t"].each do |sep|
|
||||
TEST_CASES.each do |test_case|
|
||||
assert_equal( test_case.last.map { |t| t.tr(",", sep) unless t.nil? },
|
||||
CSV.parse_line( test_case.first.tr(",", sep),
|
||||
:col_sep => sep ) )
|
||||
end
|
||||
end
|
||||
assert_equal([",,,", nil], CSV.parse_line(",,,;", :col_sep => ";"))
|
||||
end
|
||||
|
||||
def test_row_sep
|
||||
assert_raise(CSV::MalformedCSVError) do
|
||||
CSV.parse_line("1,2,3\n,4,5\r\n", :row_sep => "\r\n")
|
||||
end
|
||||
assert_equal( ["1", "2", "3\n", "4", "5"],
|
||||
CSV.parse_line(%Q{1,2,"3\n",4,5\r\n}, :row_sep => "\r\n"))
|
||||
end
|
||||
|
||||
def test_quote_char
|
||||
TEST_CASES.each do |test_case|
|
||||
assert_equal( test_case.last.map { |t| t.tr('"', "'") unless t.nil? },
|
||||
CSV.parse_line( test_case.first.tr('"', "'"),
|
||||
:quote_char => "'" ) )
|
||||
end
|
||||
end
|
||||
|
||||
def test_row_sep_auto_discovery
|
||||
["\r\n", "\n", "\r"].each do |line_end|
|
||||
data = "1,2,3#{line_end}4,5#{line_end}"
|
||||
discovered = CSV.new(data).instance_eval { @row_sep }
|
||||
assert_equal(line_end, discovered)
|
||||
end
|
||||
|
||||
assert_equal("\n", CSV.new("\n\r\n\r").instance_eval { @row_sep })
|
||||
|
||||
assert_equal($/, CSV.new("").instance_eval { @row_sep })
|
||||
|
||||
assert_equal($/, CSV.new(STDERR).instance_eval { @row_sep })
|
||||
end
|
||||
|
||||
def test_lineno
|
||||
assert_equal(5, @sample_data.to_a.size)
|
||||
|
||||
4.times do |line_count|
|
||||
assert_equal(line_count, @csv.lineno)
|
||||
assert_not_nil(@csv.shift)
|
||||
assert_equal(line_count + 1, @csv.lineno)
|
||||
end
|
||||
assert_nil(@csv.shift)
|
||||
end
|
||||
|
||||
def test_readline
|
||||
test_lineno
|
||||
|
||||
@csv.rewind
|
||||
|
||||
test_lineno
|
||||
end
|
||||
|
||||
def test_unknown_options
|
||||
assert_raise(ArgumentError) { CSV.new(String.new, :unknown => :error) }
|
||||
end
|
||||
|
||||
def test_skip_blanks
|
||||
assert_equal(4, @csv.to_a.size)
|
||||
|
||||
@csv = CSV.new(@sample_data, :skip_blanks => true)
|
||||
|
||||
count = 0
|
||||
@csv.each do |row|
|
||||
count += 1
|
||||
assert_equal("line", row.first)
|
||||
end
|
||||
assert_equal(3, count)
|
||||
end
|
||||
|
||||
# reported by Kev Jackson
|
||||
def test_failing_to_escape_col_sep_bug_fix
|
||||
assert_nothing_raised(Exception) { CSV.new(String.new, :col_sep => "|") }
|
||||
end
|
||||
|
||||
# reported by Chris Roos
|
||||
def test_failing_to_reset_headers_in_rewind_bug_fix
|
||||
csv = CSV.new("forename,surname", :headers => true, :return_headers => true)
|
||||
csv.each { |row| assert row.header_row? }
|
||||
csv.rewind
|
||||
csv.each { |row| assert row.header_row? }
|
||||
end
|
||||
|
||||
# reported by Dave Burt
|
||||
def test_leading_empty_fields_with_multibyte_col_sep_bug_fix
|
||||
data = <<-END_DATA.gsub(/^\s+/, "")
|
||||
<=><=>A<=>B<=>C
|
||||
1<=>2<=>3
|
||||
END_DATA
|
||||
parsed = CSV.parse(data, :col_sep => "<=>")
|
||||
assert_equal([[nil, nil, "A", "B", "C"], ["1", "2", "3"]], parsed)
|
||||
end
|
||||
|
||||
def test_gzip_reader_bug_fix
|
||||
zipped = nil
|
||||
assert_nothing_raised(NoMethodError) do
|
||||
zipped = CSV.new(
|
||||
Zlib::GzipReader.open(
|
||||
File.join(File.dirname(__FILE__), "line_endings.gz")
|
||||
)
|
||||
)
|
||||
end
|
||||
assert_equal("\r\n", zipped.instance_eval { @row_sep })
|
||||
end
|
||||
|
||||
def test_gzip_writer_bug_fix
|
||||
file = File.join(File.dirname(__FILE__), "temp.gz")
|
||||
zipped = nil
|
||||
assert_nothing_raised(NoMethodError) do
|
||||
zipped = CSV.new(Zlib::GzipWriter.open(file))
|
||||
end
|
||||
zipped << %w[one two three]
|
||||
zipped << [1, 2, 3]
|
||||
zipped.close
|
||||
|
||||
assert( Zlib::GzipReader.open(file) { |f| f.read }.
|
||||
include?($INPUT_RECORD_SEPARATOR),
|
||||
"@row_sep did not default" )
|
||||
File.unlink(file)
|
||||
end
|
||||
|
||||
def test_version
|
||||
assert_not_nil(CSV::VERSION)
|
||||
assert_instance_of(String, CSV::VERSION)
|
||||
assert(CSV::VERSION.frozen?)
|
||||
assert_match(/\A\d\.\d\.\d\Z/, CSV::VERSION)
|
||||
end
|
||||
end
|
261
test/csv/tc_headers.rb
Normal file
261
test/csv/tc_headers.rb
Normal file
|
@ -0,0 +1,261 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_headers.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVHeaders < Test::Unit::TestCase
|
||||
def setup
|
||||
@data = <<-END_CSV.gsub(/^\s+/, "")
|
||||
first,second,third
|
||||
A,B,C
|
||||
1,2,3
|
||||
END_CSV
|
||||
end
|
||||
|
||||
def test_first_row
|
||||
[:first_row, true].each do |setting| # two names for the same setting
|
||||
# activate headers
|
||||
csv = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => setting)
|
||||
end
|
||||
|
||||
# first data row - skipping headers
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
|
||||
|
||||
# second data row
|
||||
row = csv[1]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
|
||||
|
||||
# empty
|
||||
assert_nil(csv[2])
|
||||
end
|
||||
end
|
||||
|
||||
def test_array_of_headers
|
||||
# activate headers
|
||||
csv = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => [:my, :new, :headers])
|
||||
end
|
||||
|
||||
# first data row - skipping headers
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal( [[:my, "first"], [:new, "second"], [:headers, "third"]],
|
||||
row.to_a )
|
||||
|
||||
# second data row
|
||||
row = csv[1]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([[:my, "A"], [:new, "B"], [:headers, "C"]], row.to_a)
|
||||
|
||||
# third data row
|
||||
row = csv[2]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([[:my, "1"], [:new, "2"], [:headers, "3"]], row.to_a)
|
||||
|
||||
# empty
|
||||
assert_nil(csv[3])
|
||||
|
||||
# with return and convert
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => [:my, :new, :headers],
|
||||
:return_headers => true,
|
||||
:header_converters => lambda { |h| h.to_s } )
|
||||
end
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([["my", :my], ["new", :new], ["headers", :headers]], row.to_a)
|
||||
assert(row.header_row?)
|
||||
assert(!row.field_row?)
|
||||
end
|
||||
|
||||
def test_csv_header_string
|
||||
# activate headers
|
||||
csv = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => "my,new,headers")
|
||||
end
|
||||
|
||||
# first data row - skipping headers
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
|
||||
|
||||
# second data row
|
||||
row = csv[1]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{my A}, %w{new B}, %w{headers C}], row.to_a)
|
||||
|
||||
# third data row
|
||||
row = csv[2]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{my 1}, %w{new 2}, %w{headers 3}], row.to_a)
|
||||
|
||||
# empty
|
||||
assert_nil(csv[3])
|
||||
|
||||
# with return and convert
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => "my,new,headers",
|
||||
:return_headers => true,
|
||||
:header_converters => :symbol )
|
||||
end
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([[:my, "my"], [:new, "new"], [:headers, "headers"]], row.to_a)
|
||||
assert(row.header_row?)
|
||||
assert(!row.field_row?)
|
||||
end
|
||||
|
||||
def test_return_headers
|
||||
# activate headers and request they are returned
|
||||
csv = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => true, :return_headers => true)
|
||||
end
|
||||
|
||||
# header row
|
||||
row = csv[0]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal( [%w{first first}, %w{second second}, %w{third third}],
|
||||
row.to_a )
|
||||
assert(row.header_row?)
|
||||
assert(!row.field_row?)
|
||||
|
||||
# first data row - skipping headers
|
||||
row = csv[1]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
|
||||
assert(!row.header_row?)
|
||||
assert(row.field_row?)
|
||||
|
||||
# second data row
|
||||
row = csv[2]
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
|
||||
assert(!row.header_row?)
|
||||
assert(row.field_row?)
|
||||
|
||||
# empty
|
||||
assert_nil(csv[3])
|
||||
end
|
||||
|
||||
def test_converters
|
||||
# create test data where headers and fields look alike
|
||||
data = <<-END_MATCHING_CSV.gsub(/^\s+/, "")
|
||||
1,2,3
|
||||
1,2,3
|
||||
END_MATCHING_CSV
|
||||
|
||||
# normal converters do not affect headers
|
||||
csv = CSV.parse( data, :headers => true,
|
||||
:return_headers => true,
|
||||
:converters => :numeric )
|
||||
assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv[0].to_a)
|
||||
assert_equal([["1", 1], ["2", 2], ["3", 3]], csv[1].to_a)
|
||||
assert_nil(csv[2])
|
||||
|
||||
# header converters do affect headers (only)
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse( data, :headers => true,
|
||||
:return_headers => true,
|
||||
:converters => :numeric,
|
||||
:header_converters => :symbol )
|
||||
end
|
||||
assert_equal([[:"1", "1"], [:"2", "2"], [:"3", "3"]], csv[0].to_a)
|
||||
assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv[1].to_a)
|
||||
assert_nil(csv[2])
|
||||
end
|
||||
|
||||
def test_builtin_downcase_converter
|
||||
csv = CSV.parse( "One,TWO Three", :headers => true,
|
||||
:return_headers => true,
|
||||
:header_converters => :downcase )
|
||||
assert_equal(%w{one two\ three}, csv.headers)
|
||||
end
|
||||
|
||||
def test_builtin_symbol_converter
|
||||
csv = CSV.parse( "One,TWO Three", :headers => true,
|
||||
:return_headers => true,
|
||||
:header_converters => :symbol )
|
||||
assert_equal([:one, :two_three], csv.headers)
|
||||
end
|
||||
|
||||
def test_custom_converter
|
||||
converter = lambda { |header| header.tr(" ", "_") }
|
||||
csv = CSV.parse( "One,TWO Three",
|
||||
:headers => true,
|
||||
:return_headers => true,
|
||||
:header_converters => converter )
|
||||
assert_equal(%w{One TWO_Three}, csv.headers)
|
||||
end
|
||||
|
||||
def test_table_support
|
||||
csv = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
csv = CSV.parse(@data, :headers => true)
|
||||
end
|
||||
|
||||
assert_instance_of(CSV::Table, csv)
|
||||
end
|
||||
|
||||
def test_skip_blanks
|
||||
@data = <<-END_CSV.gsub(/^ +/, "")
|
||||
|
||||
|
||||
A,B,C
|
||||
|
||||
1,2,3
|
||||
|
||||
|
||||
|
||||
END_CSV
|
||||
|
||||
expected = [%w[1 2 3]]
|
||||
CSV.parse(@data, :headers => true, :skip_blanks => true) do |row|
|
||||
assert_equal(expected.shift, row.fields)
|
||||
end
|
||||
|
||||
expected = [%w[A B C], %w[1 2 3]]
|
||||
CSV.parse( @data,
|
||||
:headers => true,
|
||||
:return_headers => true,
|
||||
:skip_blanks => true ) do |row|
|
||||
assert_equal(expected.shift, row.fields)
|
||||
end
|
||||
end
|
||||
|
||||
def test_blank_row_bug_fix
|
||||
@data += "\n#{@data}" # add a blank row
|
||||
|
||||
# ensure that everything returned is a Row object
|
||||
CSV.parse(@data, :headers => true) do |row|
|
||||
assert_instance_of(CSV::Row, row)
|
||||
end
|
||||
end
|
||||
end
|
235
test/csv/tc_interface.rb
Normal file
235
test/csv/tc_interface.rb
Normal file
|
@ -0,0 +1,235 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_interface.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVInterface < Test::Unit::TestCase
|
||||
def setup
|
||||
@path = File.join(File.dirname(__FILE__), "temp_test_data.csv")
|
||||
|
||||
File.open(@path, "w") do |file|
|
||||
file << "1\t2\t3\r\n"
|
||||
file << "4\t5\r\n"
|
||||
end
|
||||
|
||||
@expected = [%w{1 2 3}, %w{4 5}]
|
||||
end
|
||||
|
||||
def teardown
|
||||
File.unlink(@path)
|
||||
end
|
||||
|
||||
### Test Read Interface ###
|
||||
|
||||
def test_foreach
|
||||
CSV.foreach(@path, :col_sep => "\t", :row_sep => "\r\n") do |row|
|
||||
assert_equal(@expected.shift, row)
|
||||
end
|
||||
end
|
||||
|
||||
def test_open_and_close
|
||||
csv = CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n")
|
||||
assert_not_nil(csv)
|
||||
assert_instance_of(CSV, csv)
|
||||
assert_equal(false, csv.closed?)
|
||||
csv.close
|
||||
assert(csv.closed?)
|
||||
|
||||
ret = CSV.open(@path) do |csv|
|
||||
assert_instance_of(CSV, csv)
|
||||
"Return value."
|
||||
end
|
||||
assert(csv.closed?)
|
||||
assert_equal("Return value.", ret)
|
||||
end
|
||||
|
||||
def test_parse
|
||||
data = File.read(@path)
|
||||
assert_equal( @expected,
|
||||
CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") )
|
||||
|
||||
CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") do |row|
|
||||
assert_equal(@expected.shift, row)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parse_line
|
||||
row = CSV.parse_line("1;2;3", :col_sep => ";")
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(Array, row)
|
||||
assert_equal(%w{1 2 3}, row)
|
||||
|
||||
# shortcut interface
|
||||
row = "1;2;3".parse_csv(:col_sep => ";")
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(Array, row)
|
||||
assert_equal(%w{1 2 3}, row)
|
||||
end
|
||||
|
||||
def test_read_and_readlines
|
||||
assert_equal( @expected,
|
||||
CSV.read(@path, :col_sep => "\t", :row_sep => "\r\n") )
|
||||
assert_equal( @expected,
|
||||
CSV.readlines(@path, :col_sep => "\t", :row_sep => "\r\n") )
|
||||
|
||||
|
||||
data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
|
||||
csv.read
|
||||
end
|
||||
assert_equal(@expected, data)
|
||||
data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
|
||||
csv.readlines
|
||||
end
|
||||
assert_equal(@expected, data)
|
||||
end
|
||||
|
||||
def test_table
|
||||
table = CSV.table(@path, :col_sep => "\t", :row_sep => "\r\n")
|
||||
assert_instance_of(CSV::Table, table)
|
||||
assert_equal([[:"1", :"2", :"3"], [4, 5, nil]], table.to_a)
|
||||
end
|
||||
|
||||
def test_shift # aliased as gets() and readline()
|
||||
CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n") do |csv|
|
||||
assert_equal(@expected.shift, csv.shift)
|
||||
assert_equal(@expected.shift, csv.shift)
|
||||
assert_equal(nil, csv.shift)
|
||||
end
|
||||
end
|
||||
|
||||
### Test Write Interface ###
|
||||
|
||||
def test_generate
|
||||
str = CSV.generate do |csv| # default empty String
|
||||
assert_instance_of(CSV, csv)
|
||||
assert_equal(csv, csv << [1, 2, 3])
|
||||
assert_equal(csv, csv << [4, nil, 5])
|
||||
end
|
||||
assert_not_nil(str)
|
||||
assert_instance_of(String, str)
|
||||
assert_equal("1,2,3\n4,,5\n", str)
|
||||
|
||||
CSV.generate(str) do |csv| # appending to a String
|
||||
assert_equal(csv, csv << ["last", %Q{"row"}])
|
||||
end
|
||||
assert_equal(%Q{1,2,3\n4,,5\nlast,"""row"""\n}, str)
|
||||
end
|
||||
|
||||
def test_generate_line
|
||||
line = CSV.generate_line(%w{1 2 3}, :col_sep => ";")
|
||||
assert_not_nil(line)
|
||||
assert_instance_of(String, line)
|
||||
assert_equal("1;2;3\n", line)
|
||||
|
||||
# shortcut interface
|
||||
line = %w{1 2 3}.to_csv(:col_sep => ";")
|
||||
assert_not_nil(line)
|
||||
assert_instance_of(String, line)
|
||||
assert_equal("1;2;3\n", line)
|
||||
end
|
||||
|
||||
def test_write_header_detection
|
||||
File.unlink(@path)
|
||||
|
||||
headers = %w{a b c}
|
||||
CSV.open(@path, "w", :headers => true) do |csv|
|
||||
csv << headers
|
||||
csv << %w{1 2 3}
|
||||
assert_equal(headers, csv.instance_variable_get(:@headers))
|
||||
end
|
||||
end
|
||||
|
||||
def test_write_lineno
|
||||
File.unlink(@path)
|
||||
|
||||
CSV.open(@path, "w") do |csv|
|
||||
lines = 20
|
||||
lines.times { csv << %w{a b c} }
|
||||
assert_equal(lines, csv.lineno)
|
||||
end
|
||||
end
|
||||
|
||||
def test_write_hash
|
||||
File.unlink(@path)
|
||||
|
||||
lines = [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
|
||||
CSV.open( @path, "w", :headers => true,
|
||||
:converters => :all,
|
||||
:header_converters => :symbol ) do |csv|
|
||||
csv << lines.first.keys
|
||||
lines.each { |line| csv << line }
|
||||
end
|
||||
CSV.open( @path, "w", :headers => true,
|
||||
:converters => :all,
|
||||
:header_converters => :symbol ) do |csv|
|
||||
csv.each { |line| assert_equal(lines.shift, line.to_hash) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_append # aliased add_row() and puts()
|
||||
File.unlink(@path)
|
||||
|
||||
CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
|
||||
@expected.each { |row| csv << row }
|
||||
end
|
||||
|
||||
test_shift
|
||||
|
||||
# same thing using CSV::Row objects
|
||||
File.unlink(@path)
|
||||
|
||||
CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
|
||||
@expected.each { |row| csv << CSV::Row.new(Array.new, row) }
|
||||
end
|
||||
|
||||
test_shift
|
||||
end
|
||||
|
||||
### Test Read and Write Interface ###
|
||||
|
||||
def test_filter
|
||||
assert_respond_to(CSV, :filter)
|
||||
|
||||
expected = [[1, 2, 3], [4, 5]]
|
||||
CSV.filter( "1;2;3\n4;5\n", (result = String.new),
|
||||
:in_col_sep => ";", :out_col_sep => ",",
|
||||
:converters => :all ) do |row|
|
||||
assert_equal(row, expected.shift)
|
||||
row.map! { |n| n * 2 }
|
||||
row << "Added\r"
|
||||
end
|
||||
assert_equal("2,4,6,\"Added\r\"\n8,10,\"Added\r\"\n", result)
|
||||
end
|
||||
|
||||
def test_instance
|
||||
csv = String.new
|
||||
|
||||
first = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
first = CSV.instance(csv, :col_sep => ";")
|
||||
first << %w{a b c}
|
||||
end
|
||||
|
||||
assert_equal("a;b;c\n", csv)
|
||||
|
||||
second = nil
|
||||
assert_nothing_raised(Exception) do
|
||||
second = CSV.instance(csv, :col_sep => ";")
|
||||
second << [1, 2, 3]
|
||||
end
|
||||
|
||||
assert_equal(first.object_id, second.object_id)
|
||||
assert_equal("a;b;c\n1;2;3\n", csv)
|
||||
|
||||
# shortcuts
|
||||
assert_equal(STDOUT, CSV.instance.instance_eval { @io })
|
||||
assert_equal(STDOUT, CSV { |csv| csv.instance_eval { @io } })
|
||||
end
|
||||
end
|
289
test/csv/tc_row.rb
Normal file
289
test/csv/tc_row.rb
Normal file
|
@ -0,0 +1,289 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_row.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVRow < Test::Unit::TestCase
|
||||
def setup
|
||||
@row = CSV::Row.new(%w{A B C A A}, [1, 2, 3, 4])
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
# basic
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2, 3])
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([["A", 1], ["B", 2], ["C", 3]], row.to_a)
|
||||
|
||||
# missing headers
|
||||
row = CSV::Row.new(%w{A}, [1, 2, 3])
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([["A", 1], [nil, 2], [nil, 3]], row.to_a)
|
||||
|
||||
# missing fields
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2])
|
||||
assert_not_nil(row)
|
||||
assert_instance_of(CSV::Row, row)
|
||||
assert_equal([["A", 1], ["B", 2], ["C", nil]], row.to_a)
|
||||
end
|
||||
|
||||
def test_row_type
|
||||
# field rows
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2, 3]) # implicit
|
||||
assert(!row.header_row?)
|
||||
assert(row.field_row?)
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2, 3], false) # explicit
|
||||
assert(!row.header_row?)
|
||||
assert(row.field_row?)
|
||||
|
||||
# header row
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2, 3], true)
|
||||
assert(row.header_row?)
|
||||
assert(!row.field_row?)
|
||||
end
|
||||
|
||||
def test_headers
|
||||
assert_equal(%w{A B C A A}, @row.headers)
|
||||
end
|
||||
|
||||
def test_field
|
||||
# by name
|
||||
assert_equal(2, @row.field("B"))
|
||||
assert_equal(2, @row["B"]) # alias
|
||||
|
||||
# by index
|
||||
assert_equal(3, @row.field(2))
|
||||
|
||||
# missing
|
||||
assert_nil(@row.field("Missing"))
|
||||
assert_nil(@row.field(10))
|
||||
|
||||
# minimum index
|
||||
assert_equal(1, @row.field("A"))
|
||||
assert_equal(1, @row.field("A", 0))
|
||||
assert_equal(4, @row.field("A", 1))
|
||||
assert_equal(4, @row.field("A", 2))
|
||||
assert_equal(4, @row.field("A", 3))
|
||||
assert_equal(nil, @row.field("A", 4))
|
||||
assert_equal(nil, @row.field("A", 5))
|
||||
end
|
||||
|
||||
def test_set_field
|
||||
# set field by name
|
||||
assert_equal(100, @row["A"] = 100)
|
||||
|
||||
# set field by index
|
||||
assert_equal(300, @row[3] = 300)
|
||||
|
||||
# set field by name and minimum index
|
||||
assert_equal([:a, :b, :c], @row["A", 4] = [:a, :b, :c])
|
||||
|
||||
# verify the changes
|
||||
assert_equal( [ ["A", 100],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 300],
|
||||
["A", [:a, :b, :c]] ], @row.to_a )
|
||||
|
||||
# assigning an index past the end
|
||||
assert_equal("End", @row[10] = "End")
|
||||
assert_equal( [ ["A", 100],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 300],
|
||||
["A", [:a, :b, :c]],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, "End"] ], @row.to_a )
|
||||
|
||||
# assigning a new field by header
|
||||
assert_equal("New", @row[:new] = "New")
|
||||
assert_equal( [ ["A", 100],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 300],
|
||||
["A", [:a, :b, :c]],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, nil],
|
||||
[nil, "End"],
|
||||
[:new, "New"] ], @row.to_a )
|
||||
end
|
||||
|
||||
def test_append
|
||||
# add a value
|
||||
assert_equal(@row, @row << "Value")
|
||||
assert_equal( [ ["A", 1],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 4],
|
||||
["A", nil],
|
||||
[nil, "Value"] ], @row.to_a )
|
||||
|
||||
# add a pair
|
||||
assert_equal(@row, @row << %w{Header Field})
|
||||
assert_equal( [ ["A", 1],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 4],
|
||||
["A", nil],
|
||||
[nil, "Value"],
|
||||
%w{Header Field} ], @row.to_a )
|
||||
|
||||
# a pair with Hash syntax
|
||||
assert_equal(@row, @row << {:key => :value})
|
||||
assert_equal( [ ["A", 1],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 4],
|
||||
["A", nil],
|
||||
[nil, "Value"],
|
||||
%w{Header Field},
|
||||
[:key, :value] ], @row.to_a )
|
||||
|
||||
# multiple fields at once
|
||||
assert_equal(@row, @row.push(100, 200, [:last, 300]))
|
||||
assert_equal( [ ["A", 1],
|
||||
["B", 2],
|
||||
["C", 3],
|
||||
["A", 4],
|
||||
["A", nil],
|
||||
[nil, "Value"],
|
||||
%w{Header Field},
|
||||
[:key, :value],
|
||||
[nil, 100],
|
||||
[nil, 200],
|
||||
[:last, 300] ], @row.to_a )
|
||||
end
|
||||
|
||||
def test_delete
|
||||
# by index
|
||||
assert_equal(["B", 2], @row.delete(1))
|
||||
|
||||
# by header
|
||||
assert_equal(["C", 3], @row.delete("C"))
|
||||
|
||||
# using a block
|
||||
assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? })
|
||||
assert_equal([["A", nil]], @row.to_a)
|
||||
end
|
||||
|
||||
def test_fields
|
||||
# all fields
|
||||
assert_equal([1, 2, 3, 4, nil], @row.fields)
|
||||
|
||||
# by header
|
||||
assert_equal([1, 3], @row.fields("A", "C"))
|
||||
|
||||
# by index
|
||||
assert_equal([2, 3, nil], @row.fields(1, 2, 10))
|
||||
|
||||
# by both
|
||||
assert_equal([2, 3, 4], @row.fields("B", "C", 3))
|
||||
|
||||
# with minimum indices
|
||||
assert_equal([2, 3, 4], @row.fields("B", "C", ["A", 3]))
|
||||
|
||||
# by header range
|
||||
assert_equal([2, 3], @row.values_at("B".."C"))
|
||||
end
|
||||
|
||||
def test_index
|
||||
# basic usage
|
||||
assert_equal(0, @row.index("A"))
|
||||
assert_equal(1, @row.index("B"))
|
||||
assert_equal(2, @row.index("C"))
|
||||
assert_equal(nil, @row.index("Z"))
|
||||
|
||||
# with minimum index
|
||||
assert_equal(0, @row.index("A"))
|
||||
assert_equal(0, @row.index("A", 0))
|
||||
assert_equal(3, @row.index("A", 1))
|
||||
assert_equal(3, @row.index("A", 2))
|
||||
assert_equal(3, @row.index("A", 3))
|
||||
assert_equal(4, @row.index("A", 4))
|
||||
assert_equal(nil, @row.index("A", 5))
|
||||
end
|
||||
|
||||
def test_queries
|
||||
# headers
|
||||
assert(@row.header?("A"))
|
||||
assert(@row.header?("C"))
|
||||
assert(!@row.header?("Z"))
|
||||
assert(@row.include?("A")) # alias
|
||||
|
||||
# fields
|
||||
assert(@row.field?(4))
|
||||
assert(@row.field?(nil))
|
||||
assert(!@row.field?(10))
|
||||
end
|
||||
|
||||
def test_each
|
||||
# array style
|
||||
ary = @row.to_a
|
||||
@row.each do |pair|
|
||||
assert_equal(ary.first.first, pair.first)
|
||||
assert_equal(ary.shift.last, pair.last)
|
||||
end
|
||||
|
||||
# hash style
|
||||
ary = @row.to_a
|
||||
@row.each do |header, field|
|
||||
assert_equal(ary.first.first, header)
|
||||
assert_equal(ary.shift.last, field)
|
||||
end
|
||||
|
||||
# verify that we can chain the call
|
||||
assert_equal(@row, @row.each { })
|
||||
end
|
||||
|
||||
def test_enumerable
|
||||
assert_equal( [["A", 1], ["A", 4], ["A", nil]],
|
||||
@row.select { |pair| pair.first == "A" } )
|
||||
|
||||
assert_equal(10, @row.inject(0) { |sum, (header, n)| sum + (n || 0) })
|
||||
end
|
||||
|
||||
def test_to_a
|
||||
row = CSV::Row.new(%w{A B C}, [1, 2, 3]).to_a
|
||||
assert_instance_of(Array, row)
|
||||
row.each do |pair|
|
||||
assert_instance_of(Array, pair)
|
||||
assert_equal(2, pair.size)
|
||||
end
|
||||
assert_equal([["A", 1], ["B", 2], ["C", 3]], row)
|
||||
end
|
||||
|
||||
def test_to_hash
|
||||
assert_equal({"A" => nil, "B" => 2, "C" => 3}, @row.to_hash)
|
||||
end
|
||||
|
||||
def test_to_csv
|
||||
# normal conversion
|
||||
assert_equal("1,2,3,4,\n", @row.to_csv)
|
||||
assert_equal("1,2,3,4,\n", @row.to_s) # alias
|
||||
|
||||
# with options
|
||||
assert_equal( "1|2|3|4|\r\n",
|
||||
@row.to_csv(:col_sep => "|", :row_sep => "\r\n") )
|
||||
end
|
||||
|
||||
def test_array_delegation
|
||||
assert(!@row.empty?, "Row was empty.")
|
||||
|
||||
assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
|
||||
end
|
||||
end
|
155
test/csv/tc_serialization.rb
Normal file
155
test/csv/tc_serialization.rb
Normal file
|
@ -0,0 +1,155 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_serialization.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
# An example of how to provide custom CSV serialization.
|
||||
class Hash
|
||||
def self.csv_load( meta, headers, fields )
|
||||
self[*headers.zip(fields).flatten.map { |e| eval(e) }]
|
||||
end
|
||||
|
||||
def csv_headers
|
||||
keys.map { |key| key.inspect }
|
||||
end
|
||||
|
||||
def csv_dump( headers )
|
||||
headers.map { |header| fetch(eval(header)).inspect }
|
||||
end
|
||||
end
|
||||
|
||||
class TestSerialization < Test::Unit::TestCase
|
||||
|
||||
### Classes Used to Test Serialization ###
|
||||
|
||||
class ReadOnlyName
|
||||
def initialize( first, last )
|
||||
@first, @last = first, last
|
||||
end
|
||||
|
||||
attr_reader :first, :last
|
||||
|
||||
def ==( other )
|
||||
%w{first last}.all? { |att| send(att) == other.send(att) }
|
||||
end
|
||||
end
|
||||
|
||||
Name = Struct.new(:first, :last)
|
||||
|
||||
class FullName < Name
|
||||
def initialize( first, last, suffix = nil )
|
||||
super(first, last)
|
||||
|
||||
@suffix = suffix
|
||||
end
|
||||
|
||||
attr_accessor :suffix
|
||||
|
||||
def ==( other )
|
||||
%w{first last suffix}.all? { |att| send(att) == other.send(att) }
|
||||
end
|
||||
end
|
||||
|
||||
### Tests ###
|
||||
|
||||
def test_class_dump
|
||||
@names = [ %w{James Gray},
|
||||
%w{Dana Gray},
|
||||
%w{Greg Brown} ].map do |first, last|
|
||||
ReadOnlyName.new(first, last)
|
||||
end
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
@data = CSV.dump(@names)
|
||||
end
|
||||
assert_equal(<<-END_CLASS_DUMP.gsub(/^\s*/, ""), @data)
|
||||
class,TestSerialization::ReadOnlyName
|
||||
@first,@last
|
||||
James,Gray
|
||||
Dana,Gray
|
||||
Greg,Brown
|
||||
END_CLASS_DUMP
|
||||
end
|
||||
|
||||
def test_struct_dump
|
||||
@names = [ %w{James Gray},
|
||||
%w{Dana Gray},
|
||||
%w{Greg Brown} ].map do |first, last|
|
||||
Name.new(first, last)
|
||||
end
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
@data = CSV.dump(@names)
|
||||
end
|
||||
assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
|
||||
class,TestSerialization::Name
|
||||
first=,last=
|
||||
James,Gray
|
||||
Dana,Gray
|
||||
Greg,Brown
|
||||
END_STRUCT_DUMP
|
||||
end
|
||||
|
||||
def test_inherited_struct_dump
|
||||
@names = [ %w{James Gray II},
|
||||
%w{Dana Gray},
|
||||
%w{Greg Brown} ].map do |first, last, suffix|
|
||||
FullName.new(first, last, suffix)
|
||||
end
|
||||
|
||||
assert_nothing_raised(Exception) do
|
||||
@data = CSV.dump(@names)
|
||||
end
|
||||
assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
|
||||
class,TestSerialization::FullName
|
||||
@suffix,first=,last=
|
||||
II,James,Gray
|
||||
,Dana,Gray
|
||||
,Greg,Brown
|
||||
END_STRUCT_DUMP
|
||||
end
|
||||
|
||||
def test_load
|
||||
%w{ test_class_dump
|
||||
test_struct_dump
|
||||
test_inherited_struct_dump }.each do |test|
|
||||
send(test)
|
||||
CSV.load(@data).each do |loaded|
|
||||
assert_instance_of(@names.first.class, loaded)
|
||||
assert_equal(@names.shift, loaded)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_io
|
||||
test_class_dump
|
||||
|
||||
data_file = File.join(File.dirname(__FILE__), "temp_test_data.csv")
|
||||
CSV.dump(@names, File.open(data_file, "w"))
|
||||
|
||||
assert(File.exist?(data_file))
|
||||
assert_equal(<<-END_IO_DUMP.gsub(/^\s*/, ""), File.read(data_file))
|
||||
class,TestSerialization::ReadOnlyName
|
||||
@first,@last
|
||||
James,Gray
|
||||
Dana,Gray
|
||||
Greg,Brown
|
||||
END_IO_DUMP
|
||||
|
||||
assert_equal(@names, CSV.load(File.open(data_file)))
|
||||
|
||||
File.unlink(data_file)
|
||||
end
|
||||
|
||||
def test_custom_dump_and_load
|
||||
obj = {1 => "simple", :test => Hash}
|
||||
assert_equal(obj, CSV.load(CSV.dump([obj])).first)
|
||||
end
|
||||
end
|
392
test/csv/tc_table.rb
Normal file
392
test/csv/tc_table.rb
Normal file
|
@ -0,0 +1,392 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# tc_table.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "csv"
|
||||
|
||||
class TestCSVTable < Test::Unit::TestCase
|
||||
def setup
|
||||
@rows = [ CSV::Row.new(%w{A B C}, [1, 2, 3]),
|
||||
CSV::Row.new(%w{A B C}, [4, 5, 6]),
|
||||
CSV::Row.new(%w{A B C}, [7, 8, 9]) ]
|
||||
@table = CSV::Table.new(@rows)
|
||||
|
||||
@header_table = CSV::Table.new(
|
||||
[CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
|
||||
)
|
||||
end
|
||||
|
||||
def test_initialze
|
||||
assert_not_nil(@table)
|
||||
assert_instance_of(CSV::Table, @table)
|
||||
end
|
||||
|
||||
def test_modes
|
||||
assert_equal(:col_or_row, @table.mode)
|
||||
|
||||
# non-destructive changes, intended for one shot calls
|
||||
cols = @table.by_col
|
||||
assert_equal(:col_or_row, @table.mode)
|
||||
assert_equal(:col, cols.mode)
|
||||
assert_equal(@table, cols)
|
||||
|
||||
rows = @table.by_row
|
||||
assert_equal(:col_or_row, @table.mode)
|
||||
assert_equal(:row, rows.mode)
|
||||
assert_equal(@table, rows)
|
||||
|
||||
# destructive mode changing calls
|
||||
assert_equal(@table, @table.by_row!)
|
||||
assert_equal(:row, @table.mode)
|
||||
assert_equal(@table, @table.by_col_or_row!)
|
||||
assert_equal(:col_or_row, @table.mode)
|
||||
end
|
||||
|
||||
def test_headers
|
||||
assert_equal(@rows.first.headers, @table.headers)
|
||||
end
|
||||
|
||||
def test_index
|
||||
##################
|
||||
### Mixed Mode ###
|
||||
##################
|
||||
# by row
|
||||
@rows.each_index { |i| assert_equal(@rows[i], @table[i]) }
|
||||
assert_equal(nil, @table[100]) # empty row
|
||||
|
||||
# by col
|
||||
@rows.first.headers.each do |header|
|
||||
assert_equal(@rows.map { |row| row[header] }, @table[header])
|
||||
end
|
||||
assert_equal([nil] * @rows.size, @table["Z"]) # empty col
|
||||
|
||||
# by cell, row then col
|
||||
assert_equal(2, @table[0][1])
|
||||
assert_equal(6, @table[1]["C"])
|
||||
|
||||
# by cell, col then row
|
||||
assert_equal(5, @table["B"][1])
|
||||
assert_equal(9, @table["C"][2])
|
||||
|
||||
# with headers (by col)
|
||||
assert_equal(["B", 2, 5, 8], @header_table["B"])
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
@table.by_col!
|
||||
|
||||
assert_equal([2, 5, 8], @table[1])
|
||||
assert_equal([2, 5, 8], @table["B"])
|
||||
|
||||
################
|
||||
### Row Mode ###
|
||||
################
|
||||
@table.by_row!
|
||||
|
||||
assert_equal(@rows[1], @table[1])
|
||||
assert_raise(TypeError) { @table["B"] }
|
||||
|
||||
############################
|
||||
### One Shot Mode Change ###
|
||||
############################
|
||||
assert_equal(@rows[1], @table[1])
|
||||
assert_equal([2, 5, 8], @table.by_col[1])
|
||||
assert_equal(@rows[1], @table[1])
|
||||
end
|
||||
|
||||
def test_set_row_or_column
|
||||
##################
|
||||
### Mixed Mode ###
|
||||
##################
|
||||
# set row
|
||||
@table[2] = [10, 11, 12]
|
||||
assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a)
|
||||
|
||||
@table[3] = CSV::Row.new(%w[A B C], [13, 14, 15])
|
||||
assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]],
|
||||
@table.to_a )
|
||||
|
||||
# set col
|
||||
@table["Type"] = "data"
|
||||
assert_equal( [ %w[A B C Type],
|
||||
[1, 2, 3, "data"],
|
||||
[4, 5, 6, "data"],
|
||||
[10, 11, 12, "data"],
|
||||
[13, 14, 15, "data"] ],
|
||||
@table.to_a )
|
||||
|
||||
@table["Index"] = [1, 2, 3]
|
||||
assert_equal( [ %w[A B C Type Index],
|
||||
[1, 2, 3, "data", 1],
|
||||
[4, 5, 6, "data", 2],
|
||||
[10, 11, 12, "data", 3],
|
||||
[13, 14, 15, "data", nil] ],
|
||||
@table.to_a )
|
||||
|
||||
@table["B"] = [100, 200]
|
||||
assert_equal( [ %w[A B C Type Index],
|
||||
[1, 100, 3, "data", 1],
|
||||
[4, 200, 6, "data", 2],
|
||||
[10, nil, 12, "data", 3],
|
||||
[13, nil, 15, "data", nil] ],
|
||||
@table.to_a )
|
||||
|
||||
# verify resulting table
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
A,B,C,Type,Index
|
||||
1,100,3,data,1
|
||||
4,200,6,data,2
|
||||
10,,12,data,3
|
||||
13,,15,data,
|
||||
END_RESULT
|
||||
|
||||
# with headers
|
||||
@header_table["Type"] = "data"
|
||||
assert_equal(%w[Type data data data], @header_table["Type"])
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
@table.by_col!
|
||||
|
||||
@table[1] = [2, 5, 11, 14]
|
||||
assert_equal( [ %w[A B C Type Index],
|
||||
[1, 2, 3, "data", 1],
|
||||
[4, 5, 6, "data", 2],
|
||||
[10, 11, 12, "data", 3],
|
||||
[13, 14, 15, "data", nil] ],
|
||||
@table.to_a )
|
||||
|
||||
@table["Extra"] = "new stuff"
|
||||
assert_equal( [ %w[A B C Type Index Extra],
|
||||
[1, 2, 3, "data", 1, "new stuff"],
|
||||
[4, 5, 6, "data", 2, "new stuff"],
|
||||
[10, 11, 12, "data", 3, "new stuff"],
|
||||
[13, 14, 15, "data", nil, "new stuff"] ],
|
||||
@table.to_a )
|
||||
|
||||
################
|
||||
### Row Mode ###
|
||||
################
|
||||
@table.by_row!
|
||||
|
||||
@table[1] = (1..6).to_a
|
||||
assert_equal( [ %w[A B C Type Index Extra],
|
||||
[1, 2, 3, "data", 1, "new stuff"],
|
||||
[1, 2, 3, 4, 5, 6],
|
||||
[10, 11, 12, "data", 3, "new stuff"],
|
||||
[13, 14, 15, "data", nil, "new stuff"] ],
|
||||
@table.to_a )
|
||||
|
||||
assert_raise(TypeError) { @table["Extra"] = nil }
|
||||
end
|
||||
|
||||
def test_each
|
||||
######################
|
||||
### Mixed/Row Mode ###
|
||||
######################
|
||||
i = 0
|
||||
@table.each do |row|
|
||||
assert_equal(@rows[i], row)
|
||||
i += 1
|
||||
end
|
||||
|
||||
# verify that we can chain the call
|
||||
assert_equal(@table, @table.each { })
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
@table.by_col!
|
||||
|
||||
headers = @table.headers
|
||||
@table.each do |header, column|
|
||||
assert_equal(headers.shift, header)
|
||||
assert_equal(@table[header], column)
|
||||
end
|
||||
|
||||
############################
|
||||
### One Shot Mode Change ###
|
||||
############################
|
||||
@table.by_col_or_row!
|
||||
|
||||
@table.each { |row| assert_instance_of(CSV::Row, row) }
|
||||
@table.by_col.each { |tuple| assert_instance_of(Array, tuple) }
|
||||
@table.each { |row| assert_instance_of(CSV::Row, row) }
|
||||
end
|
||||
|
||||
def test_enumerable
|
||||
assert_equal( @rows.values_at(0, 2),
|
||||
@table.select { |row| (row["B"] % 2).zero? } )
|
||||
|
||||
assert_equal(@rows[1], @table.find { |row| row["C"] > 5 })
|
||||
end
|
||||
|
||||
def test_to_a
|
||||
assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a)
|
||||
|
||||
# with headers
|
||||
assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]],
|
||||
@header_table.to_a )
|
||||
end
|
||||
|
||||
def test_to_csv
|
||||
csv = <<-END_CSV.gsub(/^\s+/, "")
|
||||
A,B,C
|
||||
1,2,3
|
||||
4,5,6
|
||||
7,8,9
|
||||
END_CSV
|
||||
|
||||
# normal conversion
|
||||
assert_equal(csv, @table.to_csv)
|
||||
assert_equal(csv, @table.to_s) # alias
|
||||
|
||||
# with options
|
||||
assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
|
||||
@table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
|
||||
|
||||
# with headers
|
||||
assert_equal(csv, @header_table.to_csv)
|
||||
end
|
||||
|
||||
def test_append
|
||||
# verify that we can chain the call
|
||||
assert_equal(@table, @table << [10, 11, 12])
|
||||
|
||||
# Array append
|
||||
assert_equal(CSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1])
|
||||
|
||||
# Row append
|
||||
assert_equal(@table, @table << CSV::Row.new(%w[A B C], [13, 14, 15]))
|
||||
assert_equal(CSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1])
|
||||
end
|
||||
|
||||
def test_delete
|
||||
##################
|
||||
### Mixed Mode ###
|
||||
##################
|
||||
# delete a row
|
||||
assert_equal(@rows[1], @table.delete(1))
|
||||
|
||||
# delete a col
|
||||
assert_equal(@rows.map { |row| row["A"] }, @table.delete("A"))
|
||||
|
||||
# verify resulting table
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
B,C
|
||||
2,3
|
||||
8,9
|
||||
END_RESULT
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
setup
|
||||
@table.by_col!
|
||||
|
||||
assert_equal(@rows.map { |row| row[0] }, @table.delete(0))
|
||||
assert_equal(@rows.map { |row| row["C"] }, @table.delete("C"))
|
||||
|
||||
# verify resulting table
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
B
|
||||
2
|
||||
5
|
||||
8
|
||||
END_RESULT
|
||||
|
||||
################
|
||||
### Row Mode ###
|
||||
################
|
||||
setup
|
||||
@table.by_row!
|
||||
|
||||
assert_equal(@rows[1], @table.delete(1))
|
||||
assert_raise(TypeError) { @table.delete("C") }
|
||||
|
||||
# verify resulting table
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
A,B,C
|
||||
1,2,3
|
||||
7,8,9
|
||||
END_RESULT
|
||||
end
|
||||
|
||||
def test_delete_if
|
||||
######################
|
||||
### Mixed/Row Mode ###
|
||||
######################
|
||||
# verify that we can chain the call
|
||||
assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? })
|
||||
|
||||
# verify resulting table
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
A,B,C
|
||||
4,5,6
|
||||
END_RESULT
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
setup
|
||||
@table.by_col!
|
||||
|
||||
assert_equal(@table, @table.delete_if { |h, v| h > "A" })
|
||||
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
|
||||
A
|
||||
1
|
||||
4
|
||||
7
|
||||
END_RESULT
|
||||
end
|
||||
|
||||
def test_values_at
|
||||
##################
|
||||
### Mixed Mode ###
|
||||
##################
|
||||
# rows
|
||||
assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
|
||||
assert_equal(@rows.values_at(1..2), @table.values_at(1..2))
|
||||
|
||||
# cols
|
||||
assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
|
||||
assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C"))
|
||||
|
||||
###################
|
||||
### Column Mode ###
|
||||
###################
|
||||
@table.by_col!
|
||||
|
||||
assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2))
|
||||
assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
|
||||
|
||||
################
|
||||
### Row Mode ###
|
||||
################
|
||||
@table.by_row!
|
||||
|
||||
assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
|
||||
assert_raise(TypeError) { @table.values_at("A", "C") }
|
||||
|
||||
############################
|
||||
### One Shot Mode Change ###
|
||||
############################
|
||||
assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
|
||||
assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
|
||||
assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
|
||||
end
|
||||
|
||||
def test_array_delegation
|
||||
assert(!@table.empty?, "Table was empty.")
|
||||
|
||||
assert_equal(@rows.size, @table.size)
|
||||
end
|
||||
end
|
19
test/csv/ts_all.rb
Normal file
19
test/csv/ts_all.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# ts_all.rb
|
||||
#
|
||||
# Created by James Edward Gray II on 2005-10-31.
|
||||
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
||||
# under the terms of Ruby's license.
|
||||
|
||||
require "test/unit"
|
||||
|
||||
require "tc_csv_parsing"
|
||||
require "tc_features"
|
||||
require "tc_interface"
|
||||
require "tc_csv_writing"
|
||||
require "tc_data_converters"
|
||||
require "tc_row"
|
||||
require "tc_table"
|
||||
require "tc_headers"
|
||||
require "tc_serialization"
|
Loading…
Add table
Reference in a new issue