1#!/usr/bin/env ruby -w 2# encoding: UTF-8 3 4# tc_table.rb 5# 6# Created by James Edward Gray II on 2005-10-31. 7# Copyright 2005 James Edward Gray II. You can redistribute or modify this code 8# under the terms of Ruby's license. 9 10require_relative "base" 11 12class TestCSV::Table < TestCSV 13 extend DifferentOFS 14 15 def setup 16 super 17 @rows = [ CSV::Row.new(%w{A B C}, [1, 2, 3]), 18 CSV::Row.new(%w{A B C}, [4, 5, 6]), 19 CSV::Row.new(%w{A B C}, [7, 8, 9]) ] 20 @table = CSV::Table.new(@rows) 21 22 @header_table = CSV::Table.new( 23 [CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows 24 ) 25 end 26 27 def test_initialze 28 assert_not_nil(@table) 29 assert_instance_of(CSV::Table, @table) 30 end 31 32 def test_modes 33 assert_equal(:col_or_row, @table.mode) 34 35 # non-destructive changes, intended for one shot calls 36 cols = @table.by_col 37 assert_equal(:col_or_row, @table.mode) 38 assert_equal(:col, cols.mode) 39 assert_equal(@table, cols) 40 41 rows = @table.by_row 42 assert_equal(:col_or_row, @table.mode) 43 assert_equal(:row, rows.mode) 44 assert_equal(@table, rows) 45 46 # destructive mode changing calls 47 assert_equal(@table, @table.by_row!) 48 assert_equal(:row, @table.mode) 49 assert_equal(@table, @table.by_col_or_row!) 50 assert_equal(:col_or_row, @table.mode) 51 end 52 53 def test_headers 54 assert_equal(@rows.first.headers, @table.headers) 55 end 56 57 def test_index 58 ################## 59 ### Mixed Mode ### 60 ################## 61 # by row 62 @rows.each_index { |i| assert_equal(@rows[i], @table[i]) } 63 assert_equal(nil, @table[100]) # empty row 64 65 # by col 66 @rows.first.headers.each do |header| 67 assert_equal(@rows.map { |row| row[header] }, @table[header]) 68 end 69 assert_equal([nil] * @rows.size, @table["Z"]) # empty col 70 71 # by cell, row then col 72 assert_equal(2, @table[0][1]) 73 assert_equal(6, @table[1]["C"]) 74 75 # by cell, col then row 76 assert_equal(5, @table["B"][1]) 77 assert_equal(9, @table["C"][2]) 78 79 # with headers (by col) 80 assert_equal(["B", 2, 5, 8], @header_table["B"]) 81 82 ################### 83 ### Column Mode ### 84 ################### 85 @table.by_col! 86 87 assert_equal([2, 5, 8], @table[1]) 88 assert_equal([2, 5, 8], @table["B"]) 89 90 ################ 91 ### Row Mode ### 92 ################ 93 @table.by_row! 94 95 assert_equal(@rows[1], @table[1]) 96 assert_raise(TypeError) { @table["B"] } 97 98 ############################ 99 ### One Shot Mode Change ### 100 ############################ 101 assert_equal(@rows[1], @table[1]) 102 assert_equal([2, 5, 8], @table.by_col[1]) 103 assert_equal(@rows[1], @table[1]) 104 end 105 106 def test_set_row_or_column 107 ################## 108 ### Mixed Mode ### 109 ################## 110 # set row 111 @table[2] = [10, 11, 12] 112 assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a) 113 114 @table[3] = CSV::Row.new(%w[A B C], [13, 14, 15]) 115 assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]], 116 @table.to_a ) 117 118 # set col 119 @table["Type"] = "data" 120 assert_equal( [ %w[A B C Type], 121 [1, 2, 3, "data"], 122 [4, 5, 6, "data"], 123 [10, 11, 12, "data"], 124 [13, 14, 15, "data"] ], 125 @table.to_a ) 126 127 @table["Index"] = [1, 2, 3] 128 assert_equal( [ %w[A B C Type Index], 129 [1, 2, 3, "data", 1], 130 [4, 5, 6, "data", 2], 131 [10, 11, 12, "data", 3], 132 [13, 14, 15, "data", nil] ], 133 @table.to_a ) 134 135 @table["B"] = [100, 200] 136 assert_equal( [ %w[A B C Type Index], 137 [1, 100, 3, "data", 1], 138 [4, 200, 6, "data", 2], 139 [10, nil, 12, "data", 3], 140 [13, nil, 15, "data", nil] ], 141 @table.to_a ) 142 143 # verify resulting table 144 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 145 A,B,C,Type,Index 146 1,100,3,data,1 147 4,200,6,data,2 148 10,,12,data,3 149 13,,15,data, 150 END_RESULT 151 152 # with headers 153 @header_table["Type"] = "data" 154 assert_equal(%w[Type data data data], @header_table["Type"]) 155 156 ################### 157 ### Column Mode ### 158 ################### 159 @table.by_col! 160 161 @table[1] = [2, 5, 11, 14] 162 assert_equal( [ %w[A B C Type Index], 163 [1, 2, 3, "data", 1], 164 [4, 5, 6, "data", 2], 165 [10, 11, 12, "data", 3], 166 [13, 14, 15, "data", nil] ], 167 @table.to_a ) 168 169 @table["Extra"] = "new stuff" 170 assert_equal( [ %w[A B C Type Index Extra], 171 [1, 2, 3, "data", 1, "new stuff"], 172 [4, 5, 6, "data", 2, "new stuff"], 173 [10, 11, 12, "data", 3, "new stuff"], 174 [13, 14, 15, "data", nil, "new stuff"] ], 175 @table.to_a ) 176 177 ################ 178 ### Row Mode ### 179 ################ 180 @table.by_row! 181 182 @table[1] = (1..6).to_a 183 assert_equal( [ %w[A B C Type Index Extra], 184 [1, 2, 3, "data", 1, "new stuff"], 185 [1, 2, 3, 4, 5, 6], 186 [10, 11, 12, "data", 3, "new stuff"], 187 [13, 14, 15, "data", nil, "new stuff"] ], 188 @table.to_a ) 189 190 assert_raise(TypeError) { @table["Extra"] = nil } 191 end 192 193 def test_each 194 ###################### 195 ### Mixed/Row Mode ### 196 ###################### 197 i = 0 198 @table.each do |row| 199 assert_equal(@rows[i], row) 200 i += 1 201 end 202 203 # verify that we can chain the call 204 assert_equal(@table, @table.each { }) 205 206 ################### 207 ### Column Mode ### 208 ################### 209 @table.by_col! 210 211 headers = @table.headers 212 @table.each do |header, column| 213 assert_equal(headers.shift, header) 214 assert_equal(@table[header], column) 215 end 216 217 ############################ 218 ### One Shot Mode Change ### 219 ############################ 220 @table.by_col_or_row! 221 222 @table.each { |row| assert_instance_of(CSV::Row, row) } 223 @table.by_col.each { |tuple| assert_instance_of(Array, tuple) } 224 @table.each { |row| assert_instance_of(CSV::Row, row) } 225 end 226 227 def test_enumerable 228 assert_equal( @rows.values_at(0, 2), 229 @table.select { |row| (row["B"] % 2).zero? } ) 230 231 assert_equal(@rows[1], @table.find { |row| row["C"] > 5 }) 232 end 233 234 def test_to_a 235 assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a) 236 237 # with headers 238 assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], 239 @header_table.to_a ) 240 end 241 242 def test_to_csv 243 csv = <<-END_CSV.gsub(/^\s+/, "") 244 A,B,C 245 1,2,3 246 4,5,6 247 7,8,9 248 END_CSV 249 250 # normal conversion 251 assert_equal(csv, @table.to_csv) 252 assert_equal(csv, @table.to_s) # alias 253 254 # with options 255 assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"), 256 @table.to_csv(col_sep: "|", row_sep: "\r\n") ) 257 assert_equal( csv.lines.to_a[1..-1].join(''), 258 @table.to_csv(:write_headers => false) ) 259 260 # with headers 261 assert_equal(csv, @header_table.to_csv) 262 end 263 264 def test_append 265 # verify that we can chain the call 266 assert_equal(@table, @table << [10, 11, 12]) 267 268 # Array append 269 assert_equal(CSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1]) 270 271 # Row append 272 assert_equal(@table, @table << CSV::Row.new(%w[A B C], [13, 14, 15])) 273 assert_equal(CSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1]) 274 end 275 276 def test_delete_mixed 277 ################## 278 ### Mixed Mode ### 279 ################## 280 # delete a row 281 assert_equal(@rows[1], @table.delete(1)) 282 283 # delete a col 284 assert_equal(@rows.map { |row| row["A"] }, @table.delete("A")) 285 286 # verify resulting table 287 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 288 B,C 289 2,3 290 8,9 291 END_RESULT 292 end 293 294 def test_delete_column 295 ################### 296 ### Column Mode ### 297 ################### 298 @table.by_col! 299 300 assert_equal(@rows.map { |row| row[0] }, @table.delete(0)) 301 assert_equal(@rows.map { |row| row["C"] }, @table.delete("C")) 302 303 # verify resulting table 304 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 305 B 306 2 307 5 308 8 309 END_RESULT 310 end 311 312 def test_delete_row 313 ################ 314 ### Row Mode ### 315 ################ 316 @table.by_row! 317 318 assert_equal(@rows[1], @table.delete(1)) 319 assert_raise(TypeError) { @table.delete("C") } 320 321 # verify resulting table 322 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 323 A,B,C 324 1,2,3 325 7,8,9 326 END_RESULT 327 end 328 329 def test_delete_with_blank_rows 330 data = "col1,col2\nra1,ra2\n\nrb1,rb2" 331 table = CSV.parse(data, :headers => true) 332 assert_equal(["ra2", nil, "rb2"], table.delete("col2")) 333 end 334 335 def test_delete_if_row 336 ###################### 337 ### Mixed/Row Mode ### 338 ###################### 339 # verify that we can chain the call 340 assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? }) 341 342 # verify resulting table 343 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 344 A,B,C 345 4,5,6 346 END_RESULT 347 end 348 349 def test_delete_if_column 350 ################### 351 ### Column Mode ### 352 ################### 353 @table.by_col! 354 355 assert_equal(@table, @table.delete_if { |h, v| h > "A" }) 356 assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv) 357 A 358 1 359 4 360 7 361 END_RESULT 362 end 363 364 def test_values_at 365 ################## 366 ### Mixed Mode ### 367 ################## 368 # rows 369 assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) 370 assert_equal(@rows.values_at(1..2), @table.values_at(1..2)) 371 372 # cols 373 assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C")) 374 assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C")) 375 376 ################### 377 ### Column Mode ### 378 ################### 379 @table.by_col! 380 381 assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2)) 382 assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C")) 383 384 ################ 385 ### Row Mode ### 386 ################ 387 @table.by_row! 388 389 assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) 390 assert_raise(TypeError) { @table.values_at("A", "C") } 391 392 ############################ 393 ### One Shot Mode Change ### 394 ############################ 395 assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) 396 assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2)) 397 assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) 398 end 399 400 def test_array_delegation 401 assert(!@table.empty?, "Table was empty.") 402 403 assert_equal(@rows.size, @table.size) 404 end 405 406 def test_inspect_shows_current_mode 407 str = @table.inspect 408 assert(str.include?("mode:#{@table.mode}"), "Mode not shown.") 409 410 @table.by_col! 411 str = @table.inspect 412 assert(str.include?("mode:#{@table.mode}"), "Mode not shown.") 413 end 414 415 def test_inspect_encoding_is_ascii_compatible 416 assert( Encoding.compatible?( Encoding.find("US-ASCII"), 417 @table.inspect.encoding ), 418 "inspect() was not ASCII compatible." ) 419 end 420end 421