tc_table.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #!/usr/local/bin/ruby -w
  2. # tc_table.rb
  3. #
  4. # Created by James Edward Gray II on 2006-02-24.
  5. # Copyright 2012 Gray Productions. All rights reserved.
  6. require "test/unit"
  7. require "faster_csv"
  8. class TestFasterCSVTable < Test::Unit::TestCase
  9. def setup
  10. @rows = [ FasterCSV::Row.new(%w{A B C}, [1, 2, 3]),
  11. FasterCSV::Row.new(%w{A B C}, [4, 5, 6]),
  12. FasterCSV::Row.new(%w{A B C}, [7, 8, 9]) ]
  13. @table = FasterCSV::Table.new(@rows)
  14. @header_table = FasterCSV::Table.new(
  15. [FasterCSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
  16. )
  17. end
  18. def test_initialze
  19. assert_not_nil(@table)
  20. assert_instance_of(FasterCSV::Table, @table)
  21. end
  22. def test_modes
  23. assert_equal(:col_or_row, @table.mode)
  24. # non-destructive changes, intended for one shot calls
  25. cols = @table.by_col
  26. assert_equal(:col_or_row, @table.mode)
  27. assert_equal(:col, cols.mode)
  28. assert_equal(@table, cols)
  29. rows = @table.by_row
  30. assert_equal(:col_or_row, @table.mode)
  31. assert_equal(:row, rows.mode)
  32. assert_equal(@table, rows)
  33. # destructive mode changing calls
  34. assert_equal(@table, @table.by_row!)
  35. assert_equal(:row, @table.mode)
  36. assert_equal(@table, @table.by_col_or_row!)
  37. assert_equal(:col_or_row, @table.mode)
  38. end
  39. def test_headers
  40. assert_equal(@rows.first.headers, @table.headers)
  41. end
  42. def test_index
  43. ##################
  44. ### Mixed Mode ###
  45. ##################
  46. # by row
  47. @rows.each_index { |i| assert_equal(@rows[i], @table[i]) }
  48. assert_equal(nil, @table[100]) # empty row
  49. # by col
  50. @rows.first.headers.each do |header|
  51. assert_equal(@rows.map { |row| row[header] }, @table[header])
  52. end
  53. assert_equal([nil] * @rows.size, @table["Z"]) # empty col
  54. # by cell, row then col
  55. assert_equal(2, @table[0][1])
  56. assert_equal(6, @table[1]["C"])
  57. # by cell, col then row
  58. assert_equal(5, @table["B"][1])
  59. assert_equal(9, @table["C"][2])
  60. # with headers (by col)
  61. assert_equal(["B", 2, 5, 8], @header_table["B"])
  62. ###################
  63. ### Column Mode ###
  64. ###################
  65. @table.by_col!
  66. assert_equal([2, 5, 8], @table[1])
  67. assert_equal([2, 5, 8], @table["B"])
  68. ################
  69. ### Row Mode ###
  70. ################
  71. @table.by_row!
  72. assert_equal(@rows[1], @table[1])
  73. assert_raise(TypeError) { @table["B"] }
  74. ############################
  75. ### One Shot Mode Change ###
  76. ############################
  77. assert_equal(@rows[1], @table[1])
  78. assert_equal([2, 5, 8], @table.by_col[1])
  79. assert_equal(@rows[1], @table[1])
  80. end
  81. def test_set_row_or_column
  82. ##################
  83. ### Mixed Mode ###
  84. ##################
  85. # set row
  86. @table[2] = [10, 11, 12]
  87. assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a)
  88. @table[3] = FasterCSV::Row.new(%w[A B C], [13, 14, 15])
  89. assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]],
  90. @table.to_a )
  91. # set col
  92. @table["Type"] = "data"
  93. assert_equal( [ %w[A B C Type],
  94. [1, 2, 3, "data"],
  95. [4, 5, 6, "data"],
  96. [10, 11, 12, "data"],
  97. [13, 14, 15, "data"] ],
  98. @table.to_a )
  99. @table["Index"] = [1, 2, 3]
  100. assert_equal( [ %w[A B C Type Index],
  101. [1, 2, 3, "data", 1],
  102. [4, 5, 6, "data", 2],
  103. [10, 11, 12, "data", 3],
  104. [13, 14, 15, "data", nil] ],
  105. @table.to_a )
  106. @table["B"] = [100, 200]
  107. assert_equal( [ %w[A B C Type Index],
  108. [1, 100, 3, "data", 1],
  109. [4, 200, 6, "data", 2],
  110. [10, nil, 12, "data", 3],
  111. [13, nil, 15, "data", nil] ],
  112. @table.to_a )
  113. # verify resulting table
  114. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  115. A,B,C,Type,Index
  116. 1,100,3,data,1
  117. 4,200,6,data,2
  118. 10,,12,data,3
  119. 13,,15,data,
  120. END_RESULT
  121. # with headers
  122. @header_table["Type"] = "data"
  123. assert_equal(%w[Type data data data], @header_table["Type"])
  124. ###################
  125. ### Column Mode ###
  126. ###################
  127. @table.by_col!
  128. @table[1] = [2, 5, 11, 14]
  129. assert_equal( [ %w[A B C Type Index],
  130. [1, 2, 3, "data", 1],
  131. [4, 5, 6, "data", 2],
  132. [10, 11, 12, "data", 3],
  133. [13, 14, 15, "data", nil] ],
  134. @table.to_a )
  135. @table["Extra"] = "new stuff"
  136. assert_equal( [ %w[A B C Type Index Extra],
  137. [1, 2, 3, "data", 1, "new stuff"],
  138. [4, 5, 6, "data", 2, "new stuff"],
  139. [10, 11, 12, "data", 3, "new stuff"],
  140. [13, 14, 15, "data", nil, "new stuff"] ],
  141. @table.to_a )
  142. ################
  143. ### Row Mode ###
  144. ################
  145. @table.by_row!
  146. @table[1] = (1..6).to_a
  147. assert_equal( [ %w[A B C Type Index Extra],
  148. [1, 2, 3, "data", 1, "new stuff"],
  149. [1, 2, 3, 4, 5, 6],
  150. [10, 11, 12, "data", 3, "new stuff"],
  151. [13, 14, 15, "data", nil, "new stuff"] ],
  152. @table.to_a )
  153. assert_raise(TypeError) { @table["Extra"] = nil }
  154. end
  155. def test_each
  156. ######################
  157. ### Mixed/Row Mode ###
  158. ######################
  159. i = 0
  160. @table.each do |row|
  161. assert_equal(@rows[i], row)
  162. i += 1
  163. end
  164. # verify that we can chain the call
  165. assert_equal(@table, @table.each { })
  166. ###################
  167. ### Column Mode ###
  168. ###################
  169. @table.by_col!
  170. headers = @table.headers
  171. @table.each do |header, column|
  172. assert_equal(headers.shift, header)
  173. assert_equal(@table[header], column)
  174. end
  175. ############################
  176. ### One Shot Mode Change ###
  177. ############################
  178. @table.by_col_or_row!
  179. @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
  180. @table.by_col.each { |tuple| assert_instance_of(Array, tuple) }
  181. @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
  182. end
  183. def test_enumerable
  184. assert_equal( @rows.values_at(0, 2),
  185. @table.select { |row| (row["B"] % 2).zero? } )
  186. assert_equal(@rows[1], @table.find { |row| row["C"] > 5 })
  187. end
  188. def test_to_a
  189. assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a)
  190. # with headers
  191. assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]],
  192. @header_table.to_a )
  193. end
  194. def test_to_csv
  195. csv = <<-END_CSV.gsub(/^\s+/, "")
  196. A,B,C
  197. 1,2,3
  198. 4,5,6
  199. 7,8,9
  200. END_CSV
  201. # normal conversion
  202. assert_equal(csv, @table.to_csv)
  203. assert_equal(csv, @table.to_s) # alias
  204. # with options
  205. assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
  206. @table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
  207. assert_equal( csv.to_a[1..-1].join,
  208. @table.to_csv(:write_headers => false) )
  209. # with headers
  210. assert_equal(csv, @header_table.to_csv)
  211. end
  212. def test_append
  213. # verify that we can chain the call
  214. assert_equal(@table, @table << [10, 11, 12])
  215. # Array append
  216. assert_equal(FasterCSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1])
  217. # Row append
  218. assert_equal(@table, @table << FasterCSV::Row.new(%w[A B C], [13, 14, 15]))
  219. assert_equal(FasterCSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1])
  220. end
  221. def test_delete
  222. ##################
  223. ### Mixed Mode ###
  224. ##################
  225. # delete a row
  226. assert_equal(@rows[1], @table.delete(1))
  227. # delete a col
  228. assert_equal(@rows.map { |row| row["A"] }, @table.delete("A"))
  229. # verify resulting table
  230. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  231. B,C
  232. 2,3
  233. 8,9
  234. END_RESULT
  235. ###################
  236. ### Column Mode ###
  237. ###################
  238. setup
  239. @table.by_col!
  240. assert_equal(@rows.map { |row| row[0] }, @table.delete(0))
  241. assert_equal(@rows.map { |row| row["C"] }, @table.delete("C"))
  242. # verify resulting table
  243. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  244. B
  245. 2
  246. 5
  247. 8
  248. END_RESULT
  249. ################
  250. ### Row Mode ###
  251. ################
  252. setup
  253. @table.by_row!
  254. assert_equal(@rows[1], @table.delete(1))
  255. assert_raise(TypeError) { @table.delete("C") }
  256. # verify resulting table
  257. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  258. A,B,C
  259. 1,2,3
  260. 7,8,9
  261. END_RESULT
  262. end
  263. def test_delete_with_blank_rows
  264. data = "col1,col2\nra1,ra2\n\nrb1,rb2"
  265. table = FasterCSV.parse(data, :headers => true)
  266. assert_equal(["ra2", nil, "rb2"], table.delete("col2"))
  267. end
  268. def test_delete_if
  269. ######################
  270. ### Mixed/Row Mode ###
  271. ######################
  272. # verify that we can chain the call
  273. assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? })
  274. # verify resulting table
  275. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  276. A,B,C
  277. 4,5,6
  278. END_RESULT
  279. ###################
  280. ### Column Mode ###
  281. ###################
  282. setup
  283. @table.by_col!
  284. assert_equal(@table, @table.delete_if { |h, v| h > "A" })
  285. assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
  286. A
  287. 1
  288. 4
  289. 7
  290. END_RESULT
  291. end
  292. def test_values_at
  293. ##################
  294. ### Mixed Mode ###
  295. ##################
  296. # rows
  297. assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
  298. assert_equal(@rows.values_at(1..2), @table.values_at(1..2))
  299. # cols
  300. assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
  301. assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C"))
  302. ###################
  303. ### Column Mode ###
  304. ###################
  305. @table.by_col!
  306. assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2))
  307. assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
  308. ################
  309. ### Row Mode ###
  310. ################
  311. @table.by_row!
  312. assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
  313. assert_raise(TypeError) { @table.values_at("A", "C") }
  314. ############################
  315. ### One Shot Mode Change ###
  316. ############################
  317. assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
  318. assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
  319. assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
  320. end
  321. def test_array_delegation
  322. assert(!@table.empty?, "Table was empty.")
  323. assert_equal(@rows.size, @table.size)
  324. end
  325. def test_inspect_shows_current_mode
  326. str = @table.inspect
  327. assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
  328. @table.by_col!
  329. str = @table.inspect
  330. assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
  331. end
  332. end