1#!/usr/bin/env ruby -w 2# encoding: UTF-8 3 4# tc_data_converters.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::DataConverters < TestCSV 13 extend DifferentOFS 14 15 def setup 16 super 17 @data = "Numbers,:integer,1,:float,3.015" 18 @parser = CSV.new(@data) 19 20 @custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field } 21 22 @win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y") 23 end 24 25 def test_builtin_integer_converter 26 # does convert 27 [-5, 1, 10000000000].each do |n| 28 assert_equal(n, CSV::Converters[:integer][n.to_s]) 29 end 30 31 # does not convert 32 (%w{junk 1.0} + [""]).each do |str| 33 assert_equal(str, CSV::Converters[:integer][str]) 34 end 35 end 36 37 def test_builtin_float_converter 38 # does convert 39 [-5.1234, 0, 2.3e-11].each do |n| 40 assert_equal(n, CSV::Converters[:float][n.to_s]) 41 end 42 43 # does not convert 44 (%w{junk 1..0 .015F} + [""]).each do |str| 45 assert_equal(str, CSV::Converters[:float][str]) 46 end 47 end 48 49 def test_builtin_date_converter 50 # does convert 51 assert_instance_of( 52 Date, 53 CSV::Converters[:date][@win_safe_time_str.sub(/\d+:\d+:\d+ /, "")] 54 ) 55 56 # does not convert 57 assert_instance_of(String, CSV::Converters[:date]["junk"]) 58 end 59 60 def test_builtin_date_time_converter 61 # does convert 62 assert_instance_of( DateTime, 63 CSV::Converters[:date_time][@win_safe_time_str] ) 64 65 # does not convert 66 assert_instance_of(String, CSV::Converters[:date_time]["junk"]) 67 end 68 69 def test_convert_with_builtin_integer 70 # setup parser... 71 assert(@parser.respond_to?(:convert)) 72 assert_nothing_raised(Exception) { @parser.convert(:integer) } 73 74 # and use 75 assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], @parser.shift) 76 end 77 78 def test_convert_with_builtin_float 79 # setup parser... 80 assert(@parser.respond_to?(:convert)) 81 assert_nothing_raised(Exception) { @parser.convert(:float) } 82 83 # and use 84 assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], @parser.shift) 85 end 86 87 def test_convert_order_float_integer 88 # floats first, then integers... 89 assert_nothing_raised(Exception) do 90 @parser.convert(:float) 91 @parser.convert(:integer) 92 end 93 94 # gets us nothing but floats 95 assert_equal( [String, String, Float, String, Float], 96 @parser.shift.map { |field| field.class } ) 97 end 98 99 def test_convert_order_integer_float 100 # integers have precendance... 101 assert_nothing_raised(Exception) do 102 @parser.convert(:integer) 103 @parser.convert(:float) 104 end 105 106 # gives us proper number conversion 107 assert_equal( [String, String, Fixnum, String, Float], 108 @parser.shift.map { |field| field.class } ) 109 end 110 111 def test_builtin_numeric_combo_converter 112 # setup parser... 113 assert_nothing_raised(Exception) { @parser.convert(:numeric) } 114 115 # and use 116 assert_equal( [String, String, Fixnum, String, Float], 117 @parser.shift.map { |field| field.class } ) 118 end 119 120 def test_builtin_all_nested_combo_converter 121 # setup parser... 122 @data << ",#{@win_safe_time_str}" # add a DateTime field 123 @parser = CSV.new(@data) # reset parser 124 assert_nothing_raised(Exception) { @parser.convert(:all) } 125 126 # and use 127 assert_equal( [String, String, Fixnum, String, Float, DateTime], 128 @parser.shift.map { |field| field.class } ) 129 end 130 131 def test_convert_with_custom_code 132 # define custom converter... 133 assert_nothing_raised(Exception) do 134 @parser.convert { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field } 135 end 136 137 # and use 138 assert_equal(["Numbers", :integer, "1", :float, "3.015"], @parser.shift) 139 end 140 141 def test_convert_with_custom_code_mix 142 # mix built-in and custom... 143 assert_nothing_raised(Exception) { @parser.convert(:numeric) } 144 assert_nothing_raised(Exception) { @parser.convert(&@custom) } 145 146 # and use 147 assert_equal(["Numbers", :integer, 1, :float, 3.015], @parser.shift) 148 end 149 150 def test_convert_with_custom_code_using_field_info 151 # define custom converter that uses field information... 152 assert_nothing_raised(Exception) do 153 @parser.convert do |field, info| 154 assert_equal(1, info.line) 155 info.index == 4 ? Float(field).floor : field 156 end 157 end 158 159 # and use 160 assert_equal(["Numbers", ":integer", "1", ":float", 3], @parser.shift) 161 end 162 163 def test_convert_with_custom_code_using_field_info_header 164 @parser = CSV.new(@data, headers: %w{one two three four five}) 165 166 # define custom converter that uses field header information... 167 assert_nothing_raised(Exception) do 168 @parser.convert do |field, info| 169 info.header == "three" ? Integer(field) * 100 : field 170 end 171 end 172 173 # and use 174 assert_equal( ["Numbers", ":integer", 100, ":float", "3.015"], 175 @parser.shift.fields ) 176 end 177 178 def test_shortcut_interface 179 assert_equal( ["Numbers", ":integer", 1, ":float", 3.015], 180 CSV.parse_line(@data, converters: :numeric) ) 181 182 assert_equal( ["Numbers", ":integer", 1, ":float", 3.015], 183 CSV.parse_line(@data, converters: [:integer, :float]) ) 184 185 assert_equal( ["Numbers", :integer, 1, :float, 3.015], 186 CSV.parse_line(@data, converters: [:numeric, @custom]) ) 187 end 188 189 def test_unconverted_fields 190 [ [ @data, 191 ["Numbers", :integer, 1, :float, 3.015], 192 %w{Numbers :integer 1 :float 3.015} ], 193 ["\n", Array.new, Array.new] ].each do |test, fields, unconverted| 194 row = nil 195 assert_nothing_raised(Exception) do 196 row = CSV.parse_line( test, 197 converters: [:numeric, @custom], 198 unconverted_fields: true ) 199 end 200 assert_not_nil(row) 201 assert_equal(fields, row) 202 assert_respond_to(row, :unconverted_fields) 203 assert_equal(unconverted, row.unconverted_fields) 204 end 205 206 data = <<-END_CSV.gsub(/^\s+/, "") 207 first,second,third 208 1,2,3 209 END_CSV 210 row = nil 211 assert_nothing_raised(Exception) do 212 row = CSV.parse_line( data, 213 converters: :numeric, 214 unconverted_fields: true, 215 headers: :first_row ) 216 end 217 assert_not_nil(row) 218 assert_equal([["first", 1], ["second", 2], ["third", 3]], row.to_a) 219 assert_respond_to(row, :unconverted_fields) 220 assert_equal(%w{1 2 3}, row.unconverted_fields) 221 222 assert_nothing_raised(Exception) do 223 row = CSV.parse_line( data, 224 converters: :numeric, 225 unconverted_fields: true, 226 headers: :first_row, 227 return_headers: true ) 228 end 229 assert_not_nil(row) 230 assert_equal( [%w{first first}, %w{second second}, %w{third third}], 231 row.to_a ) 232 assert_respond_to(row, :unconverted_fields) 233 assert_equal(%w{first second third}, row.unconverted_fields) 234 235 assert_nothing_raised(Exception) do 236 row = CSV.parse_line( data, 237 converters: :numeric, 238 unconverted_fields: true, 239 headers: :first_row, 240 return_headers: true, 241 header_converters: :symbol ) 242 end 243 assert_not_nil(row) 244 assert_equal( [[:first, "first"], [:second, "second"], [:third, "third"]], 245 row.to_a ) 246 assert_respond_to(row, :unconverted_fields) 247 assert_equal(%w{first second third}, row.unconverted_fields) 248 249 assert_nothing_raised(Exception) do 250 row = CSV.parse_line( data, 251 converters: :numeric, 252 unconverted_fields: true, 253 headers: %w{my new headers}, 254 return_headers: true, 255 header_converters: :symbol ) 256 end 257 assert_not_nil(row) 258 assert_equal( [[:my, "my"], [:new, "new"], [:headers, "headers"]], 259 row.to_a ) 260 assert_respond_to(row, :unconverted_fields) 261 assert_equal(Array.new, row.unconverted_fields) 262 end 263end 264