View Javadoc
1   /*
2    * Copyright 2018 Andrew Rucker Jones.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.opencsv.bean;
17  
18  import com.opencsv.bean.mocks.number.*;
19  import com.opencsv.exceptions.CsvBadConverterException;
20  import com.opencsv.exceptions.CsvDataTypeMismatchException;
21  import com.opencsv.exceptions.CsvException;
22  import org.apache.commons.lang3.StringUtils;
23  import org.junit.jupiter.api.AfterEach;
24  import org.junit.jupiter.api.BeforeAll;
25  import org.junit.jupiter.api.BeforeEach;
26  import org.junit.jupiter.api.Test;
27  
28  import java.io.FileReader;
29  import java.io.IOException;
30  import java.io.StringReader;
31  import java.io.StringWriter;
32  import java.math.BigDecimal;
33  import java.math.BigInteger;
34  import java.util.Arrays;
35  import java.util.List;
36  import java.util.Locale;
37  
38  import static org.junit.jupiter.api.Assertions.*;
39  
40  /**
41   * Tests of the {@link CsvNumber} annotation.
42   *
43   * @author Andrew Rucker Jones
44   */
45  public class NumberTest {
46  
47      private static Locale systemLocale;
48  
49      @BeforeAll
50      public static void storeSystemLocale() {
51          systemLocale = Locale.getDefault();
52      }
53  
54      @BeforeEach
55      public void setSystemLocaleToValueNotGerman() {
56          Locale.setDefault(Locale.US);
57      }
58  
59      @AfterEach
60      public void setSystemLocaleBackToDefault() {
61          Locale.setDefault(systemLocale);
62      }
63  
64      /**
65       * Tests reading a value into a byte.
66       * Also incidentally tests:
67       * <ul><li>Reading with a HeaderColumnNameMappingStrategy</li>
68       * <li>Conversion without a locale</li></ul>
69       * @throws IOException If bad things happen
70       */
71      @Test
72      public void testPrimitiveByte() throws IOException {
73           List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
74                   .withType(NumberMockHeader.class)
75                   .withSeparator(';').build().parse();
76           assertNotNull(beans);
77           assertEquals(2, beans.size());
78           NumberMockHeader bean = beans.get(0);
79           assertEquals(3, bean.getPrimitiveByte());
80           bean = beans.get(1);
81           assertEquals(45, bean.getPrimitiveByte());
82      }
83  
84      /**
85       * Tests reading a value into a {@link java.lang.Byte}.
86       * Also incidentally tests:
87       * <ul><li>Conversion with a locale</li></ul>
88       * @throws IOException If bad things happen
89       */
90      @Test
91      public void testWrappedByte() throws IOException {
92          List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
93                  .withType(NumberMockHeader.class)
94                  .withSeparator(';').build().parse();
95          assertNotNull(beans);
96          assertEquals(2, beans.size());
97          NumberMockHeader bean = beans.get(0);
98          assertEquals(Byte.valueOf((byte)12), bean.getWrappedByte());
99          bean = beans.get(1);
100         assertEquals(Byte.valueOf((byte)67), bean.getWrappedByte());
101     }
102 
103     @Test
104     public void testPrimitiveShort() throws IOException {
105         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
106                 .withType(NumberMockHeader.class)
107                 .withSeparator(';').build().parse();
108         assertNotNull(beans);
109         assertEquals(2, beans.size());
110         NumberMockHeader bean = beans.get(0);
111         assertEquals(1, bean.getPrimitiveShort());
112         bean = beans.get(1);
113         assertEquals(2, bean.getPrimitiveShort());
114     }
115 
116     @Test
117     public void testWrappedShort() throws IOException {
118         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
119                 .withType(NumberMockHeader.class)
120                 .withSeparator(';').build().parse();
121         assertNotNull(beans);
122         assertEquals(2, beans.size());
123         NumberMockHeader bean = beans.get(0);
124         assertEquals(Short.valueOf((short)23), bean.getWrappedShort());
125         bean = beans.get(1);
126         assertEquals(Short.valueOf((short)45), bean.getWrappedShort());
127     }
128 
129     @Test
130     public void testPrimitiveInteger() throws IOException {
131         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
132                 .withType(NumberMockHeader.class)
133                 .withSeparator(';').build().parse();
134         assertNotNull(beans);
135         assertEquals(2, beans.size());
136         NumberMockHeader bean = beans.get(0);
137         assertEquals(1234, bean.getPrimitiveInteger());
138         bean = beans.get(1);
139         assertEquals(4321, bean.getPrimitiveInteger());
140     }
141 
142     @Test
143     public void testWrappedInteger() throws IOException {
144         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
145                 .withType(NumberMockHeader.class)
146                 .withSeparator(';').build().parse();
147         assertNotNull(beans);
148         assertEquals(2, beans.size());
149         NumberMockHeader bean = beans.get(0);
150         assertEquals(Integer.valueOf(5), bean.getWrappedInteger());
151         bean = beans.get(1);
152         assertEquals(Integer.valueOf(6), bean.getWrappedInteger());
153     }
154 
155     @Test
156     public void testPrimitiveLong() throws IOException {
157         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
158                 .withType(NumberMockHeader.class)
159                 .withSeparator(';').build().parse();
160         assertNotNull(beans);
161         assertEquals(2, beans.size());
162         NumberMockHeader bean = beans.get(0);
163         assertEquals(123456789L, bean.getPrimitiveLong());
164         bean = beans.get(1);
165         assertEquals(987654321L, bean.getPrimitiveLong());
166     }
167 
168     @Test
169     public void testWrappedLong() throws IOException {
170         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
171                 .withType(NumberMockHeader.class)
172                 .withSeparator(';').build().parse();
173         assertNotNull(beans);
174         assertEquals(2, beans.size());
175         NumberMockHeader bean = beans.get(0);
176         assertEquals(Long.valueOf(987654321L), bean.getWrappedLong());
177         bean = beans.get(1);
178         assertEquals(Long.valueOf(123456789L), bean.getWrappedLong());
179     }
180 
181     @Test
182     public void testPrimitiveFloat() throws IOException {
183         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
184                 .withType(NumberMockHeader.class)
185                 .withSeparator(';').build().parse();
186         assertNotNull(beans);
187         assertEquals(2, beans.size());
188         NumberMockHeader bean = beans.get(0);
189         assertEquals(0.12, bean.getPrimitiveFloat(), 0.001);
190         bean = beans.get(1);
191         assertEquals(0.21, bean.getPrimitiveFloat(), 0.001);
192     }
193 
194     @Test
195     public void testWrappedFloat() throws IOException {
196         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
197                 .withType(NumberMockHeader.class)
198                 .withSeparator(';').build().parse();
199         assertNotNull(beans);
200         assertEquals(2, beans.size());
201         NumberMockHeader bean = beans.get(0);
202         assertEquals(0.2345, bean.getWrappedFloat(), 0.00001);
203         bean = beans.get(1);
204         assertEquals(0.2346, bean.getWrappedFloat(), 0.00001);
205     }
206 
207     @Test
208     public void testPrimitiveDouble() throws IOException {
209         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
210                 .withType(NumberMockHeader.class)
211                 .withSeparator(';').build().parse();
212         assertNotNull(beans);
213         assertEquals(2, beans.size());
214         NumberMockHeader bean = beans.get(0);
215         assertEquals(10.1234, bean.getPrimitiveDouble(), 0.001);
216         bean = beans.get(1);
217         assertEquals(19.1234, bean.getPrimitiveDouble(), 0.001);
218     }
219 
220     @Test
221     public void testWrappedDouble() throws IOException {
222         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
223                 .withType(NumberMockHeader.class)
224                 .withSeparator(';').build().parse();
225         assertNotNull(beans);
226         assertEquals(2, beans.size());
227         NumberMockHeader bean = beans.get(0);
228         assertEquals(1.0, bean.getWrappedDouble(), 0.001);
229         bean = beans.get(1);
230         assertEquals(2.0, bean.getWrappedDouble(), 0.001);
231     }
232 
233     /**
234      * Tests formatting of a {@link java.math.BigDecimal}.
235      * Also incidentally tests:
236      * <ul><li>Mapping with {@link ColumnPositionMappingStrategy}</li></ul>
237      * @throws IOException If bad things happen
238      */
239     @Test
240     public void testBigDecimal() throws IOException {
241         List<NumberMockColumn> beans = new CsvToBeanBuilder<NumberMockColumn>(new FileReader("src/test/resources/testnumberbypositiongood.csv"))
242                 .withType(NumberMockColumn.class)
243                 .withSeparator(';').build().parse();
244         assertNotNull(beans);
245         assertEquals(2, beans.size());
246         NumberMockColumn bean = beans.get(0);
247         assertEquals(BigDecimal.valueOf(1.2), bean.getBigDecimal());
248         bean = beans.get(1);
249         assertEquals(BigDecimal.valueOf(2.1), bean.getBigDecimal());
250     }
251 
252     @Test
253     public void testBigInteger() throws IOException {
254         List<NumberMockColumn> beans = new CsvToBeanBuilder<NumberMockColumn>(new FileReader("src/test/resources/testnumberbypositiongood.csv"))
255                 .withType(NumberMockColumn.class)
256                 .withSeparator(';').build().parse();
257         assertNotNull(beans);
258         assertEquals(2, beans.size());
259         NumberMockColumn bean = beans.get(0);
260         assertEquals(BigInteger.valueOf(34L), bean.getBigInteger());
261         bean = beans.get(1);
262         assertEquals(BigInteger.valueOf(43L), bean.getBigInteger());
263     }
264 
265     @Test
266     public void testUnparsableNumber() throws IOException {
267         CsvToBean<NumberMockHeader> csvToBean = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynameunparsable.csv"))
268                 .withType(NumberMockHeader.class).withThrowExceptions(false)
269                 .withSeparator(';').build();
270         List<NumberMockHeader> beans = csvToBean.parse();
271         assertNotNull(beans);
272         assertTrue(beans.isEmpty());
273         List<CsvException> thrownExceptions = csvToBean.getCapturedExceptions();
274         assertNotNull(thrownExceptions);
275         assertEquals(1, thrownExceptions.size());
276         CsvException e = thrownExceptions.get(0);
277         assertTrue(e instanceof CsvDataTypeMismatchException);
278         CsvDataTypeMismatchException csve = (CsvDataTypeMismatchException) e;
279         assertEquals("\u20BE \u20BE \u20BE 1.2 \u20BE \u20BE \u20BE", csve.getSourceObject());
280         assertEquals(Byte.class, csve.getDestinationClass());
281         assertEquals(2, csve.getLineNumber());
282         assertNotNull(csve.getLine());
283         assertNotNull(csve.getCause());
284     }
285 
286     @Test
287     public void testEmptyOptionalInput() {
288         StringReader reader = new StringReader("primitiveByte;wrappedByte;primitiveShort;wrappedShort;primitiveInteger;wrappedInteger;primitiveLong;wrappedLong;primitiveFloat;wrappedFloat;primitiveDouble;wrappedDouble\n" +
289                 "byte: 3;;1;23;1.234;5;123456789;987654321;1.2E-1;23,45%;10.1234;1\n");
290         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(reader)
291                 .withType(NumberMockHeader.class)
292                 .withSeparator(';').build().parse();
293         assertNotNull(beans);
294         assertEquals(1, beans.size());
295         NumberMockHeader bean = beans.get(0);
296         assertEquals(3, bean.getPrimitiveByte());
297         assertNull(bean.getWrappedByte());
298         assertEquals(1, bean.getPrimitiveShort());
299         assertEquals(23, (short)bean.getWrappedShort());
300         assertEquals(1234, bean.getPrimitiveInteger());
301         assertEquals(5, (int)bean.getWrappedInteger());
302         assertEquals(123456789L, bean.getPrimitiveLong());
303         assertEquals(987654321L, (long)bean.getWrappedLong());
304         assertEquals(0.12f, bean.getPrimitiveFloat(), 0.001);
305         assertEquals(0.2345f, bean.getWrappedFloat(), 0.001);
306         assertEquals(10.1234, bean.getPrimitiveDouble(), 0.00001);
307         assertEquals(1.0, bean.getWrappedDouble(), 0.1);
308     }
309 
310     @Test
311     public void testWritingHeaderNameMappingStrategy() throws IOException, CsvException {
312         List<NumberMockHeader> beans = new CsvToBeanBuilder<NumberMockHeader>(new FileReader("src/test/resources/testnumberbynamegood.csv"))
313                 .withType(NumberMockHeader.class)
314                 .withSeparator(';').build().parse();
315         StringWriter w = new StringWriter();
316         new StatefulBeanToCsvBuilder<NumberMockHeader>(w)
317                 .withSeparator(';')
318                 .withApplyQuotesToAll(false)
319                 .build()
320                 .write(beans);
321         assertEquals("PRIMITIVEBYTE;PRIMITIVEDOUBLE;PRIMITIVEFLOAT;PRIMITIVEINTEGER;PRIMITIVELONG;PRIMITIVESHORT;WRAPPEDBYTE;WRAPPEDDOUBLE;WRAPPEDFLOAT;WRAPPEDINTEGER;WRAPPEDLONG;WRAPPEDSHORT\n" +
322                 "byte: 3;10.1234;1.2E-1;1.234;123456789;1;¥ ¥ ¥ 12 ¥ ¥ ¥;1;23,45%;5;987654321;23\n" +
323                 "byte: 45;19.1234;2.1E-1;4.321;987654321;2;¥ ¥ ¥ 67 ¥ ¥ ¥;2;23,46%;6;123456789;45\n",
324                 w.toString());
325     }
326 
327     /**
328      * Tests writing numerical values using {@link CsvNumber} and the column
329      * position mapping strategy.
330      * Also incidentally tests:
331      * <ul>
332      * <li>Using a different format string for writing than reading</li>
333      * <li>Using a different format string for writing, but leaving
334      * {@link CsvNumber#writeFormatEqualsReadFormat()} {@code true}</li>
335      * </ul>
336      *
337      * @throws IOException  Never thrown
338      * @throws CsvException Never thrown
339      */
340     @Test
341     public void testWritingColumnPositionMappingStrategy() throws IOException, CsvException {
342         List<NumberMockColumn> beans = new CsvToBeanBuilder<NumberMockColumn>(new FileReader("src/test/resources/testnumberbypositiongood.csv"))
343                 .withType(NumberMockColumn.class)
344                 .withSeparator(';').build().parse();
345         StringWriter w = new StringWriter();
346         new StatefulBeanToCsvBuilder<NumberMockColumn>(w)
347                 .withSeparator(';')
348                 .withApplyQuotesToAll(false)
349                 .build()
350                 .write(beans);
351         assertEquals("1.2yeah;34\n2.1yeah;43\n",
352                 w.toString());
353     }
354 
355     @Test
356     public void testNonNumber() {
357         try {
358             new CsvToBeanBuilder<NumberNonNumber>(new StringReader("test\\nteststring"))
359                     .withType(NumberNonNumber.class)
360                     .build();
361             fail("Exception should have been thrown");
362         } catch (CsvBadConverterException e) {
363             assertEquals(ConverterNumber.class, e.getConverterClass());
364             assertTrue(StringUtils.isNotBlank(e.getLocalizedMessage()));
365         }
366     }
367 
368     @Test
369     public void testInvalidPatternReading() {
370         try {
371             new CsvToBeanBuilder<NumberInvalidPatternReading>(new StringReader("number\\n3"))
372                     .withType(NumberInvalidPatternReading.class)
373                     .build();
374             fail("Exception should have been thrown");
375         } catch (CsvBadConverterException e) {
376             assertEquals(ConverterNumber.class, e.getConverterClass());
377             assertTrue(StringUtils.isNotBlank(e.getLocalizedMessage()));
378         }
379     }
380 
381     @Test
382     public void testInvalidPatternWriting() throws CsvException {
383         try {
384             new StatefulBeanToCsvBuilder<NumberInvalidPatternWriting>(new StringWriter())
385                     .build().write(new NumberInvalidPatternWriting(1));
386             fail("Exception should have been thrown");
387         } catch (CsvBadConverterException e) {
388             assertEquals(ConverterNumber.class, e.getConverterClass());
389             assertTrue(StringUtils.isNotBlank(e.getLocalizedMessage()));
390         }
391     }
392 
393     @Test
394     public void testEmptyPattern() {
395         CsvToBean<NumberEmptyPattern> csvToBean = new CsvToBeanBuilder<NumberEmptyPattern>(new StringReader("number\n3"))
396                 .withType(NumberEmptyPattern.class)
397                 .build();
398         List<NumberEmptyPattern> beans = csvToBean.parse();
399         assertNotNull(beans);
400         assertEquals(1, beans.size());
401         assertEquals(3L, (long)beans.get(0).getNumber());
402     }
403 
404     @Test
405     public void testWriteNull() throws CsvException {
406         StringWriter w = new StringWriter();
407         new StatefulBeanToCsvBuilder<NumberMockColumn>(w)
408                 .withSeparator(';')
409                 .withApplyQuotesToAll(false)
410                 .build()
411                 .write(new NumberMockColumn());
412         assertEquals(";\n",
413                 w.toString());
414     }
415     
416     /**
417      * Tests writing {@link java.math.BigDecimal}s that need rounding.
418      *
419      * @throws CsvException Never thrown
420      */
421     @Test
422     public void testWriteRoundingMode() throws CsvException {
423         NumberMockRoundingMode b1 = new NumberMockRoundingMode();
424         b1.setRoundUp(BigDecimal.valueOf(5.5));
425         b1.setRoundDown(BigDecimal.valueOf(5.5));
426         b1.setRoundCeiling(BigDecimal.valueOf(5.5));
427         b1.setRoundFloor(BigDecimal.valueOf(5.5));
428         b1.setRoundHalfUp(BigDecimal.valueOf(5.5));
429         b1.setRoundHalfDown(BigDecimal.valueOf(5.5));
430         b1.setRoundHalfEven(BigDecimal.valueOf(5.5));
431         b1.setRoundUnnecessary(BigDecimal.valueOf(5.0));
432         
433         NumberMockRoundingMode b2 = new NumberMockRoundingMode();
434         b2.setRoundUp(BigDecimal.valueOf(5.5));
435         b2.setRoundDown(BigDecimal.valueOf(5.5));
436         b2.setRoundCeiling(BigDecimal.valueOf(5.5));
437         b2.setRoundFloor(BigDecimal.valueOf(5.5));
438         b2.setRoundHalfUp(BigDecimal.valueOf(5.5));
439         b2.setRoundHalfDown(BigDecimal.valueOf(5.5));
440         b2.setRoundHalfEven(BigDecimal.valueOf(5.5));
441         b2.setRoundUnnecessary(BigDecimal.valueOf(5.5));
442         
443         
444         List<NumberMockRoundingMode> beans = Arrays.asList(b1, b2);
445         StringWriter w = new StringWriter();
446         StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder<NumberMockRoundingMode>(w)
447                 .withApplyQuotesToAll(false)
448                 .withThrowExceptions(false)
449                 .build();
450         beanToCsv.write(beans);
451         assertEquals("6,5,6,5,6,5,6,5\n", w.toString());
452         
453         List<CsvException> errors = beanToCsv.getCapturedExceptions();
454         assertNotNull(errors);
455         assertEquals(1, errors.size());
456         CsvException e = errors.get(0);
457         assertTrue(e instanceof CsvDataTypeMismatchException);
458         assertTrue(e.getCause() instanceof ArithmeticException);
459     }
460 }