diff options
Diffstat (limited to 'src/test/java/UnitsDatabaseTest.java')
-rw-r--r-- | src/test/java/UnitsDatabaseTest.java | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/src/test/java/UnitsDatabaseTest.java b/src/test/java/UnitsDatabaseTest.java new file mode 100644 index 0000000..9222740 --- /dev/null +++ b/src/test/java/UnitsDatabaseTest.java @@ -0,0 +1,260 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package test.java; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.junit.Test; +import org.unitConverter.UnitsDatabase; +import org.unitConverter.unit.AbstractUnit; +import org.unitConverter.unit.DefaultUnitPrefix; +import org.unitConverter.unit.LinearUnit; +import org.unitConverter.unit.SI; +import org.unitConverter.unit.Unit; +import org.unitConverter.unit.UnitPrefix; + +/** + * A test for the {@link UnitsDatabase} class. This is NOT part of this program's public API. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ +public class UnitsDatabaseTest { + // some linear units and one nonlinear + private static final Unit U = SI.METRE; + private static final Unit V = SI.KILOGRAM; + private static final Unit W = SI.SECOND; + + // used for testing expressions + // J = U^2 * V / W^2 + private static final LinearUnit J = SI.KILOGRAM.times(SI.METRE.toExponent(2)).dividedBy(SI.SECOND.toExponent(2)); + private static final Unit NONLINEAR = new AbstractUnit(SI.METRE) { + + @Override + public double convertFromBase(final double value) { + return value + 1; + } + + @Override + public double convertToBase(final double value) { + return value - 1; + } + }; + + // make the prefix values prime so I can tell which multiplications were made + private static final UnitPrefix A = new DefaultUnitPrefix(2); + private static final UnitPrefix B = new DefaultUnitPrefix(3); + private static final UnitPrefix C = new DefaultUnitPrefix(5); + private static final UnitPrefix AB = new DefaultUnitPrefix(7); + private static final UnitPrefix BC = new DefaultUnitPrefix(11); + + /** + * Test that prefixes correctly apply to units. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixes() { + final UnitsDatabase database = new UnitsDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + // get the product + final Unit abcuNonlinear = database.getUnit("ABCU"); + assert abcuNonlinear instanceof LinearUnit; + + final LinearUnit abcu = (LinearUnit) abcuNonlinear; + assertEquals(A.getMultiplier() * B.getMultiplier() * C.getMultiplier(), abcu.getConversionFactor(), 1e-15); + } + + /** + * Tests the functionnalites of the prefixless unit map. + * + * <p> + * The map should be an auto-updating view of the units in the database. + * </p> + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixlessUnitMap() { + final UnitsDatabase database = new UnitsDatabase(); + final Map<String, Unit> prefixlessUnits = database.unitMapPrefixless(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + // this should work because the map should be an auto-updating view + assertTrue(prefixlessUnits.containsKey("U")); + assertFalse(prefixlessUnits.containsKey("Z")); + + assertTrue(prefixlessUnits.containsValue(U)); + assertFalse(prefixlessUnits.containsValue(NONLINEAR)); + } + + /** + * Tests that the database correctly stores and retrieves units, ignoring prefixes. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixlessUnits() { + final UnitsDatabase database = new UnitsDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + assertTrue(database.containsUnitName("U")); + assertFalse(database.containsUnitName("Z")); + + assertEquals(U, database.getUnit("U")); + assertEquals(null, database.getUnit("Z")); + } + + /** + * Test that unit expressions return the correct value. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitExpressions() { + // load units + final UnitsDatabase database = new UnitsDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + database.addUnit("fj", J.times(5)); + database.addUnit("ej", J.times(8)); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + // first test - test prefixes and operations + final Unit expected1 = J.withPrefix(A).withPrefix(B).withPrefix(C).withPrefix(C); + final Unit actual1 = database.getUnitFromExpression("ABV * CU^2 / W / W"); + + assertEquals(expected1, actual1); + + // second test - test addition and subtraction + final Unit expected2 = J.times(58); + final Unit actual2 = database.getUnitFromExpression("2 fj + 6 ej"); + + assertEquals(expected2, actual2); + } + + /** + * Tests both the unit name iterator and the name-unit entry iterator + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitIterator() { + // load units + final UnitsDatabase database = new UnitsDatabase(); + + database.addUnit("J", J); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + final Iterator<String> nameIterator = database.unitMap().keySet().iterator(); + final Iterator<Entry<String, Unit>> entryIterator = database.unitMap().entrySet().iterator(); + + int expectedLength = 1; + int unitsWithThisLengthSoFar = 0; + + // loop 1000 times + for (int i = 0; i < 1000; i++) { + // expected length of next + if (unitsWithThisLengthSoFar >= (int) Math.pow(3, expectedLength - 1)) { + expectedLength++; + unitsWithThisLengthSoFar = 0; + } + + final String nextName = nameIterator.next(); + final Unit nextUnit = database.getUnit(nextName); + final Entry<String, Unit> nextEntry = entryIterator.next(); + + assertEquals(expectedLength, nextName.length()); + assertEquals(nextName, nextEntry.getKey()); + assertEquals(nextUnit, nextEntry.getValue()); + + unitsWithThisLengthSoFar++; + } + } + + /** + * Determine, given a unit name that could mean multiple things, which meaning is chosen. + * <p> + * For example, "ABCU" could mean "A-B-C-U", "AB-C-U", or "A-BC-U". In this case, "AB-C-U" is the correct choice. + * </p> + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitPrefixCombinations() { + // load units + final UnitsDatabase database = new UnitsDatabase(); + + database.addUnit("J", J); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + database.addPrefix("AB", AB); + database.addPrefix("BC", BC); + + // test 1 - AB-C-J vs A-BC-J vs A-B-C-J + final Unit expected1 = J.withPrefix(AB).withPrefix(C); + final Unit actual1 = database.getUnit("ABCJ"); + + assertEquals(expected1, actual1); + + // test 2 - ABC-J vs AB-CJ vs AB-C-J + database.addUnit("CJ", J.times(13)); + database.addPrefix("ABC", new DefaultUnitPrefix(17)); + + final Unit expected2 = J.times(17); + final Unit actual2 = database.getUnit("ABCJ"); + + assertEquals(expected2, actual2); + } +} |