summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Hopkins <adrien.p.hopkins@gmail.com>2025-04-30 16:42:01 -0500
committerAdrien Hopkins <adrien.p.hopkins@gmail.com>2025-04-30 16:42:01 -0500
commit4910b914392753986526bc28102ddef42e275e6c (patch)
treec3c6e748584cef92660ed3cfce4a33a30491a150
parentd1335dd378a7e302e4853c2695f2931c244b8863 (diff)
Add more UnitDatabase tests
-rw-r--r--src/main/java/sevenUnits/unit/UnitDatabase.java13
-rw-r--r--src/test/java/sevenUnits/unit/UnitDatabaseTest.java460
2 files changed, 286 insertions, 187 deletions
diff --git a/src/main/java/sevenUnits/unit/UnitDatabase.java b/src/main/java/sevenUnits/unit/UnitDatabase.java
index dc81aca..690430b 100644
--- a/src/main/java/sevenUnits/unit/UnitDatabase.java
+++ b/src/main/java/sevenUnits/unit/UnitDatabase.java
@@ -1905,18 +1905,23 @@ public final class UnitDatabase {
*
* @since 2024-08-22
*/
- private List<LinearUnit> getUnitSetFromExpression(String expression) {
+ List<LinearUnit> getUnitSetFromExpression(String expression) {
final String[] parts = expression.split(";");
final List<LinearUnit> units = new ArrayList<>(parts.length);
for (final String unitName : parts) {
final Unit unit = this.getUnitFromExpression(unitName.trim());
- if (unit instanceof LinearUnit) {
- units.add((LinearUnit) unit);
- } else
+ if (!(unit instanceof LinearUnit)) {
throw new IllegalArgumentException(String.format(
"Unit '%s' is in a unit-set expression, but is not linear.",
unitName));
+ } else if (units.size() > 0 && !unit.canConvertTo(units.get(0))) {
+ throw new IllegalArgumentException(String.format(
+ "Units in expression '%s' have different dimensions.",
+ expression));
+ }
+
+ units.add((LinearUnit) unit);
}
return units;
}
diff --git a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
index e7f3ccf..e55d6af 100644
--- a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
+++ b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
@@ -23,21 +23,21 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import sevenUnits.utils.NameSymbol;
@@ -46,7 +46,7 @@ import sevenUnits.utils.UncertainDouble;
/**
* 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
@@ -54,18 +54,18 @@ import sevenUnits.utils.UncertainDouble;
class UnitDatabaseTest {
private static final class SimpleEntry<K, V> implements Map.Entry<K, V> {
private final K key;
-
+
private V value;
-
+
/**
- *
+ *
* @since 2021-10-07
*/
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
-
+
@Override
public boolean equals(Object obj) {
if (this == obj)
@@ -76,44 +76,44 @@ class UnitDatabaseTest {
return Objects.equals(this.key, other.getKey())
&& Objects.equals(this.value, other.getValue());
}
-
+
@Override
public K getKey() {
return this.key;
}
-
+
@Override
public V getValue() {
return this.value;
}
-
+
@Override
public int hashCode() {
return (this.key == null ? 0 : this.key.hashCode())
^ (this.value == null ? 0 : this.value.hashCode());
}
-
+
@Override
public V setValue(V value) {
- final V oldValue = this.value;
+ final var oldValue = this.value;
this.value = value;
return oldValue;
}
}
-
+
// 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
@@ -124,9 +124,9 @@ class UnitDatabaseTest {
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);
-
+
/**
* Gets a map entry.
*
@@ -140,7 +140,7 @@ class UnitDatabaseTest {
private static <K, V> Map.Entry<K, V> entry(K key, V value) {
return new SimpleEntry<>(key, value);
}
-
+
/**
* Loads the dimensionfile at src/test/resources/[path] to the database
* {@code loadTo}.
@@ -152,7 +152,7 @@ class UnitDatabaseTest {
*/
private static List<LoadingException> loadDimensionFile(UnitDatabase loadTo,
String path) {
- try (final InputStream testFile = UnitDatabaseTest.class
+ try (final var testFile = UnitDatabaseTest.class
.getResourceAsStream(path)) {
return loadTo.loadDimensionsFromStream(testFile);
} catch (final IOException e) {
@@ -160,7 +160,7 @@ class UnitDatabaseTest {
return Collections.emptyList();
}
}
-
+
/**
* Loads the unitfile at src/test/resources/[path] to the database
* {@code loadTo}.
@@ -172,7 +172,7 @@ class UnitDatabaseTest {
*/
private static List<LoadingException> loadUnitsFile(UnitDatabase loadTo,
String path) {
- try (final InputStream testFile = UnitDatabaseTest.class
+ try (final var testFile = UnitDatabaseTest.class
.getResourceAsStream(path)) {
return loadTo.loadUnitsFromStream(testFile);
} catch (final IOException e) {
@@ -180,53 +180,92 @@ class UnitDatabaseTest {
return Collections.emptyList();
}
}
-
+
+ private static final Stream<Arguments> testEvaluateExpressionInvalid() {
+ return Stream.of(Arguments.of("K^K"), Arguments.of("1 + K"));
+ }
+
+ private static final Stream<Arguments> testEvaluateExpressionValid() {
+ return Stream.of(
+ Arguments.of("J + (2 * 3) J + (20 / 4) J",
+ LinearUnitValue.of(J,
+ UncertainDouble.of(12, Math.sqrt(14.625)))),
+ Arguments.of("J - -1 * J",
+ LinearUnitValue.of(J, UncertainDouble.of(2, 1))),
+ Arguments.of("K^2",
+ LinearUnitValue.of(K.times(K), UncertainDouble.of(1, 0))));
+ }
+
+ /**
+ * Tests expressions that are valid to the parser, but semantically invalid
+ * (e.g. adding different dimensions)
+ *
+ * @param expression expression to test - should throw
+ * {@link IllegalArgumentException}
+ */
+ @ParameterizedTest
+ @MethodSource
+ public void testEvaluateExpressionInvalid(String expression) {
+ final var database = new UnitDatabase();
+
+ database.addUnit("J", J);
+ database.addUnit("K", K);
+
+ database.addPrefix("A", A);
+ database.addPrefix("B", B);
+ database.addPrefix("C", C);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> database.getUnitFromExpression(expression));
+ assertThrows(IllegalArgumentException.class,
+ () -> database.evaluateUnitExpression(expression));
+ }
+
/**
* A test for the {@link UnitDatabase#evaluateUnitExpression(String)}
* function. Simple because the expression parser has its own test.
- *
+ *
* @since 2021-09-27
*/
- @Test
- public void testEvaluateExpression() {
- final UnitDatabase database = new UnitDatabase();
-
+ @ParameterizedTest
+ @MethodSource
+ public void testEvaluateExpressionValid(String expression,
+ LinearUnitValue expected) {
+ final var database = new UnitDatabase();
+
database.addUnit("J", J);
database.addUnit("K", K);
-
+
database.addPrefix("A", A);
database.addPrefix("B", B);
database.addPrefix("C", C);
-
- final LinearUnitValue expected = LinearUnitValue.of(J,
- UncertainDouble.of(12, Math.sqrt(14.625)));
- // note: units are exact, each number has an uncertainty of 1
- final LinearUnitValue actual = database
- .evaluateUnitExpression("J + (2 * 3) J + (20 / 4) J");
+
+ final var actual = database
+ .evaluateUnitExpression(expression);
assertEquals(expected, actual);
-
- // check that negation works properly
- assertEquals(2,
- database.evaluateUnitExpression("J - -1 * J").getValueExact());
+
+ final var expectedU = expected.getUnit().times(expected.getValueExact());
+ final var actualU = database.getUnitFromExpression(expression);
+ assertEquals(expectedU, actualU);
}
-
+
/**
* Test for {@link UnitDatabase#getUnit}, {@link UnitDatabase#getLinearUnit}
* and {@link UnitDatabase#getLinearUnitValue}.
- *
+ *
* @since 2021-10-07
*/
@Test
public void testGetUnit() {
- final UnitDatabase database = new UnitDatabase();
-
+ final var database = new UnitDatabase();
+
database.addUnit("m", Metric.METRE);
database.addUnit("meter", Metric.METRE);
database.addUnit("metre", Metric.METRE);
database.addUnit("badname", Metric.METRE);
database.addUnit("K", Metric.KELVIN);
database.addUnit("degC", Metric.CELSIUS);
-
+
// ensure getUnit returns units, regardless of whether the name is one of
// the unit's names
assertEquals(Metric.METRE, database.getUnit("m"));
@@ -235,40 +274,40 @@ class UnitDatabaseTest {
assertEquals(Metric.METRE, database.getUnit("badname"));
assertThrows(NoSuchElementException.class,
() -> database.getUnit("blabla"));
-
+
assertEquals(Metric.KELVIN, database.getLinearUnit("K"));
assertThrows(IllegalArgumentException.class,
() -> database.getLinearUnit("degC"));
assertEquals(Metric.KELVIN.times(373.15),
database.getLinearUnit("degC(100)"));
}
-
+
/**
* 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();
-
+ final var 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()
+
+ final var entrySet = infiniteDatabase.unitMap()
.entrySet();
- final Set<String> keySet = infiniteDatabase.unitMap().keySet();
+ final var keySet = infiniteDatabase.unitMap().keySet();
assertThrows(IllegalStateException.class, () -> entrySet.toArray());
assertThrows(IllegalStateException.class, () -> keySet.toArray());
}
-
+
/**
* A bunch of tests for invalid dimension files
*
@@ -278,19 +317,19 @@ class UnitDatabaseTest {
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
public void testLoadingInvalidDimensionFile(int num) {
- final UnitDatabase database = new UnitDatabase();
+ final var database = new UnitDatabase();
database.addDimension("LENGTH", Metric.Dimensions.LENGTH);
database.addDimension("MASS", Metric.Dimensions.MASS);
database.addDimension("TIME", Metric.Dimensions.TIME);
- final String filename = String.format("/test-dimensionfile-invalid%d.txt",
+ final var filename = String.format("/test-dimensionfile-invalid%d.txt",
num);
- final List<LoadingException> errs = loadDimensionFile(database, filename);
+ final var errs = loadDimensionFile(database, filename);
assertFalse(errs.isEmpty(), "no error from invalid file " + filename);
- final RuntimeException e = errs.get(0).problem();
+ final var e = errs.get(0).problem();
assertTrue(e instanceof IllegalArgumentException
|| e instanceof NoSuchElementException);
}
-
+
/**
* A bunch of tests for invalid unit files
*
@@ -300,113 +339,117 @@ class UnitDatabaseTest {
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3, 4, 5 })
public void testLoadingInvalidUnitFile(int num) {
- final UnitDatabase database = new UnitDatabase();
- final String filename = String.format("/test-unitsfile-invalid%d.txt",
+ final var database = new UnitDatabase();
+ final var filename = String.format("/test-unitsfile-invalid%d.txt",
num);
- final List<LoadingException> errs = loadUnitsFile(database, filename);
+ final var errs = loadUnitsFile(database, filename);
assertFalse(errs.isEmpty(), "no error from invalid file " + filename);
- final RuntimeException e = errs.get(0).problem();
+ final var e = errs.get(0).problem();
assertTrue(e instanceof IllegalArgumentException
|| e instanceof NoSuchElementException);
}
-
+
/**
* Tests loading a valid dimension-file with some derived dimensions.
- *
+ *
* @since 2021-10-04
*/
@Test
public void testLoadingValidDimensions() {
- final UnitDatabase database = new UnitDatabase();
+ final var database = new UnitDatabase();
database.addDimension("LENGTH", Metric.Dimensions.LENGTH);
database.addDimension("MASS", Metric.Dimensions.MASS);
database.addDimension("TIME", Metric.Dimensions.TIME);
-
+
loadDimensionFile(database, "/test-dimensionfile-valid1.txt");
assertEquals(Metric.Dimensions.ENERGY, database.getDimension("ENERGY"));
assertEquals(Metric.Dimensions.POWER, database.getDimension("POWER"));
-
+
}
-
+
/**
* Tests loading a valid unitfile with some prefixes and no units.
- *
+ *
* @since 2021-09-22
*/
@Test
public void testLoadingValidPrefixes() {
- final UnitDatabase database = new UnitDatabase();
-
+ final var database = new UnitDatabase();
+
loadUnitsFile(database, "/test-unitsfile-valid2.txt");
assertEquals(7, database.getPrefix("A").getMultiplier());
assertEquals(11, database.getPrefix("B").getMultiplier());
assertEquals(13, database.getPrefix("C").getMultiplier());
+
+ // test invalid prefixes
+ assertThrows(NoSuchElementException.class,
+ () -> database.getPrefix("N/A"));
}
-
+
/**
* Tests loading a valid unitfile with some units and preloaded prefixes
- *
+ *
* @since 2021-09-22
*/
@Test
public void testLoadingValidUnits() {
- final UnitDatabase database = new UnitDatabase();
-
+ final var 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);
-
+
loadUnitsFile(database, "/test-unitsfile-valid1.txt");
-
+
final Unit expected1 = ((LinearUnit) U).withPrefix(A).withPrefix(B)
.withPrefix(C);
- final Unit actual1 = database.getUnit("test1");
+ final var actual1 = database.getUnit("test1");
assertEquals(expected1, actual1);
-
+
final Unit expected2 = ((LinearUnit) W).withPrefix(B)
.times(((LinearUnit) V).withPrefix(C));
- final Unit actual2 = database.getUnit("test2");
+ final var actual2 = database.getUnit("test2");
assertEquals(expected2, actual2);
-
+
final Unit expected3 = ((LinearUnit) U)
.times(A.getMultiplier() + C.getMultiplier() - B.getMultiplier());
- final Unit actual3 = database.getUnit("test3");
+ final var actual3 = database.getUnit("test3");
assertEquals(expected3, actual3);
-
- final UnitValue expected4 = UnitValue.of(U, 1);
- final UnitValue actual4 = database
+
+ final var expected4 = UnitValue.of(U, 1);
+ final var actual4 = database
.evaluateUnitExpression("-5 * U + -3 * U + 12 * U - 3 * U")
.asUnitValue();
assertEquals(expected4, actual4);
-
+
assertTrue(System.err.toString().length() > 0);
}
-
+
/**
* Tests the iterator of the prefixless unit map. These tests are simple, as
* the unit map iterator is simple.
- *
+ *
* @since 2021-10-07
*/
@Test
public void testPrefixedUnitMapIterator() {
- final UnitDatabase database1 = new UnitDatabase();
-
+ final var database1 = new UnitDatabase();
+
database1.addUnit("U", U);
database1.addUnit("V", V);
database1.addUnit("W", W);
-
- final Map<String, Unit> map1 = database1.unitMap();
- final Iterator<String> keyIterator1 = map1.keySet().iterator();
- final Iterator<Map.Entry<String, Unit>> entryIterator1 = map1.entrySet()
+
+ final var map1 = database1.unitMap();
+ final var keyIterator1 = map1.keySet().iterator();
+ final var entryIterator1 = map1.entrySet()
.iterator();
-
+
final Set<String> expectedKeys = Set.of("U", "V", "W");
final Set<String> actualKeys = new HashSet<>();
while (keyIterator1.hasNext()) {
@@ -414,7 +457,7 @@ class UnitDatabaseTest {
}
assertEquals(expectedKeys, actualKeys);
assertEquals(expectedKeys, map1.keySet());
-
+
final Set<Map.Entry<String, Unit>> expectedEntries = Set.of(entry("U", U),
entry("V", V), entry("W", W));
final Set<Map.Entry<String, Unit>> actualEntries = new HashSet<>();
@@ -424,88 +467,88 @@ class UnitDatabaseTest {
assertEquals(expectedEntries, actualEntries);
assertEquals(expectedEntries, map1.entrySet());
}
-
+
/**
* Test that prefixes correctly apply to units.
- *
+ *
* @since 2019-04-14
* @since v0.2.0
*/
@Test
public void testPrefixes() {
- final UnitDatabase database = new UnitDatabase();
-
+ final var 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");
+ final var abcuNonlinear = database.getUnit("ABCU");
assert abcuNonlinear instanceof LinearUnit;
-
- final LinearUnit abcu = (LinearUnit) abcuNonlinear;
+
+ final var 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
+ final var database = new UnitDatabase();
+ final var 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();
-
+ final var 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
public void testRemovableDuplicates() {
final Map<String, Unit> unitMap = new HashMap<>();
@@ -513,7 +556,7 @@ class UnitDatabaseTest {
unitMap.put("metre", Metric.METRE);
unitMap.put("m", Metric.METRE);
unitMap.put("second", Metric.SECOND);
-
+
assertTrue(UnitDatabase.isRemovableDuplicate(unitMap,
entry("m", Metric.METRE)));
assertTrue(UnitDatabase.isRemovableDuplicate(unitMap,
@@ -523,131 +566,131 @@ class UnitDatabaseTest {
assertFalse(UnitDatabase.isRemovableDuplicate(unitMap,
entry("second", Metric.SECOND)));
}
-
+
@Test
public void testToString() {
- final UnitDatabase database = new UnitDatabase();
-
+ final var database = new UnitDatabase();
+
database.addUnit("J", J);
database.addUnit("K", J);
-
+
database.addPrefix("A", A);
database.addPrefix("B", B);
database.addPrefix("C", C);
-
+
if ("Unit Database with 1 units, 3 unit prefixes and 0 dimensions"
.equals(database.toString())) {
fail("Database counts by number of units, not number of unit names.");
}
-
+
assertEquals(
"Unit Database with 2 units, 3 unit prefixes and 0 dimensions",
database.toString());
}
-
+
/**
* 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();
-
+ final var 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");
-
+ final var 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");
-
+ final var actual2 = database.getUnitFromExpression("2 fj + 6 ej");
+
assertEquals(expected2, actual2);
-
+
// test incorrect expressions
assertThrows(IllegalArgumentException.class,
() -> database.getUnitFromExpression("U + V"));
assertThrows(IllegalArgumentException.class,
() -> database.getUnitFromExpression("U - V"));
}
-
+
/**
* 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();
-
+ final var 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(true).size();
-
- final Iterator<String> nameIterator = database.unitMap().keySet()
+
+ final var NUM_UNITS = database.unitMapPrefixless(true).size();
+ final var NUM_PREFIXES = database.prefixMap(true).size();
+
+ final var nameIterator = database.unitMap().keySet()
.iterator();
- final Iterator<Entry<String, Unit>> entryIterator = database.unitMap()
+ final var entryIterator = database.unitMap()
.entrySet().iterator();
-
- int expectedLength = 1;
- int unitsWithThisLengthSoFar = 0;
-
+
+ var expectedLength = 1;
+ var unitsWithThisLengthSoFar = 0;
+
// loop 1000 times
- for (int i = 0; i < 1000; i++) {
+ for (var 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();
-
+ final var nextName = nameIterator.next();
+ final var nextUnit = database.getUnit(nextName);
+ final var 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++) {
+ final var entryIteratorString = entryIterator.toString();
+ for (var i = 0; i < 3; i++) {
assertEquals(entryIteratorString, entryIterator.toString());
}
-
- final String nameIteratorString = nameIterator.toString();
- for (int i = 0; i < 3; i++) {
+
+ final var nameIteratorString = nameIterator.toString();
+ for (var i = 0; i < 3; i++) {
assertEquals(nameIteratorString, nameIterator.toString());
}
}
-
+
/**
* Determine, given a unit name that could mean multiple things, which
* meaning is chosen.
@@ -655,36 +698,87 @@ class UnitDatabaseTest {
* 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();
-
+ final var 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");
-
+ final var 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");
-
+ final var actual2 = database.getUnit("ABCJ");
+
assertEquals(expected2, actual2);
}
+
+ /**
+ * Tests the ability to create, read, and delete unit sets.
+ *
+ * @since 2025-04-30
+ */
+ @Test
+ void testUnitSetsInvalid() {
+ final List<LinearUnit> units = List.of(Metric.SECOND,
+ BritishImperial.Length.INCH);
+
+ final var database = new UnitDatabase();
+
+ assertThrows(IllegalArgumentException.class,
+ () -> database.addUnitSet("badtest", units));
+ assertThrows(NoSuchElementException.class,
+ () -> database.getUnitSet("badtest"));
+
+ database.addUnit("ft", BritishImperial.Length.FOOT);
+ database.addUnit("s", Metric.SECOND);
+ database.addUnit("dC", Metric.CELSIUS);
+ database.addUnit("K", Metric.KELVIN);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> database.getUnitSetFromExpression("K; dC"),
+ "getUnitSetFromExpression allowed nonlinear unit.");
+ assertThrows(IllegalArgumentException.class,
+ () -> database.getUnitSetFromExpression("ft; s"),
+ "getUnitSetFromExpression allowed units of different dimension.");
+ }
+
+ /**
+ * Tests the ability to create, read, and delete unit sets.
+ *
+ * @since 2025-04-30
+ */
+ @Test
+ void testUnitSetsValid() {
+ final List<LinearUnit> units = List.of(BritishImperial.Length.FOOT,
+ BritishImperial.Length.INCH);
+
+ final var database = new UnitDatabase();
+
+ database.addUnitSet("ftintest", units);
+ assertEquals(units, database.getUnitSet("ftintest"));
+
+ database.addUnit("ft", BritishImperial.Length.FOOT);
+ database.addUnit("in", BritishImperial.Length.INCH);
+ assertEquals(units, database.getUnitSetFromExpression("ft; in"));
+ }
+
}