View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration2.convert;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertSame;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  
24  import java.io.File;
25  import java.lang.annotation.ElementType;
26  import java.math.BigDecimal;
27  import java.nio.file.Path;
28  import java.nio.file.Paths;
29  import java.util.regex.Pattern;
30  
31  import org.apache.commons.configuration2.ex.ConversionException;
32  import org.junit.jupiter.api.Disabled;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * Test class for PropertyConverter.
37   */
38  public class TestPropertyConverter {
39      /** Constant for an enumeration class used by some tests. */
40      private static final Class<ElementType> ENUM_CLASS = ElementType.class;
41  
42      /**
43       * See CONFIGURATION-766.
44       */
45      @Test
46      void testToBigDecimalDoubleConstructor() {
47          // If the conversion uses new BigDecimal(0.1) the result is not exact due to round off.
48          // The result is 0.1000000000000000055511151231257827021181583404541015625.
49          // See Sonar rule: https://rules.sonarsource.com/java/type/Bug/RSPEC-2111
50          final double d = 0.1;
51          // Use BigDecimal#valueOf() Fix PMD AvoidDecimalLiteralsInBigDecimalConstructor
52          assertEquals(BigDecimal.valueOf(d), PropertyConverter.toBigDecimal(d));
53      }
54  
55      /**
56       * See CONFIGURATION-766.
57       */
58      @Test
59      @Disabled
60      void testToBigDecimalStringConstructor() {
61          // If the conversion uses new BigDecimal(0.1) the result is not exact due to round off.
62          // The result is 0.1000000000000000055511151231257827021181583404541015625.
63          // See Sonar rule: https://rules.sonarsource.com/java/type/Bug/RSPEC-2111
64          final double d = 0.1;
65          assertEquals(new BigDecimal(Double.toString(d)), PropertyConverter.toBigDecimal(d));
66      }
67  
68      /**
69       * Tests a failed conversion to character.
70       */
71      @Test
72      void testToCharFailed() {
73          final DefaultConversionHandler conversionHandler = new DefaultConversionHandler();
74          assertThrows(ConversionException.class, () -> PropertyConverter.to(Character.TYPE, "FF", conversionHandler));
75      }
76  
77      /**
78       * Tests whether a conversion to character is possible.
79       */
80      @Test
81      void testToCharSuccess() {
82          assertEquals(Character.valueOf('t'), PropertyConverter.to(Character.class, "t", new DefaultConversionHandler()));
83      }
84  
85      /**
86       * Tests whether other objects implementing a toString() method can be converted to character.
87       */
88      @Test
89      void testToCharViaToString() {
90          final Object value = new Object() {
91              @Override
92              public String toString() {
93                  return "X";
94              }
95          };
96          assertEquals(Character.valueOf('X'), PropertyConverter.to(Character.TYPE, value, new DefaultConversionHandler()));
97      }
98  
99      @Test
100     void testToCustomNumber() {
101         assertEquals(new MyNumber(1), PropertyConverter.to(MyNumber.class, "1", null));
102         assertEquals(new MyNumber(2), PropertyConverter.to(MyNumber.class, new MyNumber(2), null));
103         assertEquals(new MyNumber(0), PropertyConverter.to(MyNumber.class, null, null));
104     }
105 
106     @Test
107     void testToEnumFromEnum() {
108         assertEquals(ElementType.METHOD, PropertyConverter.toEnum(ElementType.METHOD, ENUM_CLASS));
109     }
110 
111     @Test
112     void testToEnumFromInvalidNumber() {
113         assertThrows(ConversionException.class, () -> PropertyConverter.toEnum(-1, ENUM_CLASS));
114     }
115 
116     @Test
117     void testToEnumFromInvalidString() {
118         assertThrows(ConversionException.class, () -> PropertyConverter.toEnum("FOO", ENUM_CLASS));
119     }
120 
121     @Test
122     void testToEnumFromNumber() {
123         assertEquals(PropertyConverter.toEnum(Integer.valueOf(ElementType.METHOD.ordinal()), ENUM_CLASS), ElementType.METHOD);
124     }
125 
126     @Test
127     void testToEnumFromString() {
128         assertEquals(ElementType.METHOD, PropertyConverter.toEnum("METHOD", ENUM_CLASS));
129     }
130 
131     /**
132      * Tests conversion to files when the passed in objects are already files.
133      */
134     @Test
135     void testToFileDirect() {
136         final File f = new File("dir", "file");
137         assertSame(f, PropertyConverter.toFile(f));
138     }
139 
140     /**
141      * Tests conversion to file when the passed in objects are paths.
142      */
143     @Test
144     void testToFileFromPath() {
145         final Path p = Paths.get("dir", "file");
146         assertEquals(new File("dir", "file"), PropertyConverter.toFile(p));
147     }
148 
149     /**
150      * Tests conversion to file when the passed in objects have a compatible string representation.
151      */
152     @Test
153     void testToFileFromString() {
154         assertEquals(new File("dir", "file"), PropertyConverter.toFile("dir/file"));
155     }
156 
157     /**
158      * Tests a trivial conversion: the value has already the desired type.
159      */
160     @Test
161     void testToNoConversionNeeded() {
162         final String value = "testValue";
163         assertEquals(value, PropertyConverter.to(String.class, value, new DefaultConversionHandler()));
164     }
165 
166     /**
167      * Tests conversion to numbers when the passed in objects are already numbers.
168      */
169     @Test
170     void testToNumberDirect() {
171         final Integer i = Integer.valueOf(42);
172         assertSame(i, PropertyConverter.toNumber(i, Integer.class));
173         final BigDecimal d = new BigDecimal("3.1415");
174         assertSame(d, PropertyConverter.toNumber(d, Integer.class));
175     }
176 
177     /**
178      * Tests conversion to numbers when the passed in objects are strings with prefixes for special radices.
179      */
180     @Test
181     void testToNumberFromBinaryString() {
182         final Number n = PropertyConverter.toNumber("0b1111", Integer.class);
183         assertEquals(15, n.intValue());
184     }
185 
186     /**
187      * Tests conversion to numbers when the passed in objects are strings with prefixes for special radices.
188      */
189     @Test
190     void testToNumberFromHexString() {
191         final Number n = PropertyConverter.toNumber("0x10", Integer.class);
192         assertEquals(16, n.intValue());
193     }
194 
195     /**
196      * Tests conversion to numbers when an invalid binary value is passed in. This should cause an exception.
197      */
198     @Test
199     void testToNumberFromInvalidBinaryString() {
200         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("0bNotABinValue", Integer.class));
201     }
202 
203     /**
204      * Tests conversion to numbers when an invalid Hex value is passed in. This should cause an exception.
205      */
206     @Test
207     void testToNumberFromInvalidHexString() {
208         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("0xNotAHexValue", Integer.class));
209     }
210 
211     /**
212      * Tests conversion to numbers when the passed in objects have no numeric String representation. This should cause an
213      * exception.
214      */
215     @Test
216     void testToNumberFromInvalidString() {
217         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("Not a number", Byte.class));
218     }
219 
220     /**
221      * Tests conversion to numbers when the passed in objects have a compatible string representation.
222      */
223     @Test
224     void testToNumberFromString() {
225         assertEquals(Integer.valueOf(42), PropertyConverter.toNumber("42", Integer.class));
226         assertEquals(Short.valueOf((short) 10), PropertyConverter.toNumber(new StringBuffer("10"), Short.class));
227     }
228 
229     /**
230      * Tests conversion to numbers when the passed in target class is invalid. This should cause an exception.
231      */
232     @Test
233     void testToNumberWithInvalidClass() {
234         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("42", Object.class));
235     }
236 
237     /**
238      * Tests conversion to paths when the passed in objects are already paths.
239      */
240     @Test
241     void testToPathDirect() {
242         final Path p = Paths.get("dir", "file");
243         assertSame(p, PropertyConverter.toPath(p));
244     }
245 
246     /**
247      * Tests conversion to path when the passed in objects are files.
248      */
249     @Test
250     void testToPathFromFile() {
251         final File f = new File("dir", "file");
252         assertEquals(Paths.get("dir", "file"), PropertyConverter.toPath(f));
253     }
254 
255     /**
256      * Tests conversion to file when the passed in objects have a compatible string representation.
257      */
258     @Test
259     void testToPathFromString() {
260         assertEquals(Paths.get("dir", "file"), PropertyConverter.toPath("dir/file"));
261     }
262 
263     /**
264      * Tests conversion to patterns when the passed in objects are already patterns.
265      */
266     @Test
267     void testToPatternDirect() {
268         final Pattern p = Pattern.compile(".+");
269         assertSame(p, PropertyConverter.toPattern(p));
270     }
271 
272     /**
273      * Tests conversion to patterns when the passed in objects have a compatible string representation.
274      */
275     @Test
276     void testToPatternFromString() {
277         final Pattern p = Pattern.compile(".+");
278         assertEquals(p.pattern(), PropertyConverter.toPattern(".+").pattern());
279     }
280 
281     /**
282      * Tests a conversion to a string.
283      */
284     @Test
285     void testToStringConversion() {
286         final Integer src = 42;
287         final Object result = PropertyConverter.to(String.class, src, new DefaultConversionHandler());
288         assertEquals("42", result);
289     }
290 }