diff options
author | Adrien Hopkins <ahopk127@my.yorku.ca> | 2021-08-26 15:18:30 -0400 |
---|---|---|
committer | Adrien Hopkins <ahopk127@my.yorku.ca> | 2021-08-26 15:18:30 -0400 |
commit | c4ae6887c32ee8d2e9e8853ffd12721d4db2fd3b (patch) | |
tree | b51679f692e90292901669d2c1bccad347c25434 /src/test/java/sevenUnits | |
parent | 360b4261ebb9b65dcf91a6e49c5d23784e592945 (diff) | |
parent | 54e481cdb7115b236bcddb86b785d88dcc757c39 (diff) |
Merge branch 'develop'
Diffstat (limited to 'src/test/java/sevenUnits')
-rw-r--r-- | src/test/java/sevenUnits/unit/MultiUnitTest.java | 110 | ||||
-rw-r--r-- | src/test/java/sevenUnits/unit/UnitDatabaseTest.java | 317 | ||||
-rw-r--r-- | src/test/java/sevenUnits/unit/UnitTest.java | 153 | ||||
-rw-r--r-- | src/test/java/sevenUnits/utils/ConditionalExistenceCollectionsTest.java | 161 | ||||
-rw-r--r-- | src/test/java/sevenUnits/utils/ExpressionParserTest.java | 54 | ||||
-rw-r--r-- | src/test/java/sevenUnits/utils/ObjectProductTest.java | 80 |
6 files changed, 875 insertions, 0 deletions
diff --git a/src/test/java/sevenUnits/unit/MultiUnitTest.java b/src/test/java/sevenUnits/unit/MultiUnitTest.java new file mode 100644 index 0000000..d632118 --- /dev/null +++ b/src/test/java/sevenUnits/unit/MultiUnitTest.java @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2020 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 sevenUnits.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.jupiter.api.Test; + +import sevenUnits.unit.BritishImperial; +import sevenUnits.unit.MultiUnit; +import sevenUnits.unit.Metric; + +/** + * Tests related to the {@code MultiUnit}. + * + * @since 2020-10-03 + */ +class MultiUnitTest { + + @Test + final void testConvert() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + assertEquals(1702.0, footInch.convertTo(Metric.METRE.withPrefix(Metric.MILLI), + Arrays.asList(5.0, 7.0)), 1.0); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double millimetres = feet * 304.8 + inches * 25.4; + + final List<Double> feetAndInches = Metric.METRE.withPrefix(Metric.MILLI) + .convertTo(footInch, millimetres); + assertEquals(feet, feetAndInches.get(0), 1e-10); + assertEquals(inches, feetAndInches.get(1), 1e-10); + } + } + + /** + * Test method for + * {@link sevenUnits.unit.MultiUnit#convertFromBase(double)}. + */ + @Test + final void testConvertFromBase() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + // 1.7 m =~ 5' + 7" + final List<Double> values = footInch.convertFromBase(1.7018); + + assertEquals(5, values.get(0)); + assertEquals(7, values.get(1), 1e-12); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double metres = feet * 0.3048 + inches * 0.0254; + + final List<Double> feetAndInches = footInch.convertFromBase(metres); + assertEquals(feet, feetAndInches.get(0), 1e-10); + assertEquals(inches, feetAndInches.get(1), 1e-10); + } + } + + /** + * Test method for + * {@link sevenUnits.unit.MultiUnit#convertToBase(java.util.List)}. + */ + @Test + final void testConvertToBase() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + // 1.7 m =~ 5' + 7" + assertEquals(1.7018, footInch.convertToBase(Arrays.asList(5.0, 7.0)), + 1e-12); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double metres = feet * 0.3048 + inches * 0.0254; + + assertEquals(metres, + footInch.convertToBase(Arrays.asList(feet, inches)), 1e-12); + } + } +} diff --git a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java new file mode 100644 index 0000000..1d5e503 --- /dev/null +++ b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java @@ -0,0 +1,317 @@ +/** + * 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 sevenUnits.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import sevenUnits.unit.LinearUnit; +import sevenUnits.unit.NameSymbol; +import sevenUnits.unit.Metric; +import sevenUnits.unit.Unit; +import sevenUnits.unit.UnitDatabase; +import sevenUnits.unit.UnitPrefix; + +/** + * A test for the {@link UnitDatabase} class. This is NOT part of this program's + * public API. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ +class UnitDatabaseTest { + // some linear units and one nonlinear + private static final Unit U = Metric.METRE; + private static final Unit V = Metric.KILOGRAM; + private static final Unit W = Metric.SECOND; + + // used for testing expressions + // J = U^2 * V / W^2 + private static final LinearUnit J = Metric.KILOGRAM.times(Metric.METRE.toExponent(2)) + .dividedBy(Metric.SECOND.toExponent(2)); + private static final LinearUnit K = Metric.KELVIN; + + private static final Unit NONLINEAR = Unit + .fromConversionFunctions(Metric.METRE.getBase(), o -> o + 1, o -> o - 1); + + // make the prefix values prime so I can tell which multiplications were made + private static final UnitPrefix A = UnitPrefix.valueOf(2) + .withName(NameSymbol.ofName("A")); + private static final UnitPrefix B = UnitPrefix.valueOf(3) + .withName(NameSymbol.ofName("B")); + private static final UnitPrefix C = UnitPrefix.valueOf(5) + .withName(NameSymbol.ofName("C")); + private static final UnitPrefix AB = UnitPrefix.valueOf(7); + private static final UnitPrefix BC = UnitPrefix.valueOf(11); + + /** + * Confirms that operations that shouldn't function for infinite databases + * throw an {@code IllegalStateException}. + * + * @since 2019-05-03 + */ +// @Test +// @Timeout(value = 1, unit = TimeUnit.SECONDS) + public void testInfiniteSetExceptions() { + // load units + final UnitDatabase infiniteDatabase = new UnitDatabase(); + + infiniteDatabase.addUnit("J", J); + infiniteDatabase.addUnit("K", K); + + infiniteDatabase.addPrefix("A", A); + infiniteDatabase.addPrefix("B", B); + infiniteDatabase.addPrefix("C", C); + + final Set<Entry<String, Unit>> entrySet = infiniteDatabase.unitMap() + .entrySet(); + final Set<String> keySet = infiniteDatabase.unitMap().keySet(); + assertThrows(IllegalStateException.class, () -> entrySet.toArray()); + assertThrows(IllegalStateException.class, () -> keySet.toArray()); + } + + /** + * Test that prefixes correctly apply to units. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixes() { + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + // test the getPrefixesFromName method + final List<UnitPrefix> expected = Arrays.asList(C, B, A); + assertEquals(expected, database.getPrefixesFromName("ABCU")); + + // 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 UnitDatabase database = new UnitDatabase(); + final Map<String, Unit> prefixlessUnits = database + .unitMapPrefixless(true); + + 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 UnitDatabase database = new UnitDatabase(); + + 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")); + assertThrows(NoSuchElementException.class, () -> 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 UnitDatabase database = new UnitDatabase(); + + 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 UnitDatabase database = new UnitDatabase(); + + database.addUnit("J", J); + database.addUnit("K", K); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + final int NUM_UNITS = database.unitMapPrefixless(true).size(); + final int NUM_PREFIXES = database.prefixMap().size(); + + 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 >= NUM_UNITS + * (int) Math.pow(NUM_PREFIXES, expectedLength - 1)) { + expectedLength++; + unitsWithThisLengthSoFar = 0; + } + + // test that stuff is valid + 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++; + } + + // test toString for consistency + final String entryIteratorString = entryIterator.toString(); + for (int i = 0; i < 3; i++) { + assertEquals(entryIteratorString, entryIterator.toString()); + } + + final String nameIteratorString = nameIterator.toString(); + for (int i = 0; i < 3; i++) { + assertEquals(nameIteratorString, nameIterator.toString()); + } + } + + /** + * 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 UnitDatabase database = new UnitDatabase(); + + 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", UnitPrefix.valueOf(17)); + + final Unit expected2 = J.times(17); + final Unit actual2 = database.getUnit("ABCJ"); + + assertEquals(expected2, actual2); + } +} diff --git a/src/test/java/sevenUnits/unit/UnitTest.java b/src/test/java/sevenUnits/unit/UnitTest.java new file mode 100644 index 0000000..a980054 --- /dev/null +++ b/src/test/java/sevenUnits/unit/UnitTest.java @@ -0,0 +1,153 @@ +/** + * Copyright (C) 2018 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 sevenUnits.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.jupiter.api.Test; + +import sevenUnits.unit.LinearUnit; +import sevenUnits.unit.LinearUnitValue; +import sevenUnits.unit.NameSymbol; +import sevenUnits.unit.Metric; +import sevenUnits.unit.Unit; +import sevenUnits.unit.UnitValue; +import sevenUnits.utils.DecimalComparison; + +/** + * Testing the various Unit classes. This is NOT part of this program's public + * API. + * + * @author Adrien Hopkins + * @since 2018-12-22 + * @since v0.1.0 + */ +class UnitTest { + /** A random number generator */ + private static final Random rng = ThreadLocalRandom.current(); + + @Test + public void testAdditionAndSubtraction() { + final LinearUnit inch = Metric.METRE.times(0.0254) + .withName(NameSymbol.of("inch", "in")); + final LinearUnit foot = Metric.METRE.times(0.3048) + .withName(NameSymbol.of("foot", "ft")); + + assertEquals(inch.plus(foot), Metric.METRE.times(0.3302)); + assertEquals(foot.minus(inch), Metric.METRE.times(0.2794)); + + // test with LinearUnitValue + final LinearUnitValue value1 = LinearUnitValue.getExact(Metric.METRE, 15); + final LinearUnitValue value2 = LinearUnitValue.getExact(foot, 120); + final LinearUnitValue value3 = LinearUnitValue.getExact(Metric.METRE, 0.5); + final LinearUnitValue value4 = LinearUnitValue.getExact(Metric.KILOGRAM, 60); + + // make sure addition is done correctly + assertEquals(51.576, value1.plus(value2).getValueExact(), 0.001); + assertEquals(15.5, value1.plus(value3).getValueExact()); + assertEquals(52.076, value1.plus(value2).plus(value3).getValueExact(), + 0.001); + + // make sure addition uses the correct unit, and is still associative + // (ignoring floating-point rounding errors) + assertEquals(Metric.METRE, value1.plus(value2).getUnit()); + assertEquals(Metric.METRE, value1.plus(value2).plus(value3).getUnit()); + assertEquals(foot, value2.plus(value1).getUnit()); + assertTrue(value1.plus(value2).equals(value2.plus(value1), true)); + + // make sure errors happen when they should + assertThrows(IllegalArgumentException.class, () -> value1.plus(value4)); + } + + @Test + public void testConversion() { + final LinearUnit metre = Metric.METRE; + final Unit inch = metre.times(0.0254); + + final UnitValue value = UnitValue.of(inch, 75); + + assertEquals(1.9, inch.convertTo(metre, 75), 0.01); + assertEquals(1.9, value.convertTo(metre).getValue(), 0.01); + + // try random stuff + for (int i = 0; i < 1000; i++) { + // initiate random values + final double conversionFactor = UnitTest.rng.nextDouble() * 1000000; + final double testValue = UnitTest.rng.nextDouble() * 1000000; + final double expected = testValue * conversionFactor; + + // test + final Unit unit = Metric.METRE.times(conversionFactor); + final double actual = unit.convertToBase(testValue); + + assertEquals(actual, expected, + expected * DecimalComparison.DOUBLE_EPSILON); + } + } + + @Test + public void testEquals() { + final LinearUnit metre = Metric.METRE; + final Unit meter = Metric.BaseUnits.METRE.asLinearUnit(); + + assertEquals(metre, meter); + } + + @Test + public void testIsMetric() { + final Unit metre = Metric.METRE; + final Unit megasecond = Metric.SECOND.withPrefix(Metric.MEGA); + final Unit hour = Metric.HOUR; + + assertTrue(metre.isMetric()); + assertTrue(megasecond.isMetric()); + assertFalse(hour.isMetric()); + } + + @Test + public void testMultiplicationAndDivision() { + // test unit-times-unit multiplication + final LinearUnit generatedJoule = Metric.KILOGRAM + .times(Metric.METRE.toExponent(2)).dividedBy(Metric.SECOND.toExponent(2)); + final LinearUnit actualJoule = Metric.JOULE; + + assertEquals(generatedJoule, actualJoule); + + // test multiplication by conversion factors + final LinearUnit kilometre = Metric.METRE.times(1000); + final LinearUnit hour = Metric.SECOND.times(3600); + final LinearUnit generatedKPH = kilometre.dividedBy(hour); + + final LinearUnit actualKPH = Metric.METRE.dividedBy(Metric.SECOND).dividedBy(3.6); + + assertEquals(generatedKPH, actualKPH); + } + + @Test + public void testPrefixes() { + final LinearUnit generatedKilometre = Metric.METRE.withPrefix(Metric.KILO); + final LinearUnit actualKilometre = Metric.METRE.times(1000); + + assertEquals(generatedKilometre, actualKilometre); + } +} diff --git a/src/test/java/sevenUnits/utils/ConditionalExistenceCollectionsTest.java b/src/test/java/sevenUnits/utils/ConditionalExistenceCollectionsTest.java new file mode 100644 index 0000000..46afe77 --- /dev/null +++ b/src/test/java/sevenUnits/utils/ConditionalExistenceCollectionsTest.java @@ -0,0 +1,161 @@ +/** + * 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 sevenUnits.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; + +import org.junit.jupiter.api.Test; + +import sevenUnits.utils.ConditionalExistenceCollections; +import sevenUnits.utils.ConditionalExistenceCollections.ConditionalExistenceIterator; + +/** + * Tests the {@link #ConditionalExistenceCollections}. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +class ConditionalExistenceCollectionsTest { + + /** + * The returned iterator ignores elements that don't start with "a". + * + * @return test iterator + * @since 2019-10-17 + */ + ConditionalExistenceIterator<String> getTestIterator() { + final List<String> items = Arrays.asList("aa", "ab", "ba"); + final Iterator<String> it = items.iterator(); + final ConditionalExistenceIterator<String> cit = (ConditionalExistenceIterator<String>) ConditionalExistenceCollections + .conditionalExistenceIterator(it, s -> s.startsWith("a")); + return cit; + } + + /** + * The returned map ignores mappings where the value is zero. + * + * @return map to be used for test data + * @since 2019-10-16 + */ + Map<String, Integer> getTestMap() { + final Map<String, Integer> map = new HashMap<>(); + map.put("one", 1); + map.put("two", 2); + map.put("zero", 0); + map.put("ten", 10); + final Map<String, Integer> conditionalMap = ConditionalExistenceCollections.conditionalExistenceMap(map, + e -> !Integer.valueOf(0).equals(e.getValue())); + return conditionalMap; + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsKey(java.lang.Object)}. + */ + @Test + void testContainsKeyObject() { + final Map<String, Integer> map = this.getTestMap(); + assertTrue(map.containsKey("one")); + assertTrue(map.containsKey("ten")); + assertFalse(map.containsKey("five")); + assertFalse(map.containsKey("zero")); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsValue(java.lang.Object)}. + */ + @Test + void testContainsValueObject() { + final Map<String, Integer> map = this.getTestMap(); + assertTrue(map.containsValue(1)); + assertTrue(map.containsValue(10)); + assertFalse(map.containsValue(5)); + assertFalse(map.containsValue(0)); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#entrySet()}. + */ + @Test + void testEntrySet() { + final Map<String, Integer> map = this.getTestMap(); + for (final Entry<String, Integer> e : map.entrySet()) { + assertTrue(e.getValue() != 0); + } + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#get(java.lang.Object)}. + */ + @Test + void testGetObject() { + final Map<String, Integer> map = this.getTestMap(); + assertEquals(1, map.get("one")); + assertEquals(10, map.get("ten")); + assertEquals(null, map.get("five")); + assertEquals(null, map.get("zero")); + } + + @Test + void testIterator() { + final ConditionalExistenceIterator<String> testIterator = this.getTestIterator(); + + assertTrue(testIterator.hasNext); + assertTrue(testIterator.hasNext()); + assertEquals("aa", testIterator.nextElement); + assertEquals("aa", testIterator.next()); + + assertTrue(testIterator.hasNext); + assertTrue(testIterator.hasNext()); + assertEquals("ab", testIterator.nextElement); + assertEquals("ab", testIterator.next()); + + assertFalse(testIterator.hasNext); + assertFalse(testIterator.hasNext()); + assertEquals(null, testIterator.nextElement); + assertThrows(NoSuchElementException.class, testIterator::next); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#keySet()}. + */ + @Test + void testKeySet() { + final Map<String, Integer> map = this.getTestMap(); + assertFalse(map.keySet().contains("zero")); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#values()}. + */ + @Test + void testValues() { + final Map<String, Integer> map = this.getTestMap(); + assertFalse(map.values().contains(0)); + } + +} diff --git a/src/test/java/sevenUnits/utils/ExpressionParserTest.java b/src/test/java/sevenUnits/utils/ExpressionParserTest.java new file mode 100644 index 0000000..29648ee --- /dev/null +++ b/src/test/java/sevenUnits/utils/ExpressionParserTest.java @@ -0,0 +1,54 @@ +/** + * 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 sevenUnits.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import sevenUnits.utils.ExpressionParser; + +/** + * A test for the {@code ExpressionParser} class. This is NOT part of this program's public API. + * + * @author Adrien Hopkins + * @since 2019-03-22 + * @since v0.2.0 + */ +class ExpressionParserTest { + private static final ExpressionParser<Integer> numberParser = new ExpressionParser.Builder<>(Integer::parseInt) + .addBinaryOperator("+", (o1, o2) -> o1 + o2, 0).addBinaryOperator("-", (o1, o2) -> o1 - o2, 0) + .addBinaryOperator("*", (o1, o2) -> o1 * o2, 1).addBinaryOperator("/", (o1, o2) -> o1 / o2, 1) + .addBinaryOperator("^", (o1, o2) -> (int) Math.pow(o1, o2), 2).build(); + + /** + * Test method for {@link sevenUnits.utils.ExpressionParser#parseExpression(java.lang.String)}. + */ + @Test + public void testParseExpression() { + // test parsing of expressions + assertEquals((int) numberParser.parseExpression("1 + 2 ^ 5 * 3"), 97); + assertEquals((int) numberParser.parseExpression("(1 + 2) ^ 5 * 3"), 729); + + // ensure it normally goes left to right + assertEquals((int) numberParser.parseExpression("1 + 2 + 3 + 4"), 10); + assertEquals((int) numberParser.parseExpression("12 - 4 - 3"), 5); + assertEquals((int) numberParser.parseExpression("12 - (4 - 3)"), 11); + assertEquals((int) numberParser.parseExpression("1 / 2 + 3"), 3); + } + +} diff --git a/src/test/java/sevenUnits/utils/ObjectProductTest.java b/src/test/java/sevenUnits/utils/ObjectProductTest.java new file mode 100644 index 0000000..13fd7ec --- /dev/null +++ b/src/test/java/sevenUnits/utils/ObjectProductTest.java @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2018 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 sevenUnits.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static sevenUnits.unit.Metric.Dimensions.AREA; +import static sevenUnits.unit.Metric.Dimensions.ENERGY; +import static sevenUnits.unit.Metric.Dimensions.LENGTH; +import static sevenUnits.unit.Metric.Dimensions.MASS; +import static sevenUnits.unit.Metric.Dimensions.MASS_DENSITY; +import static sevenUnits.unit.Metric.Dimensions.QUANTITY; +import static sevenUnits.unit.Metric.Dimensions.TIME; +import static sevenUnits.unit.Metric.Dimensions.VOLUME; + +import org.junit.jupiter.api.Test; + +import sevenUnits.unit.Metric; +import sevenUnits.utils.ObjectProduct; + +/** + * Tests for {@link ObjectProduct} using BaseDimension as a test object. This is NOT part of this program's public API. + * + * @author Adrien Hopkins + * @since 2018-12-12 + * @since v0.1.0 + */ +class ObjectProductTest { + /** + * Tests {@link UnitDimension#equals} + * + * @since 2018-12-12 + * @since v0.1.0 + */ + @Test + public void testEquals() { + assertEquals(LENGTH, LENGTH); + assertFalse(LENGTH.equals(QUANTITY)); + } + + /** + * Tests {@code UnitDimension}'s exponentiation + * + * @since 2019-01-15 + * @since v0.1.0 + */ + @Test + public void testExponents() { + assertEquals(1, LENGTH.getExponent(Metric.BaseDimensions.LENGTH)); + assertEquals(3, VOLUME.getExponent(Metric.BaseDimensions.LENGTH)); + } + + /** + * Tests {@code UnitDimension}'s multiplication and division. + * + * @since 2018-12-12 + * @since v0.1.0 + */ + @Test + public void testMultiplicationAndDivision() { + assertEquals(AREA, LENGTH.times(LENGTH)); + assertEquals(MASS_DENSITY, MASS.dividedBy(VOLUME)); + assertEquals(ENERGY, AREA.times(MASS).dividedBy(TIME).dividedBy(TIME)); + assertEquals(LENGTH, LENGTH.times(TIME).dividedBy(TIME)); + } +} |