/* * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.common; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.math.RoundingMode; import org.junit.jupiter.api.Test; public class YT1440Test { @Test public void testScaleSame() { final var twenty = Decimal64.valueOf(2, 20); assertSame(twenty, twenty.scaleTo(2)); // Do not tolerate null rounding even for no-op assertThrows(NullPointerException.class, () -> twenty.scaleTo(2, null)); } @Test public void testScaleZero() { final var two = Decimal64.valueOf(2, 0); final var one = two.scaleTo(1); assertEquals(1, one.scale()); assertEquals(0, one.unscaledValue()); final var three = two.scaleTo(3); assertEquals(3, three.scale()); assertEquals(0, three.unscaledValue()); } @Test public void testScaleUpNoRemain() { // Template, scale=5 final var two = Decimal64.valueOf(2, 20); // scale = 5 final var five = two.scaleTo(5); assertEquals(5, five.scale()); assertEquals(two, five); assertEquals("20.0", five.toString()); // scale = 18 fails final var ex = assertThrows(ArithmeticException.class, () -> two.scaleTo(18)); assertEquals("Increasing scale of 20.0 to 18 would overflow", ex.getMessage()); } @Test public void testScaleDownNoRemain() { // Template, scale=5 final var five = Decimal64.valueOf(5, 20); // scale = 2 final var two = five.scaleTo(2); assertEquals(2, two.scale()); assertEquals(five, two); assertEquals("20.0", two.toString()); } @Test public void testScaleDownPositive() { final var two = Decimal64.valueOf("0.63"); assertEquals(2, two.scale()); assertEquals(63, two.unscaledValue()); // Trim '3' assertScaleDown(7, two, 1, RoundingMode.UP); assertScaleDown(6, two, 1, RoundingMode.DOWN); assertScaleDown(7, two, 1, RoundingMode.CEILING); assertScaleDown(6, two, 1, RoundingMode.FLOOR); assertScaleDown(6, two, 1, RoundingMode.HALF_UP); assertScaleDown(6, two, 1, RoundingMode.HALF_DOWN); assertScaleDown(6, two, 1, RoundingMode.HALF_EVEN); final var three = Decimal64.valueOf("0.635"); assertEquals(3, three.scale()); assertEquals(635, three.unscaledValue()); // Trim '5' assertScaleDown(64, three, 2, RoundingMode.UP); assertScaleDown(63, three, 2, RoundingMode.DOWN); assertScaleDown(64, three, 2, RoundingMode.CEILING); assertScaleDown(63, three, 2, RoundingMode.FLOOR); assertScaleDown(64, three, 2, RoundingMode.HALF_UP); assertScaleDown(63, three, 2, RoundingMode.HALF_DOWN); assertScaleDown(64, three, 2, RoundingMode.HALF_EVEN); // Trim '35' assertScaleDown(7, three, 1, RoundingMode.UP); assertScaleDown(6, three, 1, RoundingMode.DOWN); assertScaleDown(7, three, 1, RoundingMode.CEILING); assertScaleDown(6, three, 1, RoundingMode.FLOOR); assertScaleDown(6, three, 1, RoundingMode.HALF_UP); assertScaleDown(6, three, 1, RoundingMode.HALF_DOWN); assertScaleDown(6, three, 1, RoundingMode.HALF_EVEN); final var four = Decimal64.valueOf("0.6355"); assertEquals(4, four.scale()); assertEquals(6355, four.unscaledValue()); // Trim 55 assertScaleDown(64, four, 2, RoundingMode.UP); assertScaleDown(63, four, 2, RoundingMode.DOWN); assertScaleDown(64, four, 2, RoundingMode.CEILING); assertScaleDown(63, four, 2, RoundingMode.FLOOR); assertScaleDown(64, four, 2, RoundingMode.HALF_UP); assertScaleDown(64, four, 2, RoundingMode.HALF_DOWN); assertScaleDown(64, four, 2, RoundingMode.HALF_EVEN); final var five = Decimal64.valueOf("0.635").scaleTo(5); assertEquals(5, five.scale()); assertEquals(63500, five.unscaledValue()); // Trim 500 assertScaleDown(64, five, 2, RoundingMode.UP); assertScaleDown(63, five, 2, RoundingMode.DOWN); assertScaleDown(64, five, 2, RoundingMode.CEILING); assertScaleDown(63, five, 2, RoundingMode.FLOOR); assertScaleDown(64, five, 2, RoundingMode.HALF_UP); assertScaleDown(63, five, 2, RoundingMode.HALF_DOWN); assertScaleDown(64, five, 2, RoundingMode.HALF_EVEN); } @Test public void testScaleDownNegative() { final var two = Decimal64.valueOf("-0.63"); assertEquals(2, two.scale()); assertEquals(-63, two.unscaledValue()); // Trim '3' assertScaleDown(-7, two, 1, RoundingMode.UP); assertScaleDown(-6, two, 1, RoundingMode.DOWN); assertScaleDown(-6, two, 1, RoundingMode.CEILING); assertScaleDown(-7, two, 1, RoundingMode.FLOOR); assertScaleDown(-6, two, 1, RoundingMode.HALF_UP); assertScaleDown(-6, two, 1, RoundingMode.HALF_DOWN); assertScaleDown(-6, two, 1, RoundingMode.HALF_EVEN); final var three = Decimal64.valueOf("-0.635"); assertEquals(3, three.scale()); assertEquals(-635, three.unscaledValue()); // Trim '5' assertScaleDown(-64, three, 2, RoundingMode.UP); assertScaleDown(-63, three, 2, RoundingMode.DOWN); assertScaleDown(-63, three, 2, RoundingMode.CEILING); assertScaleDown(-64, three, 2, RoundingMode.FLOOR); assertScaleDown(-64, three, 2, RoundingMode.HALF_UP); assertScaleDown(-63, three, 2, RoundingMode.HALF_DOWN); assertScaleDown(-64, three, 2, RoundingMode.HALF_EVEN); // Trim '35' assertScaleDown(-7, three, 1, RoundingMode.UP); assertScaleDown(-6, three, 1, RoundingMode.DOWN); assertScaleDown(-6, three, 1, RoundingMode.CEILING); assertScaleDown(-7, three, 1, RoundingMode.FLOOR); assertScaleDown(-6, three, 1, RoundingMode.HALF_UP); assertScaleDown(-6, three, 1, RoundingMode.HALF_DOWN); assertScaleDown(-6, three, 1, RoundingMode.HALF_EVEN); final var four = Decimal64.valueOf("-0.6355"); assertEquals(4, four.scale()); assertEquals(-6355, four.unscaledValue()); // Trim 55 assertScaleDown(-64, four, 2, RoundingMode.UP); assertScaleDown(-63, four, 2, RoundingMode.DOWN); assertScaleDown(-63, four, 2, RoundingMode.CEILING); assertScaleDown(-64, four, 2, RoundingMode.FLOOR); assertScaleDown(-64, four, 2, RoundingMode.HALF_UP); assertScaleDown(-64, four, 2, RoundingMode.HALF_DOWN); assertScaleDown(-64, four, 2, RoundingMode.HALF_EVEN); final var five = Decimal64.valueOf("-0.635").scaleTo(5); assertEquals(5, five.scale()); assertEquals(-63500, five.unscaledValue()); // Trim 500 assertScaleDown(-64, five, 2, RoundingMode.UP); assertScaleDown(-63, five, 2, RoundingMode.DOWN); assertScaleDown(-63, five, 2, RoundingMode.CEILING); assertScaleDown(-64, five, 2, RoundingMode.FLOOR); assertScaleDown(-64, five, 2, RoundingMode.HALF_UP); assertScaleDown(-63, five, 2, RoundingMode.HALF_DOWN); assertScaleDown(-64, five, 2, RoundingMode.HALF_EVEN); } @Test public void testScaleDownTrim() { final var two = Decimal64.valueOf("0.63"); final var ex = assertThrows(ArithmeticException.class, () -> two.scaleTo(1)); assertEquals("Decreasing scale of 0.63 to 1 requires rounding", ex.getMessage()); } private static void assertScaleDown(final long expectedUnscaled, final Decimal64 value, final int scale, final RoundingMode mode) { final var scaled = value.scaleTo(scale, mode); assertEquals(scale, scaled.scale()); assertEquals(expectedUnscaled, scaled.unscaledValue()); } }