-- 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 = rcsv.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 rcsv.write_csv by writing what we just parsed.
		-- and then *parse* that written CSV again to check
		-- for validity
		local written_csv = rcsv.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(rcsv.parse_csv() == nil)
-- Wrong data type
assert(rcsv.parse_csv(1) == nil)
-- CR without LF
assert(rcsv.parse_csv("\013hello") == nil)
-- CR without LF at end of string
assert(rcsv.parse_csv("\013") == nil)
-- CR CR without LF
assert(rcsv.parse_csv("\013\013") == nil)
-- lonely LF
assert(rcsv.parse_csv("\010") == nil)
-- LF CR (swapped order)
assert(rcsv.parse_csv("\010\013") == nil)
-- Number of entries per line is different (2 lines)
assert(rcsv.parse_csv("line1,line1,line1\013\010line2,line2") == nil)
-- Number of entries per line is different (3 lines)
assert(rcsv.parse_csv("line1,line1,line1\013\010line2,line2,line2\013\010line3,line3") == nil)
