use strict; use warnings; use utf8; use Test::More; use Cepis::CSV; binmode Test::More->builder->output, ':encoding(UTF-8)'; binmode Test::More->builder->failure_output, ':encoding(UTF-8)'; is_deeply( Cepis::CSV::parse_rows(''), [], 'empty input yields no rows' ); is_deeply( Cepis::CSV::parse_rows("a,b,c\n1,2,3\n"), [ [qw(a b c)], [qw(1 2 3)] ], 'plain rows' ); is_deeply( Cepis::CSV::parse_rows("a,b\r\n1,2\r\n"), [ [qw(a b)], [qw(1 2)] ], 'CRLF line endings' ); is_deeply( Cepis::CSV::parse_rows("a,b\n1,2"), [ [qw(a b)], [qw(1 2)] ], 'a missing final newline still closes the row' ); is_deeply( Cepis::CSV::parse_rows(qq{a,b\n"um, dois",3\n}), [ [qw(a b)], [ 'um, dois', '3' ] ], 'a quoted field may hold a comma' ); is_deeply( Cepis::CSV::parse_rows(qq{a\n"he said ""hi"""\n}), [ ['a'], ['he said "hi"'] ], 'a doubled quote is an escaped quote' ); is_deeply( Cepis::CSV::parse_rows(qq{a,b\n"line\none",2\n}), [ [qw(a b)], [ "line\none", '2' ] ], 'a quoted field may hold a newline' ); is_deeply( Cepis::CSV::parse_rows(qq{a,b,c\n,,\n}), [ [qw(a b c)], [ '', '', '' ] ], 'empty fields survive' ); is_deeply( Cepis::CSV::parse_rows(qq{a,b\n"",""\n}), [ [qw(a b)], [ '', '' ] ], 'explicitly quoted empty fields survive' ); is_deeply( Cepis::CSV::parse_rows("\x{FEFF}a,b\n1,2\n"), [ [qw(a b)], [qw(1 2)] ], 'a byte order mark is stripped' ); is_deeply( Cepis::CSV::parse_rows("a,b\n1,2\n\n\n"), [ [qw(a b)], [qw(1 2)] ], 'blank lines are skipped' ); is_deeply( Cepis::CSV::parse_rows("cep,localidade\n01001000,São Paulo\n"), [ [qw(cep localidade)], [ '01001000', 'São Paulo' ] ], 'non-ASCII characters survive' ); my ( $header, $records ) = Cepis::CSV::parse_hashes("cep,localidade,uf\n01001000,São Paulo,SP\n99999999,,\n"); is_deeply( $header, [qw(cep localidade uf)], 'the header row comes back' ); is_deeply( $records, [ { cep => '01001000', localidade => 'São Paulo', uf => 'SP' }, { cep => '99999999', localidade => '', uf => '' }, ], 'records are keyed by column name' ); ( $header, $records ) = Cepis::CSV::parse_hashes("a,b,c\n1\n"); is_deeply( $records, [ { a => '1', b => '', c => '' } ], 'a short row is filled with empty strings' ); ( $header, $records ) = Cepis::CSV::parse_hashes("a\n1,2,3\n"); is_deeply( $records, [ { a => '1' } ], 'fields beyond the header are dropped' ); ( $header, $records ) = Cepis::CSV::parse_hashes(''); is_deeply( [ $header, $records ], [ [], [] ], 'empty input yields nothing' ); done_testing();