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