rw_fastercsv 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_interface.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-11-14.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "faster_csv"
11
+
12
+ class TestFasterCSVRPCases < Test::Unit::TestCase
13
+ def setup
14
+ @path = File.join(File.dirname(__FILE__), "export.csv")
15
+ end
16
+
17
+ def teardown
18
+ # File.unlink(@path)
19
+ end
20
+
21
+ #RPBS-2760
22
+ def test_failed_export
23
+ lines = []
24
+ csv = FasterCSV.open(@path, :raise_exception => true)
25
+ assert_raise(FasterCSV::MalformedCSVError) do
26
+ while line = csv.gets
27
+ lines<<line
28
+ end
29
+ end
30
+ assert_equal(4,lines.size)
31
+ end
32
+
33
+ def test_success_export
34
+ lines = []
35
+ csv = FasterCSV.open(@path, :raise_exception => false)
36
+ assert_nothing_raised do
37
+ while line = csv.gets
38
+ lines<<line
39
+ end
40
+ end
41
+ assert_equal(5,lines.size)
42
+ end
43
+
44
+
45
+ end
@@ -0,0 +1,154 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_serialization.rb
4
+ #
5
+ # Created by James Edward Gray II on 2006-03-28.
6
+ # Copyright 2006 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "faster_csv"
11
+
12
+ # An example of how to provide custom CSV serialization.
13
+ class Hash
14
+ def self.csv_load( meta, headers, fields )
15
+ self[*headers.zip(fields).flatten.map { |e| eval(e) }]
16
+ end
17
+
18
+ def csv_headers
19
+ keys.map { |key| key.inspect }
20
+ end
21
+
22
+ def csv_dump( headers )
23
+ headers.map { |header| fetch(eval(header)).inspect }
24
+ end
25
+ end
26
+
27
+ class TestSerialization < Test::Unit::TestCase
28
+
29
+ ### Classes Used to Test Serialization ###
30
+
31
+ class ReadOnlyName
32
+ def initialize( first, last )
33
+ @first, @last = first, last
34
+ end
35
+
36
+ attr_reader :first, :last
37
+
38
+ def ==( other )
39
+ %w{first last}.all? { |att| send(att) == other.send(att) }
40
+ end
41
+ end
42
+
43
+ Name = Struct.new(:first, :last)
44
+
45
+ class FullName < Name
46
+ def initialize( first, last, suffix = nil )
47
+ super(first, last)
48
+
49
+ @suffix = suffix
50
+ end
51
+
52
+ attr_accessor :suffix
53
+
54
+ def ==( other )
55
+ %w{first last suffix}.all? { |att| send(att) == other.send(att) }
56
+ end
57
+ end
58
+
59
+ ### Tests ###
60
+
61
+ def test_class_dump
62
+ @names = [ %w{James Gray},
63
+ %w{Dana Gray},
64
+ %w{Greg Brown} ].map do |first, last|
65
+ ReadOnlyName.new(first, last)
66
+ end
67
+
68
+ assert_nothing_raised(Exception) do
69
+ @data = FasterCSV.dump(@names)
70
+ end
71
+ assert_equal(<<-END_CLASS_DUMP.gsub(/^\s*/, ""), @data)
72
+ class,TestSerialization::ReadOnlyName
73
+ @first,@last
74
+ James,Gray
75
+ Dana,Gray
76
+ Greg,Brown
77
+ END_CLASS_DUMP
78
+ end
79
+
80
+ def test_struct_dump
81
+ @names = [ %w{James Gray},
82
+ %w{Dana Gray},
83
+ %w{Greg Brown} ].map do |first, last|
84
+ Name.new(first, last)
85
+ end
86
+
87
+ assert_nothing_raised(Exception) do
88
+ @data = FasterCSV.dump(@names)
89
+ end
90
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
91
+ class,TestSerialization::Name
92
+ first=,last=
93
+ James,Gray
94
+ Dana,Gray
95
+ Greg,Brown
96
+ END_STRUCT_DUMP
97
+ end
98
+
99
+ def test_inherited_struct_dump
100
+ @names = [ %w{James Gray II},
101
+ %w{Dana Gray},
102
+ %w{Greg Brown} ].map do |first, last, suffix|
103
+ FullName.new(first, last, suffix)
104
+ end
105
+
106
+ assert_nothing_raised(Exception) do
107
+ @data = FasterCSV.dump(@names)
108
+ end
109
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
110
+ class,TestSerialization::FullName
111
+ @suffix,first=,last=
112
+ II,James,Gray
113
+ ,Dana,Gray
114
+ ,Greg,Brown
115
+ END_STRUCT_DUMP
116
+ end
117
+
118
+ def test_load
119
+ %w{ test_class_dump
120
+ test_struct_dump
121
+ test_inherited_struct_dump }.each do |test|
122
+ send(test)
123
+ FasterCSV.load(@data).each do |loaded|
124
+ assert_instance_of(@names.first.class, loaded)
125
+ assert_equal(@names.shift, loaded)
126
+ end
127
+ end
128
+ end
129
+
130
+ def test_io
131
+ test_class_dump
132
+
133
+ data_file = File.join(File.dirname(__FILE__), "temp_test_data.csv")
134
+ FasterCSV.dump(@names, File.open(data_file, "w"))
135
+
136
+ assert(File.exist?(data_file))
137
+ assert_equal(<<-END_IO_DUMP.gsub(/^\s*/, ""), File.read(data_file))
138
+ class,TestSerialization::ReadOnlyName
139
+ @first,@last
140
+ James,Gray
141
+ Dana,Gray
142
+ Greg,Brown
143
+ END_IO_DUMP
144
+
145
+ assert_equal(@names, FasterCSV.load(File.open(data_file)))
146
+
147
+ File.unlink(data_file)
148
+ end
149
+
150
+ def test_custom_dump_and_load
151
+ obj = {1 => "simple", :test => Hash}
152
+ assert_equal(obj, FasterCSV.load(FasterCSV.dump([obj])).first)
153
+ end
154
+ end
data/test/tc_speed.rb ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_speed.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-11-14.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+ require "timeout"
10
+
11
+ require "faster_csv"
12
+ require "csv"
13
+
14
+ class TestFasterCSVSpeed < Test::Unit::TestCase
15
+ PATH = File.join(File.dirname(__FILE__), "test_data.csv")
16
+ BIG_DATA = "123456789\n" * 1024
17
+
18
+ def test_that_we_are_doing_the_same_work
19
+ FasterCSV.open(PATH) do |csv|
20
+ CSV.foreach(PATH) do |row|
21
+ assert_equal(row, csv.shift)
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_speed_vs_csv
27
+ csv_time = Time.now
28
+ CSV.foreach(PATH) do |row|
29
+ # do nothing, we're just timing a read...
30
+ end
31
+ csv_time = Time.now - csv_time
32
+
33
+ faster_csv_time = Time.now
34
+ FasterCSV.foreach(PATH) do |row|
35
+ # do nothing, we're just timing a read...
36
+ end
37
+ faster_csv_time = Time.now - faster_csv_time
38
+
39
+ assert(faster_csv_time < csv_time / 3)
40
+ end
41
+
42
+ def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
43
+ assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
44
+ end
45
+
46
+ def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
47
+ assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
48
+ end
49
+
50
+ def test_field_size_limit_controls_lookahead
51
+ assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
52
+ :field_size_limit => 2048 )
53
+ end
54
+
55
+ private
56
+
57
+ def assert_parse_errors_out(*args)
58
+ assert_raise(FasterCSV::MalformedCSVError) do
59
+ Timeout.timeout(0.2) do
60
+ FasterCSV.parse(*args)
61
+ fail("Parse didn't error out")
62
+ end
63
+ end
64
+ end
65
+ end
data/test/tc_table.rb ADDED
@@ -0,0 +1,408 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_table.rb
4
+ #
5
+ # Created by James Edward Gray II on 2006-02-24.
6
+ # Copyright 2006 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "faster_csv"
11
+
12
+ class TestFasterCSVTable < Test::Unit::TestCase
13
+ def setup
14
+ @rows = [ FasterCSV::Row.new(%w{A B C}, [1, 2, 3]),
15
+ FasterCSV::Row.new(%w{A B C}, [4, 5, 6]),
16
+ FasterCSV::Row.new(%w{A B C}, [7, 8, 9]) ]
17
+ @table = FasterCSV::Table.new(@rows)
18
+
19
+ @header_table = FasterCSV::Table.new(
20
+ [FasterCSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
21
+ )
22
+ end
23
+
24
+ def test_initialze
25
+ assert_not_nil(@table)
26
+ assert_instance_of(FasterCSV::Table, @table)
27
+ end
28
+
29
+ def test_modes
30
+ assert_equal(:col_or_row, @table.mode)
31
+
32
+ # non-destructive changes, intended for one shot calls
33
+ cols = @table.by_col
34
+ assert_equal(:col_or_row, @table.mode)
35
+ assert_equal(:col, cols.mode)
36
+ assert_equal(@table, cols)
37
+
38
+ rows = @table.by_row
39
+ assert_equal(:col_or_row, @table.mode)
40
+ assert_equal(:row, rows.mode)
41
+ assert_equal(@table, rows)
42
+
43
+ # destructive mode changing calls
44
+ assert_equal(@table, @table.by_row!)
45
+ assert_equal(:row, @table.mode)
46
+ assert_equal(@table, @table.by_col_or_row!)
47
+ assert_equal(:col_or_row, @table.mode)
48
+ end
49
+
50
+ def test_headers
51
+ assert_equal(@rows.first.headers, @table.headers)
52
+ end
53
+
54
+ def test_index
55
+ ##################
56
+ ### Mixed Mode ###
57
+ ##################
58
+ # by row
59
+ @rows.each_index { |i| assert_equal(@rows[i], @table[i]) }
60
+ assert_equal(nil, @table[100]) # empty row
61
+
62
+ # by col
63
+ @rows.first.headers.each do |header|
64
+ assert_equal(@rows.map { |row| row[header] }, @table[header])
65
+ end
66
+ assert_equal([nil] * @rows.size, @table["Z"]) # empty col
67
+
68
+ # by cell, row then col
69
+ assert_equal(2, @table[0][1])
70
+ assert_equal(6, @table[1]["C"])
71
+
72
+ # by cell, col then row
73
+ assert_equal(5, @table["B"][1])
74
+ assert_equal(9, @table["C"][2])
75
+
76
+ # with headers (by col)
77
+ assert_equal(["B", 2, 5, 8], @header_table["B"])
78
+
79
+ ###################
80
+ ### Column Mode ###
81
+ ###################
82
+ @table.by_col!
83
+
84
+ assert_equal([2, 5, 8], @table[1])
85
+ assert_equal([2, 5, 8], @table["B"])
86
+
87
+ ################
88
+ ### Row Mode ###
89
+ ################
90
+ @table.by_row!
91
+
92
+ assert_equal(@rows[1], @table[1])
93
+ assert_raise(TypeError) { @table["B"] }
94
+
95
+ ############################
96
+ ### One Shot Mode Change ###
97
+ ############################
98
+ assert_equal(@rows[1], @table[1])
99
+ assert_equal([2, 5, 8], @table.by_col[1])
100
+ assert_equal(@rows[1], @table[1])
101
+ end
102
+
103
+ def test_set_row_or_column
104
+ ##################
105
+ ### Mixed Mode ###
106
+ ##################
107
+ # set row
108
+ @table[2] = [10, 11, 12]
109
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a)
110
+
111
+ @table[3] = FasterCSV::Row.new(%w[A B C], [13, 14, 15])
112
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]],
113
+ @table.to_a )
114
+
115
+ # set col
116
+ @table["Type"] = "data"
117
+ assert_equal( [ %w[A B C Type],
118
+ [1, 2, 3, "data"],
119
+ [4, 5, 6, "data"],
120
+ [10, 11, 12, "data"],
121
+ [13, 14, 15, "data"] ],
122
+ @table.to_a )
123
+
124
+ @table["Index"] = [1, 2, 3]
125
+ assert_equal( [ %w[A B C Type Index],
126
+ [1, 2, 3, "data", 1],
127
+ [4, 5, 6, "data", 2],
128
+ [10, 11, 12, "data", 3],
129
+ [13, 14, 15, "data", nil] ],
130
+ @table.to_a )
131
+
132
+ @table["B"] = [100, 200]
133
+ assert_equal( [ %w[A B C Type Index],
134
+ [1, 100, 3, "data", 1],
135
+ [4, 200, 6, "data", 2],
136
+ [10, nil, 12, "data", 3],
137
+ [13, nil, 15, "data", nil] ],
138
+ @table.to_a )
139
+
140
+ # verify resulting table
141
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
142
+ A,B,C,Type,Index
143
+ 1,100,3,data,1
144
+ 4,200,6,data,2
145
+ 10,,12,data,3
146
+ 13,,15,data,
147
+ END_RESULT
148
+
149
+ # with headers
150
+ @header_table["Type"] = "data"
151
+ assert_equal(%w[Type data data data], @header_table["Type"])
152
+
153
+ ###################
154
+ ### Column Mode ###
155
+ ###################
156
+ @table.by_col!
157
+
158
+ @table[1] = [2, 5, 11, 14]
159
+ assert_equal( [ %w[A B C Type Index],
160
+ [1, 2, 3, "data", 1],
161
+ [4, 5, 6, "data", 2],
162
+ [10, 11, 12, "data", 3],
163
+ [13, 14, 15, "data", nil] ],
164
+ @table.to_a )
165
+
166
+ @table["Extra"] = "new stuff"
167
+ assert_equal( [ %w[A B C Type Index Extra],
168
+ [1, 2, 3, "data", 1, "new stuff"],
169
+ [4, 5, 6, "data", 2, "new stuff"],
170
+ [10, 11, 12, "data", 3, "new stuff"],
171
+ [13, 14, 15, "data", nil, "new stuff"] ],
172
+ @table.to_a )
173
+
174
+ ################
175
+ ### Row Mode ###
176
+ ################
177
+ @table.by_row!
178
+
179
+ @table[1] = (1..6).to_a
180
+ assert_equal( [ %w[A B C Type Index Extra],
181
+ [1, 2, 3, "data", 1, "new stuff"],
182
+ [1, 2, 3, 4, 5, 6],
183
+ [10, 11, 12, "data", 3, "new stuff"],
184
+ [13, 14, 15, "data", nil, "new stuff"] ],
185
+ @table.to_a )
186
+
187
+ assert_raise(TypeError) { @table["Extra"] = nil }
188
+ end
189
+
190
+ def test_each
191
+ ######################
192
+ ### Mixed/Row Mode ###
193
+ ######################
194
+ i = 0
195
+ @table.each do |row|
196
+ assert_equal(@rows[i], row)
197
+ i += 1
198
+ end
199
+
200
+ # verify that we can chain the call
201
+ assert_equal(@table, @table.each { })
202
+
203
+ ###################
204
+ ### Column Mode ###
205
+ ###################
206
+ @table.by_col!
207
+
208
+ headers = @table.headers
209
+ @table.each do |header, column|
210
+ assert_equal(headers.shift, header)
211
+ assert_equal(@table[header], column)
212
+ end
213
+
214
+ ############################
215
+ ### One Shot Mode Change ###
216
+ ############################
217
+ @table.by_col_or_row!
218
+
219
+ @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
220
+ @table.by_col.each { |tuple| assert_instance_of(Array, tuple) }
221
+ @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
222
+ end
223
+
224
+ def test_enumerable
225
+ assert_equal( @rows.values_at(0, 2),
226
+ @table.select { |row| (row["B"] % 2).zero? } )
227
+
228
+ assert_equal(@rows[1], @table.find { |row| row["C"] > 5 })
229
+ end
230
+
231
+ def test_to_a
232
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a)
233
+
234
+ # with headers
235
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]],
236
+ @header_table.to_a )
237
+ end
238
+
239
+ def test_to_csv
240
+ csv = <<-END_CSV.gsub(/^\s+/, "")
241
+ A,B,C
242
+ 1,2,3
243
+ 4,5,6
244
+ 7,8,9
245
+ END_CSV
246
+
247
+ # normal conversion
248
+ assert_equal(csv, @table.to_csv)
249
+ assert_equal(csv, @table.to_s) # alias
250
+
251
+ # with options
252
+ assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
253
+ @table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
254
+ assert_equal( csv.to_a[1..-1].join,
255
+ @table.to_csv(:write_headers => false) )
256
+
257
+ # with headers
258
+ assert_equal(csv, @header_table.to_csv)
259
+ end
260
+
261
+ def test_append
262
+ # verify that we can chain the call
263
+ assert_equal(@table, @table << [10, 11, 12])
264
+
265
+ # Array append
266
+ assert_equal(FasterCSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1])
267
+
268
+ # Row append
269
+ assert_equal(@table, @table << FasterCSV::Row.new(%w[A B C], [13, 14, 15]))
270
+ assert_equal(FasterCSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1])
271
+ end
272
+
273
+ def test_delete
274
+ ##################
275
+ ### Mixed Mode ###
276
+ ##################
277
+ # delete a row
278
+ assert_equal(@rows[1], @table.delete(1))
279
+
280
+ # delete a col
281
+ assert_equal(@rows.map { |row| row["A"] }, @table.delete("A"))
282
+
283
+ # verify resulting table
284
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
285
+ B,C
286
+ 2,3
287
+ 8,9
288
+ END_RESULT
289
+
290
+ ###################
291
+ ### Column Mode ###
292
+ ###################
293
+ setup
294
+ @table.by_col!
295
+
296
+ assert_equal(@rows.map { |row| row[0] }, @table.delete(0))
297
+ assert_equal(@rows.map { |row| row["C"] }, @table.delete("C"))
298
+
299
+ # verify resulting table
300
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
301
+ B
302
+ 2
303
+ 5
304
+ 8
305
+ END_RESULT
306
+
307
+ ################
308
+ ### Row Mode ###
309
+ ################
310
+ setup
311
+ @table.by_row!
312
+
313
+ assert_equal(@rows[1], @table.delete(1))
314
+ assert_raise(TypeError) { @table.delete("C") }
315
+
316
+ # verify resulting table
317
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
318
+ A,B,C
319
+ 1,2,3
320
+ 7,8,9
321
+ END_RESULT
322
+ end
323
+
324
+ def test_delete_with_blank_rows
325
+ data = "col1,col2\nra1,ra2\n\nrb1,rb2"
326
+ table = FasterCSV.parse(data, :headers => true)
327
+ assert_equal(["ra2", nil, "rb2"], table.delete("col2"))
328
+ end
329
+
330
+ def test_delete_if
331
+ ######################
332
+ ### Mixed/Row Mode ###
333
+ ######################
334
+ # verify that we can chain the call
335
+ assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? })
336
+
337
+ # verify resulting table
338
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
339
+ A,B,C
340
+ 4,5,6
341
+ END_RESULT
342
+
343
+ ###################
344
+ ### Column Mode ###
345
+ ###################
346
+ setup
347
+ @table.by_col!
348
+
349
+ assert_equal(@table, @table.delete_if { |h, v| h > "A" })
350
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
351
+ A
352
+ 1
353
+ 4
354
+ 7
355
+ END_RESULT
356
+ end
357
+
358
+ def test_values_at
359
+ ##################
360
+ ### Mixed Mode ###
361
+ ##################
362
+ # rows
363
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
364
+ assert_equal(@rows.values_at(1..2), @table.values_at(1..2))
365
+
366
+ # cols
367
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
368
+ assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C"))
369
+
370
+ ###################
371
+ ### Column Mode ###
372
+ ###################
373
+ @table.by_col!
374
+
375
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2))
376
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
377
+
378
+ ################
379
+ ### Row Mode ###
380
+ ################
381
+ @table.by_row!
382
+
383
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
384
+ assert_raise(TypeError) { @table.values_at("A", "C") }
385
+
386
+ ############################
387
+ ### One Shot Mode Change ###
388
+ ############################
389
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
390
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
391
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
392
+ end
393
+
394
+ def test_array_delegation
395
+ assert(!@table.empty?, "Table was empty.")
396
+
397
+ assert_equal(@rows.size, @table.size)
398
+ end
399
+
400
+ def test_inspect_shows_current_mode
401
+ str = @table.inspect
402
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
403
+
404
+ @table.by_col!
405
+ str = @table.inspect
406
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
407
+ end
408
+ end