lib/standard/stream: Renamed streams for more explicit denomination
[nit.git] / lib / csv / test_csv.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Tests for `csv`.
12 module test_csv is test_suite
13
14 import test_suite
15 import csv
16
17 class TestCsvWriter
18 super TestSuite
19
20 # The custom CSV format used in the tests.
21 private var custom_format = new CsvFormat('/', ':', "#")
22
23 # Expect to write `row` as `expected_rfc4180` and as `expected_custom`.
24 #
25 # Parameters:
26 #
27 # * `always_escape`: value of the `always_escape` option.
28 # * `row`: row to write.
29 # * `expected_rfc4180`: expected result in RFC 4180.
30 # * `expected_custom`: expected result in the custom CSV format.
31 private fun expect(always_escape: Bool, row: SequenceRead[String],
32 expected_rfc4180: String,
33 expected_custom: String) do
34 var out = new StringWriter
35 var writer = new CsvWriter(out)
36
37 writer.always_escape = always_escape
38 writer.write_sequence(row)
39 assert out.to_s == expected_rfc4180 else
40 sys.stderr.write "\nFormat: RFC 4180\n"
41 sys.stderr.write "Expecting: \"{expected_rfc4180.escape_to_nit}\"\n"
42 sys.stderr.write "Got: \"{out.to_s.escape_to_nit}\"\n"
43 end
44 writer.close
45
46 out = new StringWriter
47 writer = new CsvWriter.with_format(out, custom_format)
48 writer.always_escape = always_escape
49 writer.write_sequence(row)
50 assert out.to_s == expected_custom else
51 sys.stderr.write "\nFormat: {custom_format.delimiter}"
52 sys.stderr.write " {custom_format.separator}"
53 sys.stderr.write " {custom_format.eol.escape_to_nit}\n"
54 sys.stderr.write "Expecting: \"{expected_custom.escape_to_nit}\"\n"
55 sys.stderr.write "Got: \"{out.to_s.escape_to_nit}\"\n"
56 end
57 writer.close
58 end
59
60 fun test_empty do expect(true, new Array[String], "\r\n", "#")
61
62 fun test_one_cell do expect(true, ["foo/\"\r\n,"],
63 "\"foo/\"\"\r\n,\"\r\n",
64 "/foo//\"\r\n,/#")
65
66 fun test_optimize_size_escaped do expect(false, ["foo/\"\r\n,"],
67 "\"foo/\"\"\r\n,\"\r\n",
68 "/foo//\"\r\n,/#")
69
70 fun test_optimize_size_eol do expect(false, ["foo\r#\n"],
71 "\"foo\r#\n\"\r\n",
72 "/foo\r#\n/#")
73
74 fun test_optimize_size_unescaped do expect(false, ["foo"],
75 "foo\r\n",
76 "foo#")
77
78 fun test_multiple_cells do expect(true, ["1", "", "/"],
79 "\"1\",,\"/\"\r\n",
80 "/1/::////#")
81
82 fun test_multiple_cells_optimize_size do expect(false, ["1", "", "/"],
83 "1,,/\r\n",
84 "1::////#")
85 end
86
87 class TestCsvReader
88 super TestSuite
89
90 # The custom CSV format used in the tests.
91 private var custom_format = new CsvFormat('/', ':', "#")
92
93 # Expect to read `expected`.
94 #
95 # Parameters:
96 #
97 # * `skip_empty`: value of the `skip_empty` option.
98 # * `modal_escaping`: value of the `modal_escaping` option.
99 # * `input_rfc4180`: input in the RFC 4180 format.
100 # * `input_custom`: input in the custom CSV format.
101 # * `expected`: expected resulting table.
102 private fun expect(skip_empty: Bool,
103 input_rfc4180: String,
104 input_custom: String,
105 expected: SequenceRead[SequenceRead[String]]) do
106 var istream: Reader
107 var reader: CsvReader
108
109 istream = new StringReader(input_rfc4180)
110 reader = new CsvReader(istream)
111 reader.skip_empty = skip_empty
112 assert_table_equals("RFC 4180", reader, expected.iterator)
113
114 istream = new StringReader(input_custom)
115 reader = new CsvReader.with_format(istream, custom_format)
116 reader.skip_empty = skip_empty
117 assert_table_equals("{custom_format.delimiter} " +
118 "{custom_format.separator} " +
119 "{custom_format.eol.escape_to_nit}", reader, expected.iterator)
120 end
121
122 # Check if tables are equal.
123 private fun assert_table_equals(format: String,
124 actual: Iterator[SequenceRead[String]],
125 expected: Iterator[SequenceRead[String]]) do
126 var i = 0
127
128 for actual_row in actual do
129 assert expected.is_ok else fail(format,"Too many rows.")
130 var expected_row = expected.item
131 assert_row_equals(format, i, actual_row, expected_row)
132 expected.next
133 i += 1
134 end
135 assert not expected.is_ok else fail(format, "Not enough rows.")
136 expected.finish
137 end
138
139 # Check if rows are equal.
140 private fun assert_row_equals(format: String,
141 row_index: Int,
142 actual: SequenceRead[String],
143 expected: SequenceRead[String]) do
144 assert actual == expected else
145 fail(format, """
146 At row {{{row_index}}}.
147 Expecting: {{{expected.join("|")}}}
148 Got: {{{actual.join("|")}}}""")
149 end
150 end
151
152 # Output an error message with an indication of the format used.
153 private fun fail(format: Text, message: Text) do
154 sys.stderr.write "\nFormat: {format}\n"
155 sys.stderr.write message
156 sys.stderr.write "\n"
157 end
158
159 fun test_empty do expect(false, "", "", new Array[Array[String]])
160
161 fun test_empty_eol do expect(false, "\r\n", "#", [[""]])
162
163 fun test_empty_skip do expect(true, "", "", new Array[Array[String]])
164
165 fun test_empty_skip1 do expect(true, "\r\n", "#", new Array[Array[String]])
166
167 fun test_empty_skip2 do expect(true, "\r\n\r\n", "##", new Array[Array[String]])
168
169 fun test_escaped do expect(false, "\"foo/\"\"\r\n,\"\r\n",
170 "/foo//\"\r\n,/#", [["foo/\"\r\n,"]])
171
172 fun test_unescaped do expect(false, "foo bar\r\n",
173 "foo bar#", [["foo bar"]])
174
175 fun test_escaped_no_eol do expect(false, "\"foo/\"\"\r\n,\"",
176 "/foo//\"\r\n,/", [["foo/\"\r\n,"]])
177
178 fun test_unescaped_no_eol do expect(false, "foo bar",
179 "foo bar", [["foo bar"]])
180
181 fun test_multiple_cells do expect(false, "\"1\",,\"/\"\r\n",
182 "/1/::////#", [["1", "", "/"]])
183
184 fun test_multiple_cells_unescaped do expect(false, "1,,/\r\n",
185 "1::////#", [["1", "", "/"]])
186
187 fun test_modal_escaping do expect(false, """a"b""/c","d"e""",
188 """/ab"///c:d/e/""", [["""ab"/c""", "de"]])
189
190 fun test_skip_start do expect(true, "\r\n1,,/\r\n",
191 "#1::////#", [["1", "", "/"]])
192
193 fun test_dont_skip_empty_delimited do expect(true, "\"\"\r\n",
194 "//#", [[""]])
195
196 fun test_dont_skip_multiple_empty_cells do expect(true, ",\r\n",
197 ":#", [["",""]])
198
199 fun test_mutiple_rows do expect(false, "\"a\r\nb#\",c\r\nd,\r\n,e\r\n",
200 "/a\r\nb#/:c#d:#:e#", [["a\r\nb#", "c"], ["d", ""], ["", "e"]])
201 end