9b38a85c677e6e44488752aa709c7243643a594e
[yangtools.git] / common / yang-common / src / test / java / org / opendaylight / yangtools / yang / common / Decimal64Test.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.common;
9
10
11 import static org.junit.jupiter.api.Assertions.assertEquals;
12 import static org.junit.jupiter.api.Assertions.assertFalse;
13 import static org.junit.jupiter.api.Assertions.assertThrows;
14 import static org.junit.jupiter.api.Assertions.assertTrue;
15
16 import java.math.BigDecimal;
17 import java.math.RoundingMode;
18 import org.junit.jupiter.api.Test;
19
20 public class Decimal64Test {
21     @Test
22     public void testParseEmpty() {
23         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf(""));
24     }
25
26     @Test
27     public void testParseSingleIllegal() {
28         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("a"));
29     }
30
31     @Test
32     public void testParseSingleHighIllegal() {
33         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf(":"));
34     }
35
36     @Test
37     public void testParseZeroIllegal() {
38         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0a"));
39     }
40
41     @Test
42     public void testParseZeroHighIllegal() {
43         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0:"));
44     }
45
46     @Test
47     public void testParseZeroPointIllegal() {
48         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0.a"));
49     }
50
51     @Test
52     public void testParseZeroPointHighIllegal() {
53         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0.:"));
54     }
55
56     @Test
57     public void testParsePointIllegal() {
58         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf(".a"));
59     }
60
61     @Test
62     public void testParseMinus() {
63         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("-"));
64     }
65
66     @Test
67     public void testParsePlus() {
68         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("+"));
69     }
70
71     @Test
72     public void testParsePeriod() {
73         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("."));
74     }
75
76     @Test
77     public void testParseTwoPeriods() {
78         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf(".."));
79     }
80
81     @Test
82     public void testParseTrailingPeriod() {
83         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0."));
84     }
85
86     @Test
87     public void testParseMultiplePeriods() {
88         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0.1."));
89     }
90
91     @Test
92     public void testParseLongString() {
93         Decimal64.valueOf("123456789012345678");
94     }
95
96     @Test
97     public void testParseLongDecimal() {
98         Decimal64.valueOf("0.12345678901234568");
99     }
100
101     @Test
102     public void testFractionLimits() {
103         Decimal64.valueOf("922337203685477580.7");
104         Decimal64.valueOf("9.223372036854775807");
105
106         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("922337203685477580.71"));
107         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("9.2233720368547758071"));
108     }
109
110     @Test
111     public void testParseTooLongString() {
112         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("1234567890123456789"));
113     }
114
115     @Test
116     public void testParseTooLongDecimal() {
117         assertThrows(NumberFormatException.class, () -> Decimal64.valueOf("0.1234567890123456789"));
118     }
119
120     @Test
121     public void testParse() {
122         assertParsedVariants("0", 0, 0, 1);
123         assertParsedVariants("0.00", 0, 0, 1);
124         assertParsedVariants("00.0", 0, 0, 1);
125         assertParsedVariants("000.0", 0, 0, 1);
126         assertCanonicalVariants("10.0", 10, 0, 1);
127         assertCanonicalVariants("10.09", 10, 9, 2);
128         assertParsedVariants("10.0900900", 10, 9009, 5);
129         assertParsedVariants("0002210.09", 2210, 9, 2);
130
131         Decimal64 parsed = assertParsedString("0.0", 0, 0, 1, false);
132         parsed = assertParsedString("+0.0", 0, 0, 1, false);
133         assertEquals("0.0", parsed.toString());
134         assertEquals("0.0", parsed.toString());
135         parsed = assertParsedString("-0.0", 0, 0, 1, true);
136         assertEquals("0.0", parsed.toString());
137
138         assertCanonicalVariants("1.0", 1, 0, 1);
139         assertCanonicalVariants("2.3", 2, 3, 1);
140     }
141
142     @Test
143     public void testCompare() {
144         final Decimal64 one = Decimal64.valueOf("1");
145         final Decimal64 two = Decimal64.valueOf("2");
146         final Decimal64 three = Decimal64.valueOf("3");
147         final Decimal64 negOne = Decimal64.valueOf("-1");
148         final Decimal64 anotherOne = Decimal64.valueOf("1");
149
150         assertEquals(0, one.compareTo(one));
151         assertEquals(0, one.compareTo(anotherOne));
152         assertEquals(-1, one.compareTo(two));
153         assertEquals(-1, one.compareTo(three));
154         assertEquals(1, one.compareTo(negOne));
155
156         assertEquals(1, two.compareTo(one));
157         assertEquals(1, two.compareTo(anotherOne));
158         assertEquals(-1, two.compareTo(three));
159         assertEquals(1, one.compareTo(negOne));
160     }
161
162     @Test
163     public void testEquals() {
164         final Decimal64 one = Decimal64.valueOf("1");
165         final Decimal64 two = Decimal64.valueOf("2");
166         final Decimal64 anotherOne = Decimal64.valueOf("1");
167
168         assertTrue(one.equals(one));
169         assertTrue(one.equals(anotherOne));
170         assertFalse(one.equals(two));
171         assertTrue(two.equals(two));
172         assertFalse(two.equals(one));
173
174         assertFalse(one.equals(new Object()));
175     }
176
177     @Test
178     public void testConversions() {
179         assertEquals(new BigDecimal("0.12"), Decimal64.valueOf("0.12").decimalValue());
180         assertEquals(new BigDecimal("-0.12"), Decimal64.valueOf("-0.12").decimalValue());
181         assertEquals(new BigDecimal("0.12"), Decimal64.valueOf("+0.12").decimalValue());
182         assertEquals(new BigDecimal("123.456"), Decimal64.valueOf("123.456").decimalValue());
183         assertEquals(new BigDecimal("-123.456"), Decimal64.valueOf("-123.456").decimalValue());
184
185         assertEquals(0.12, Decimal64.valueOf("0.12").doubleValue(), 0);
186         assertEquals(-0.12, Decimal64.valueOf("-0.12").doubleValue(), 0);
187
188         assertEquals((float) 0.12, Decimal64.valueOf("0.12").floatValue(), 0);
189         assertEquals((float) -0.12, Decimal64.valueOf("-0.12").floatValue(), 0);
190
191         assertEquals(12345678901L, Decimal64.valueOf("12345678901").longValue());
192         assertEquals(-12345678901L, Decimal64.valueOf("-12345678901").longValue());
193     }
194
195     @Test
196     public void testFactories() {
197         assertEquals("0.0", Decimal64.valueOf(1, (byte) 0).toString());
198         assertEquals("1.0", Decimal64.valueOf(1, (byte) 1).toString());
199         assertEquals("-1.0", Decimal64.valueOf(1, (byte) -1).toString());
200
201         assertEquals("0.0", Decimal64.valueOf(1, (short) 0).toString());
202         assertEquals("1.0", Decimal64.valueOf(1, (short) 1).toString());
203         assertEquals("-1.0", Decimal64.valueOf(1, (short) -1).toString());
204
205         assertEquals("0.0", Decimal64.valueOf(1, 0).toString());
206         assertEquals("1.0", Decimal64.valueOf(1, 1).toString());
207         assertEquals("-1.0", Decimal64.valueOf(1, -1).toString());
208
209         assertEquals("0.0", Decimal64.valueOf(1, 0L).toString());
210         assertEquals("1.0", Decimal64.valueOf(1, 1L).toString());
211         assertEquals("-1.0", Decimal64.valueOf(1, -1L).toString());
212
213         assertEquals("0.0", Decimal64.valueOf(0.0F, RoundingMode.UNNECESSARY).toString());
214         assertEquals("1.0", Decimal64.valueOf(1.0F, RoundingMode.UNNECESSARY).toString());
215         assertEquals("-1.0", Decimal64.valueOf(-1.0F, RoundingMode.UNNECESSARY).toString());
216
217         assertEquals("0.0", Decimal64.valueOf(0.0D, RoundingMode.UNNECESSARY).toString());
218         assertEquals("1.0", Decimal64.valueOf(1.0D, RoundingMode.UNNECESSARY).toString());
219         assertEquals("-1.0", Decimal64.valueOf(-1.0D, RoundingMode.UNNECESSARY).toString());
220
221         assertEquals("0.0", Decimal64.valueOf(BigDecimal.ZERO).toString());
222         assertEquals("1.0", Decimal64.valueOf(BigDecimal.ONE).toString());
223         assertEquals("-1.0", Decimal64.valueOf(BigDecimal.ONE.negate()).toString());
224     }
225
226     @Test
227     public void testLeadingZeroToString() {
228         assertEquals("-0.63", Decimal64.valueOf("-0.63").toString());
229     }
230
231     @Test
232     public void testFractionPartToString() {
233         assertEquals("0.3", Decimal64.valueOf("0.3").toString());
234         assertEquals("0.03", Decimal64.valueOf("0.03").toString());
235         assertEquals("0.003", Decimal64.valueOf("0.003").toString());
236         assertEquals("-0.3", Decimal64.valueOf("-0.3").toString());
237         assertEquals("-0.03", Decimal64.valueOf("-0.03").toString());
238         assertEquals("-0.003", Decimal64.valueOf("-0.003").toString());
239     }
240
241     @Test
242     public void testScalingToString() {
243         assertEquals("30.0", Decimal64.of(1, 300).toString());
244         assertEquals("3.0", Decimal64.of(2, 300).toString());
245         assertEquals("0.3", Decimal64.of(3, 300).toString());
246         assertEquals("0.03", Decimal64.of(4, 300).toString());
247     }
248
249     @Test
250     public void testBoundaries() {
251         assertEquals(-128L, Decimal64.valueOf(1, Byte.MIN_VALUE).longValue());
252         assertEquals(127L, Decimal64.valueOf(1, Byte.MAX_VALUE).longValue());
253         assertEquals(-32768L, Decimal64.valueOf(2, Short.MIN_VALUE).longValue());
254         assertEquals(32767L, Decimal64.valueOf(2, Short.MAX_VALUE).longValue());
255         assertEquals(-2147483648L, Decimal64.valueOf(3, Integer.MIN_VALUE).longValue());
256         assertEquals(2147483647L, Decimal64.valueOf(3, Integer.MAX_VALUE).longValue());
257     }
258
259     @Test
260     public void testByteValueExact() {
261         assertEquals(Byte.MIN_VALUE, Decimal64.valueOf(1, Byte.MIN_VALUE).byteValueExact());
262         assertEquals(Byte.MAX_VALUE, Decimal64.valueOf(1, Byte.MAX_VALUE).byteValueExact());
263     }
264
265     @Test
266     public void testByteValueExactFrac() {
267         final Decimal64 dec = Decimal64.valueOf("1.1");
268         assertThrows(ArithmeticException.class, () -> dec.byteValueExact());
269     }
270
271     @Test
272     public void testByteValueExactRange() {
273         final Decimal64 dec = Decimal64.valueOf(1, Byte.MAX_VALUE + 1);
274         assertThrows(ArithmeticException.class, () -> dec.byteValueExact());
275     }
276
277     @Test
278     public void testShortValueExact() {
279         assertEquals(Short.MIN_VALUE, Decimal64.valueOf(1, Short.MIN_VALUE).shortValueExact());
280         assertEquals(Short.MAX_VALUE, Decimal64.valueOf(1, Short.MAX_VALUE).shortValueExact());
281     }
282
283     @Test
284     public void testShortValueExactFrac() {
285         final Decimal64 dec = Decimal64.valueOf("1.1");
286         assertThrows(ArithmeticException.class, () -> dec.shortValueExact());
287     }
288
289     @Test
290     public void testShortValueExactRange() {
291         final Decimal64 dec = Decimal64.valueOf(1, Short.MAX_VALUE + 1);
292         assertThrows(ArithmeticException.class, () -> dec.shortValueExact());
293     }
294
295     @Test
296     public void testIntValueExact() {
297         assertEquals(Integer.MIN_VALUE, Decimal64.valueOf(1, Integer.MIN_VALUE).intValueExact());
298         assertEquals(Integer.MAX_VALUE, Decimal64.valueOf(1, Integer.MAX_VALUE).intValueExact());
299     }
300
301     @Test
302     public void testIntValueExactFrac() {
303         final Decimal64 dec = Decimal64.valueOf("1.1");
304         assertThrows(ArithmeticException.class, () -> dec.intValueExact());
305     }
306
307     @Test
308     public void testIntValueExactRange() {
309         final Decimal64 dec = Decimal64.valueOf(1, Integer.MAX_VALUE + 1L);
310         assertThrows(ArithmeticException.class, () -> dec.intValueExact());
311     }
312
313     @Test
314     public void testLongValueExactFrac() {
315         final Decimal64 dec = Decimal64.valueOf("1.1");
316         assertThrows(ArithmeticException.class, () -> dec.longValueExact());
317     }
318
319     @Test
320     public void testLongValueOfBits() {
321         final Decimal64 dec = Decimal64.valueOf(2, 25552555555L);
322         assertEquals(2, dec.scale());
323         assertEquals(2555255555500L, dec.unscaledValue());
324     }
325
326     @Test
327     public void testLongValueOfNegativeBits() {
328         final Decimal64 dec = Decimal64.valueOf(2, -25552555555L);
329         assertEquals(2, dec.scale());
330         assertEquals(-2555255555500L, dec.unscaledValue());
331     }
332
333     @Test
334     public void testByteRange() {
335         for (int i = 1; i <= 16; ++i) {
336             assertEquals(Byte.MIN_VALUE, Decimal64.valueOf(i, Byte.MIN_VALUE).byteValueExact());
337             assertEquals(Byte.MAX_VALUE, Decimal64.valueOf(i, Byte.MAX_VALUE).byteValueExact());
338         }
339         for (int i = 17; i <= 18; ++i) {
340             int scale = i;
341             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Byte.MIN_VALUE));
342             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Byte.MAX_VALUE));
343         }
344     }
345
346     @Test
347     public void testShortRange() {
348         for (int i = 1; i <= 14; ++i) {
349             assertEquals(Short.MIN_VALUE, Decimal64.valueOf(i, Short.MIN_VALUE).shortValueExact());
350             assertEquals(Short.MAX_VALUE, Decimal64.valueOf(i, Short.MAX_VALUE).shortValueExact());
351         }
352         for (int i = 15; i <= 18; ++i) {
353             int scale = i;
354             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Short.MIN_VALUE));
355             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Short.MAX_VALUE));
356         }
357     }
358
359     @Test
360     public void testIntRange() {
361         for (int i = 1; i <= 9; ++i) {
362             assertEquals(Integer.MIN_VALUE, Decimal64.valueOf(i, Integer.MIN_VALUE).intValueExact());
363             assertEquals(Integer.MAX_VALUE, Decimal64.valueOf(i, Integer.MAX_VALUE).intValueExact());
364         }
365         for (int i = 10; i <= 18; ++i) {
366             int scale = i;
367             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Integer.MIN_VALUE));
368             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Integer.MAX_VALUE));
369         }
370     }
371
372     @Test
373     public void testLongRange() {
374         for (int i = 1; i <= 18; ++i) {
375             int scale = i;
376             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Long.MIN_VALUE));
377             assertThrows(IllegalArgumentException.class, () -> Decimal64.valueOf(scale, Long.MAX_VALUE));
378         }
379     }
380
381     private static void assertCanonicalVariants(final String str, final long intPart, final long fracPart,
382             final int digits) {
383         assertCanonicalString(str, intPart, fracPart, digits, false);
384         assertCanonicalString("-" + str, intPart, fracPart, digits, true);
385
386         final Decimal64 parsed = assertParsedString("+" + str, intPart, fracPart, digits, false);
387         assertEquals(str, parsed.toString());
388     }
389
390     private static void assertParsedVariants(final String str, final long intPart, final long fracPart,
391             final int digits) {
392         assertParsedString(str, intPart, fracPart, digits, false);
393         assertParsedString("-" + str, intPart, fracPart, digits, true);
394         assertParsedString("+" + str, intPart, fracPart, digits, false);
395     }
396
397     private static void assertCanonicalString(final String str, final long intPart, final long fracPart,
398             final int digits, final boolean negative) {
399         final Decimal64 parsed = assertParsedString(str, intPart, fracPart, digits, negative);
400         assertEquals(str, parsed.toString());
401     }
402
403     private static Decimal64 assertParsedString(final String str, final long intPart, final long fracPart,
404             final int digits, final boolean negative) {
405         final Decimal64 parsed = Decimal64.valueOf(str);
406         assertEquals(new Decimal64((byte) digits, intPart, fracPart, negative), parsed);
407         return parsed;
408     }
409 }