1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.csv;
19
20 import java.io.IOException;
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.stream.Collectors;
24 import java.util.stream.Stream;
25
26 import org.junit.jupiter.api.Assertions;
27 import org.junit.jupiter.params.ParameterizedTest;
28 import org.junit.jupiter.params.provider.Arguments;
29 import org.junit.jupiter.params.provider.MethodSource;
30
31
32
33
34
35 public class CSVDuplicateHeaderTest {
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 static Stream<Arguments> duplicateHeaderAllowsMissingColumnsNamesData() {
52 return duplicateHeaderData()
53 .filter(arg -> Boolean.TRUE.equals(arg.get()[1]) && Boolean.FALSE.equals(arg.get()[2]))
54 .flatMap(arg -> {
55
56 final Object[][] data = new Object[4][];
57 final Boolean[] flags = {Boolean.TRUE, Boolean.FALSE};
58 int i = 0;
59 for (final Boolean a : flags) {
60 for (final Boolean b : flags) {
61 data[i] = arg.get().clone();
62 data[i][1] = a;
63 data[i][2] = b;
64 i++;
65 }
66 }
67 return Arrays.stream(data).map(Arguments::of);
68 });
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82 static Stream<Arguments> duplicateHeaderData() {
83 return Stream.of(
84
85 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "B"}, true),
86 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "B"}, true),
87 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "B"}, true),
88 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "B"}, true),
89 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "B"}, true),
90 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "B"}, true),
91
92
93 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", ""}, false),
94 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", ""}, false),
95 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", ""}, false),
96 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", ""}, true),
97 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", ""}, true),
98 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", ""}, true),
99
100
101 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", " "}, false),
102 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", " "}, false),
103 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", " "}, false),
104 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", " "}, true),
105 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", " "}, true),
106 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", " "}, true),
107
108
109 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", null}, false),
110 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", null}, false),
111 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", null}, false),
112 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", null}, true),
113 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", null}, true),
114 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", null}, true),
115
116
117 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "A"}, false),
118 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "A"}, false),
119 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "A"}, true),
120 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "A"}, false),
121 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "A"}, false),
122 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "A"}, true),
123
124
125 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"", ""}, false),
126 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"", ""}, false),
127 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"", ""}, false),
128 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"", ""}, false),
129 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"", ""}, true),
130 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"", ""}, true),
131
132
133 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {" ", " "}, false),
134 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {" ", " "}, false),
135 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {" ", " "}, false),
136 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {" ", " "}, false),
137 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {" ", " "}, true),
138 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {" ", " "}, true),
139
140
141 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {" ", " "}, false),
142 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {" ", " "}, false),
143 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {" ", " "}, false),
144 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {" ", " "}, false),
145 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {" ", " "}, true),
146 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {" ", " "}, true),
147
148
149 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {null, null}, false),
150 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {null, null}, false),
151 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {null, null}, false),
152 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {null, null}, false),
153 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {null, null}, true),
154 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {null, null}, true),
155
156
157 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {" ", " "}, false),
158 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {" ", " "}, false),
159 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {" ", " "}, false),
160 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {" ", " "}, false),
161 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {" ", " "}, true),
162 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {" ", " "}, true),
163
164
165 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {" ", null}, false),
166 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {" ", null}, false),
167 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {" ", null}, false),
168 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {" ", null}, false),
169 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {" ", null}, true),
170 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {" ", null}, true),
171
172
173 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "A", "", ""}, false),
174 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "A", "", ""}, false),
175 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "A", "", ""}, false),
176 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "A", "", ""}, false),
177 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "A", "", ""}, false),
178 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "A", "", ""}, true),
179
180
181 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "B", "", ""}, false),
182 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "B", "", ""}, false),
183 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "B", "", ""}, false),
184 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "B", "", ""}, false),
185 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "B", "", ""}, true),
186 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "B", "", ""}, true),
187
188
189 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "A", " ", " "}, false),
190 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "A", " ", " "}, false),
191 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "A", " ", " "}, false),
192 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "A", " ", " "}, false),
193 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "A", " ", " "}, false),
194 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "A", " ", " "}, true),
195
196
197 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "A", null, null}, false),
198 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "A", null, null}, false),
199 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "A", null, null}, false),
200 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "A", null, null}, false),
201 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "A", null, null}, false),
202 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "A", null, null}, true),
203
204
205 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", "", ""}, false),
206 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", "", ""}, false),
207 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", "", ""}, false),
208 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", "", ""}, false),
209 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", "", ""}, true),
210 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", "", ""}, true),
211
212
213 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", null, null}, false),
214 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", null, null}, false),
215 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", null, null}, false),
216 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", null, null}, false),
217 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", null, null}, true),
218 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", null, null}, true),
219
220
221 Arguments.of(DuplicateHeaderMode.DISALLOW, false, false, new String[] {"A", " ", " "}, false),
222 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, false, new String[] {"A", " ", " "}, false),
223 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, false, new String[] {"A", " ", " "}, false),
224 Arguments.of(DuplicateHeaderMode.DISALLOW, true, false, new String[] {"A", " ", " "}, false),
225 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, false, new String[] {"A", " ", " "}, true),
226 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, false, new String[] {"A", " ", " "}, true),
227
228
229 Arguments.of(DuplicateHeaderMode.DISALLOW, false, true , new String[] {"A", "a"}, false),
230 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, true , new String[] {"A", "a"}, false),
231 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, true , new String[] {"A", "a"}, true),
232 Arguments.of(DuplicateHeaderMode.DISALLOW, true, true , new String[] {"A", "a"}, false),
233 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, true , new String[] {"A", "a"}, false),
234 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, true , new String[] {"A", "a"}, true),
235
236
237 Arguments.of(DuplicateHeaderMode.DISALLOW, false, true, new String[] {"A", "a", "", ""}, false),
238 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, true, new String[] {"A", "a", "", ""}, false),
239 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, true, new String[] {"A", "a", "", ""}, false),
240 Arguments.of(DuplicateHeaderMode.DISALLOW, true, true, new String[] {"A", "a", "", ""}, false),
241 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, true, new String[] {"A", "a", "", ""}, false),
242 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, true, new String[] {"A", "a", "", ""}, true),
243
244
245 Arguments.of(DuplicateHeaderMode.DISALLOW, false, true, new String[] {"A", "a", " ", " "}, false),
246 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, true, new String[] {"A", "a", " ", " "}, false),
247 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, true, new String[] {"A", "a", " ", " "}, false),
248 Arguments.of(DuplicateHeaderMode.DISALLOW, true, true, new String[] {"A", "a", " ", " "}, false),
249 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, true, new String[] {"A", "a", " ", " "}, false),
250 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, true, new String[] {"A", "a", " ", " "}, true),
251
252
253 Arguments.of(DuplicateHeaderMode.DISALLOW, false, true, new String[] {"A", "a", null, null}, false),
254 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, false, true, new String[] {"A", "a", null, null}, false),
255 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, false, true, new String[] {"A", "a", null, null}, false),
256 Arguments.of(DuplicateHeaderMode.DISALLOW, true, true, new String[] {"A", "a", null, null}, false),
257 Arguments.of(DuplicateHeaderMode.ALLOW_EMPTY, true, true, new String[] {"A", "a", null, null}, false),
258 Arguments.of(DuplicateHeaderMode.ALLOW_ALL, true, true, new String[] {"A", "a", null, null}, true)
259 );
260 }
261
262
263
264
265
266
267
268
269
270
271 @ParameterizedTest
272 @MethodSource(value = {"duplicateHeaderAllowsMissingColumnsNamesData"})
273 public void testCSVFormat(final DuplicateHeaderMode duplicateHeaderMode,
274 final boolean allowMissingColumnNames,
275 final boolean ignoreHeaderCase,
276 final String[] headers,
277 final boolean valid) {
278 final CSVFormat.Builder builder =
279 CSVFormat.DEFAULT.builder()
280 .setDuplicateHeaderMode(duplicateHeaderMode)
281 .setAllowMissingColumnNames(allowMissingColumnNames)
282 .setIgnoreHeaderCase(ignoreHeaderCase)
283 .setHeader(headers);
284 if (valid) {
285 final CSVFormat format = builder.build();
286 Assertions.assertEquals(duplicateHeaderMode, format.getDuplicateHeaderMode(), "DuplicateHeaderMode");
287 Assertions.assertEquals(allowMissingColumnNames, format.getAllowMissingColumnNames(), "AllowMissingColumnNames");
288 Assertions.assertArrayEquals(headers, format.getHeader(), "Header");
289 } else {
290 Assertions.assertThrows(IllegalArgumentException.class, builder::build);
291 }
292 }
293
294
295
296
297
298
299
300
301
302
303
304 @ParameterizedTest
305 @MethodSource(value = {"duplicateHeaderData"})
306 public void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode,
307 final boolean allowMissingColumnNames,
308 final boolean ignoreHeaderCase,
309 final String[] headers,
310 final boolean valid) throws IOException {
311 final CSVFormat format =
312 CSVFormat.DEFAULT.builder()
313 .setDuplicateHeaderMode(duplicateHeaderMode)
314 .setAllowMissingColumnNames(allowMissingColumnNames)
315 .setIgnoreHeaderCase(ignoreHeaderCase)
316 .setNullString("NULL")
317 .setHeader()
318 .build();
319 final String input = Arrays.stream(headers)
320 .map(s -> s == null ? format.getNullString() : s)
321 .collect(Collectors.joining(format.getDelimiterString()));
322 if (valid) {
323 try(CSVParser parser = CSVParser.parse(input, format)) {
324
325 final List<String> expected =
326 Arrays.stream(headers)
327 .filter(s -> s != null)
328 .collect(Collectors.toList());
329 Assertions.assertEquals(expected, parser.getHeaderNames(), "HeaderNames");
330 }
331 } else {
332 Assertions.assertThrows(IllegalArgumentException.class, () -> CSVParser.parse(input, format));
333 }
334 }
335 }