-- Test the CSV functionality (parsing and writing) local test_parse_valid_csv test_parse_valid_csv = function(csv_string, expected_rows, test_write) if test_write == nil then test_write = true end local parsed_rows = lzr_csv.parse_csv(csv_string) if type(parsed_rows) ~= "table" then return false end if #parsed_rows ~= #expected_rows then return false end for r=1, #parsed_rows do local row = parsed_rows[r] for l=1, #row do local elem = row[l] if elem ~= expected_rows[r][l] then return false end end end -- If we reach this point, parsing test has been PASSED if test_write then -- Also test lzr_csv.write_csv by writing what we just parsed. -- and then *parse* that written CSV again to check -- for validity local written_csv = lzr_csv.write_csv(parsed_rows) -- Set test_write to false to avoid infinte recursion return test_parse_valid_csv(written_csv, parsed_rows, false) end return true end -- Test if valid CSVs parse correctly -- Empty CSV assert(test_parse_valid_csv('', {})) -- Single record assert(test_parse_valid_csv('1,2,3', {{"1","2","3"}})) -- Single entry assert(test_parse_valid_csv('single', {{"single"}})) -- 3 records with 1 entry each assert(test_parse_valid_csv('1\013\0102\013\0103', {{"1"},{"2"},{"3"}})) -- linebreak as part of a value assert(test_parse_valid_csv('"quoted\013\010linebreak","element 2"', {{"quoted\013\010linebreak","element 2"}})) -- 4 empty strings separated by 3 commas assert(test_parse_valid_csv(',,,', {{"","","",""}})) -- 4 entries assert(test_parse_valid_csv('word,123,äöü,%90', {{"word","123","äöü","%90"}})) -- quotation test assert(test_parse_valid_csv('quotation,"",quotation', {{"quotation","","quotation"}})) -- escaped quotation mark 1 assert(test_parse_valid_csv('quotation,"""",quotation', {{"quotation",'"',"quotation"}})) -- escaped quotation mark 2 assert(test_parse_valid_csv('"He said ""hello"".","string with spaces","lol"', {{'He said "hello".',"string with spaces","lol"}})) -- comma in value assert(test_parse_valid_csv('"embedded,comma",normal,comma', {{"embedded,comma","normal","comma"}})) -- CSV ends with CRLF assert(test_parse_valid_csv('item1,item2,item3\013\010', {{"item1","item2","item3"}})) -- Test if *invalid* inputs get rejected correctly -- No argument assert(lzr_csv.parse_csv() == nil) -- Wrong data type assert(lzr_csv.parse_csv(1) == nil) -- CR without LF assert(lzr_csv.parse_csv("\013hello") == nil) -- CR without LF at end of string assert(lzr_csv.parse_csv("\013") == nil) -- CR CR without LF assert(lzr_csv.parse_csv("\013\013") == nil) -- lonely LF assert(lzr_csv.parse_csv("\010") == nil) -- LF CR (swapped order) assert(lzr_csv.parse_csv("\010\013") == nil) -- Number of entries per line is different (2 lines) assert(lzr_csv.parse_csv("line1,line1,line1\013\010line2,line2") == nil) -- Number of entries per line is different (3 lines) assert(lzr_csv.parse_csv("line1,line1,line1\013\010line2,line2,line2\013\010line3,line3") == nil)