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  
40      /** Constant for an enumeration class used by some tests. */
41      private static final Class<ElementType> ENUM_CLASS = ElementType.class;
42  
43      /**
44       * See CONFIGURATION-766.
45       */
46      @Test
47      void testToBigDecimalDoubleConstructor() {
48          // If the conversion uses new BigDecimal(0.1) the result is not exact due to round off.
49          // The result is 0.1000000000000000055511151231257827021181583404541015625.
50          // See Sonar rule: https://rules.sonarsource.com/java/type/Bug/RSPEC-2111
51          final double d = 0.1;
52          // Use BigDecimal#valueOf() Fix PMD AvoidDecimalLiteralsInBigDecimalConstructor
53          assertEquals(BigDecimal.valueOf(d), PropertyConverter.toBigDecimal(d));
54      }
55  
56      /**
57       * See CONFIGURATION-766.
58       */
59      @Test
60      @Disabled
61      void testToBigDecimalStringConstructor() {
62          // If the conversion uses new BigDecimal(0.1) the result is not exact due to round off.
63          // The result is 0.1000000000000000055511151231257827021181583404541015625.
64          // See Sonar rule: https://rules.sonarsource.com/java/type/Bug/RSPEC-2111
65          final double d = 0.1;
66          assertEquals(new BigDecimal(Double.toString(d)), PropertyConverter.toBigDecimal(d));
67      }
68  
69      /**
70       * Tests a failed conversion to character.
71       */
72      @Test
73      void testToCharFailed() {
74          final DefaultConversionHandler conversionHandler = new DefaultConversionHandler();
75          assertThrows(ConversionException.class, () -> PropertyConverter.to(Character.TYPE, "FF", conversionHandler));
76      }
77  
78      /**
79       * Tests whether a conversion to character is possible.
80       */
81      @Test
82      void testToCharSuccess() {
83          assertEquals(Character.valueOf('t'), PropertyConverter.to(Character.class, "t", new DefaultConversionHandler()));
84      }
85  
86      /**
87       * Tests whether other objects implementing a toString() method can be converted to character.
88       */
89      @Test
90      void testToCharViaToString() {
91          final Object value = new Object() {
92              @Override
93              public String toString() {
94                  return "X";
95              }
96          };
97          assertEquals(Character.valueOf('X'), PropertyConverter.to(Character.TYPE, value, new DefaultConversionHandler()));
98      }
99  
100     @Test
101     void testToCustomNumber() {
102         assertEquals(new MyNumber(1), PropertyConverter.to(MyNumber.class, "1", null));
103         assertEquals(new MyNumber(2), PropertyConverter.to(MyNumber.class, new MyNumber(2), null));
104         assertEquals(new MyNumber(0), PropertyConverter.to(MyNumber.class, null, null));
105     }
106 
107     @Test
108     void testToEnumFromEnum() {
109         assertEquals(ElementType.METHOD, PropertyConverter.toEnum(ElementType.METHOD, ENUM_CLASS));
110     }
111 
112     @Test
113     void testToEnumFromInvalidNumber() {
114         assertThrows(ConversionException.class, () -> PropertyConverter.toEnum(-1, ENUM_CLASS));
115     }
116 
117     @Test
118     void testToEnumFromInvalidString() {
119         assertThrows(ConversionException.class, () -> PropertyConverter.toEnum("FOO", ENUM_CLASS));
120     }
121 
122     @Test
123     void testToEnumFromNumber() {
124         assertEquals(PropertyConverter.toEnum(Integer.valueOf(ElementType.METHOD.ordinal()), ENUM_CLASS), ElementType.METHOD);
125     }
126 
127     @Test
128     void testToEnumFromString() {
129         assertEquals(ElementType.METHOD, PropertyConverter.toEnum("METHOD", ENUM_CLASS));
130     }
131 
132     /**
133      * Tests conversion to files when the passed in objects are already files.
134      */
135     @Test
136     void testToFileDirect() {
137         final File f = new File("dir", "file");
138         assertSame(f, PropertyConverter.toFile(f));
139     }
140 
141     /**
142      * Tests conversion to file when the passed in objects are paths.
143      */
144     @Test
145     void testToFileFromPath() {
146         final Path p = Paths.get("dir", "file");
147         assertEquals(new File("dir", "file"), PropertyConverter.toFile(p));
148     }
149 
150     /**
151      * Tests conversion to file when the passed in objects have a compatible string representation.
152      */
153     @Test
154     void testToFileFromString() {
155         assertEquals(new File("dir", "file"), PropertyConverter.toFile("dir/file"));
156     }
157 
158     /**
159      * Tests a trivial conversion: the value has already the desired type.
160      */
161     @Test
162     void testToNoConversionNeeded() {
163         final String value = "testValue";
164         assertEquals(value, PropertyConverter.to(String.class, value, new DefaultConversionHandler()));
165     }
166 
167     /**
168      * Tests conversion to numbers when the passed in objects are already numbers.
169      */
170     @Test
171     void testToNumberDirect() {
172         final Integer i = Integer.valueOf(42);
173         assertSame(i, PropertyConverter.toNumber(i, Integer.class));
174         final BigDecimal d = new BigDecimal("3.1415");
175         assertSame(d, PropertyConverter.toNumber(d, Integer.class));
176     }
177 
178     /**
179      * Tests conversion to numbers when the passed in objects are strings with prefixes for special radices.
180      */
181     @Test
182     void testToNumberFromBinaryString() {
183         final Number n = PropertyConverter.toNumber("0b1111", Integer.class);
184         assertEquals(15, n.intValue());
185     }
186 
187     /**
188      * Tests conversion to numbers when the passed in objects are strings with prefixes for special radices.
189      */
190     @Test
191     void testToNumberFromHexString() {
192         final Number n = PropertyConverter.toNumber("0x10", Integer.class);
193         assertEquals(16, n.intValue());
194     }
195 
196     /**
197      * Tests conversion to numbers when an invalid binary value is passed in. This should cause an exception.
198      */
199     @Test
200     void testToNumberFromInvalidBinaryString() {
201         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("0bNotABinValue", Integer.class));
202     }
203 
204     /**
205      * Tests conversion to numbers when an invalid Hex value is passed in. This should cause an exception.
206      */
207     @Test
208     void testToNumberFromInvalidHexString() {
209         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("0xNotAHexValue", Integer.class));
210     }
211 
212     /**
213      * Tests conversion to numbers when the passed in objects have no numeric String representation. This should cause an
214      * exception.
215      */
216     @Test
217     void testToNumberFromInvalidString() {
218         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("Not a number", Byte.class));
219     }
220 
221     /**
222      * Tests conversion to numbers when the passed in objects have a compatible string representation.
223      */
224     @Test
225     void testToNumberFromString() {
226         assertEquals(Integer.valueOf(42), PropertyConverter.toNumber("42", Integer.class));
227         assertEquals(Short.valueOf((short) 10), PropertyConverter.toNumber(new StringBuffer("10"), Short.class));
228     }
229 
230     /**
231      * Tests conversion to numbers when the passed in target class is invalid. This should cause an exception.
232      */
233     @Test
234     void testToNumberWithInvalidClass() {
235         assertThrows(ConversionException.class, () -> PropertyConverter.toNumber("42", Object.class));
236     }
237 
238     /**
239      * Tests conversion to paths when the passed in objects are already paths.
240      */
241     @Test
242     void testToPathDirect() {
243         final Path p = Paths.get("dir", "file");
244         assertSame(p, PropertyConverter.toPath(p));
245     }
246 
247     /**
248      * Tests conversion to path when the passed in objects are files.
249      */
250     @Test
251     void testToPathFromFile() {
252         final File f = new File("dir", "file");
253         assertEquals(Paths.get("dir", "file"), PropertyConverter.toPath(f));
254     }
255 
256     /**
257      * Tests conversion to file when the passed in objects have a compatible string representation.
258      */
259     @Test
260     void testToPathFromString() {
261         assertEquals(Paths.get("dir", "file"), PropertyConverter.toPath("dir/file"));
262     }
263 
264     /**
265      * Tests conversion to patterns when the passed in objects are already patterns.
266      */
267     @Test
268     void testToPatternDirect() {
269         final Pattern p = Pattern.compile(".+");
270         assertSame(p, PropertyConverter.toPattern(p));
271     }
272 
273     /**
274      * Tests conversion to patterns when the passed in objects have a compatible string representation.
275      */
276     @Test
277     void testToPatternFromString() {
278         final Pattern p = Pattern.compile(".+");
279         assertEquals(p.pattern(), PropertyConverter.toPattern(".+").pattern());
280     }
281 
282     /**
283      * Tests a conversion to a string.
284      */
285     @Test
286     void testToStringConversion() {
287         final Integer src = 42;
288         final Object result = PropertyConverter.to(String.class, src, new DefaultConversionHandler());
289         assertEquals("42", result);
290     }
291 }