summaryrefslogtreecommitdiff
path: root/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/sevenUnits/unit/UnitDatabaseTest.java')
-rw-r--r--src/test/java/sevenUnits/unit/UnitDatabaseTest.java324
1 files changed, 228 insertions, 96 deletions
diff --git a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
index 9d650f0..3d6d663 100644
--- a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
+++ b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2019 Adrien Hopkins
+ * Copyright (C) 2019, 2021, 2022, 2024, 2025 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
@@ -23,20 +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;
@@ -45,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
@@ -57,8 +58,8 @@ class UnitDatabaseTest {
private V value;
/**
- *
* @since 2021-10-07
+ * @since v0.3.2
*/
public SimpleEntry(K key, V value) {
this.key = key;
@@ -94,7 +95,7 @@ class UnitDatabaseTest {
@Override
public V setValue(V value) {
- final V oldValue = this.value;
+ final var oldValue = this.value;
this.value = value;
return oldValue;
}
@@ -135,6 +136,7 @@ class UnitDatabaseTest {
* @param value value in entry
* @return entry
* @since 2021-10-07
+ * @since v0.3.2
*/
private static <K, V> Map.Entry<K, V> entry(K key, V value) {
return new SimpleEntry<>(key, value);
@@ -146,14 +148,18 @@ class UnitDatabaseTest {
*
* @param loadTo database to load to
* @param path path of file to load
+ * @return exceptions returned by file loading
* @since 2021-10-04
+ * @since v0.3.2
*/
- private static void loadDimensionFile(UnitDatabase loadTo, String path) {
- try (final InputStream testFile = UnitDatabaseTest.class
+ private static List<LoadingException> loadDimensionFile(UnitDatabase loadTo,
+ String path) {
+ try (final var testFile = UnitDatabaseTest.class
.getResourceAsStream(path)) {
- loadTo.loadDimensionsFromStream(testFile);
+ return loadTo.loadDimensionsFromStream(testFile);
} catch (final IOException e) {
fail(e.getClass() + " occurred upon loading file \"" + path + "\".");
+ return Collections.emptyList();
}
}
@@ -163,26 +169,89 @@ class UnitDatabaseTest {
*
* @param loadTo database to load to
* @param path path of file to load
+ * @return exceptions returned by file loading
* @since 2021-09-22
+ * @since v0.3.2
*/
- private static void loadUnitsFile(UnitDatabase loadTo, String path) {
- try (final InputStream testFile = UnitDatabaseTest.class
+ private static List<LoadingException> loadUnitsFile(UnitDatabase loadTo,
+ String path) {
+ try (final var testFile = UnitDatabaseTest.class
.getResourceAsStream(path)) {
- loadTo.loadUnitsFromStream(testFile);
+ return loadTo.loadUnitsFromStream(testFile);
} catch (final IOException e) {
fail(e.getClass() + " occurred upon loading file \"" + path + "\".");
+ 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() {
+ final var uncertainTwoThirds = UncertainDouble.of(2.0, 1.0)
+ .dividedBy(UncertainDouble.of(3.0, 1.0));
+ 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 + 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))),
+ Arguments.of("2 J / 3 J",
+ LinearUnitValue.of(J.dividedBy(J), uncertainTwoThirds)));
+ }
+
+ private static final Stream<Arguments> testFormatExpression() {
+ return Stream.of(Arguments.of("1*2", "1 * 2"),
+ Arguments.of("1/2", "1 / 2"), Arguments.of("1|2", "1 | 2"),
+ Arguments.of("1^2", "1 ^ 2"), Arguments.of("1 * 2", "1 * 2"),
+ Arguments.of("+1", "+1"), Arguments.of("-1", "-1"),
+ Arguments.of("1.1e+5", "1.1e+5"),
+ Arguments.of("1.25e-5", "1.25e-5"));
+ }
+
+ /**
+ * 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
+ * @since v0.3.2
*/
- @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);
@@ -191,27 +260,30 @@ class UnitDatabaseTest {
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);
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ public void testFormatExpression(String expression, String expected) {
+ assertEquals(expected, UnitDatabase.formatExpression(expression));
}
/**
* Test for {@link UnitDatabase#getUnit}, {@link UnitDatabase#getLinearUnit}
* and {@link UnitDatabase#getLinearUnitValue}.
- *
+ *
* @since 2021-10-07
+ * @since v0.3.2
*/
@Test
public void testGetUnit() {
- final UnitDatabase database = new UnitDatabase();
+ final var database = new UnitDatabase();
database.addUnit("m", Metric.METRE);
database.addUnit("meter", Metric.METRE);
@@ -239,14 +311,15 @@ class UnitDatabaseTest {
/**
* Confirms that operations that shouldn't function for infinite databases
* throw an {@code IllegalStateException}.
- *
+ *
* @since 2019-05-03
+ * @since v0.3.0
*/
// @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);
@@ -255,9 +328,8 @@ class UnitDatabaseTest {
infiniteDatabase.addPrefix("B", B);
infiniteDatabase.addPrefix("C", C);
- final Set<Entry<String, Unit>> entrySet = infiniteDatabase.unitMap()
- .entrySet();
- final Set<String> keySet = infiniteDatabase.unitMap().keySet();
+ final var entrySet = infiniteDatabase.unitMap().entrySet();
+ final var keySet = infiniteDatabase.unitMap().keySet();
assertThrows(IllegalStateException.class, () -> entrySet.toArray());
assertThrows(IllegalStateException.class, () -> keySet.toArray());
}
@@ -267,18 +339,20 @@ class UnitDatabaseTest {
*
* @param num which file to test
* @since 2021-10-04
+ * @since v0.3.2
*/
@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 RuntimeException e = assertThrows(RuntimeException.class,
- () -> loadDimensionFile(database, filename));
+ final var errs = loadDimensionFile(database, filename);
+ assertFalse(errs.isEmpty(), "no error from invalid file " + filename);
+ final var e = errs.get(0).problem();
assertTrue(e instanceof IllegalArgumentException
|| e instanceof NoSuchElementException);
}
@@ -288,27 +362,29 @@ class UnitDatabaseTest {
*
* @param num which file to test
* @since 2021-09-27
+ * @since v0.3.2
*/
@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",
- num);
- final RuntimeException e = assertThrows(RuntimeException.class,
- () -> loadUnitsFile(database, filename));
+ final var database = new UnitDatabase();
+ final var filename = String.format("/test-unitsfile-invalid%d.txt", num);
+ final var errs = loadUnitsFile(database, filename);
+ assertFalse(errs.isEmpty(), "no error from invalid file " + filename);
+ 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
+ * @since v0.3.2
*/
@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);
@@ -321,27 +397,33 @@ class UnitDatabaseTest {
/**
* Tests loading a valid unitfile with some prefixes and no units.
- *
+ *
* @since 2021-09-22
+ * @since v0.3.2
*/
@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
+ * @since v0.3.2
*/
@Test
public void testLoadingValidUnits() {
- final UnitDatabase database = new UnitDatabase();
+ final var database = new UnitDatabase();
database.addUnit("U", U);
database.addUnit("V", V);
@@ -357,21 +439,21 @@ class UnitDatabaseTest {
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);
@@ -382,21 +464,21 @@ class UnitDatabaseTest {
/**
* Tests the iterator of the prefixless unit map. These tests are simple, as
* the unit map iterator is simple.
- *
+ *
* @since 2021-10-07
+ * @since v0.3.2
*/
@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()
- .iterator();
+ 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<>();
@@ -418,13 +500,13 @@ class UnitDatabaseTest {
/**
* 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);
@@ -439,29 +521,28 @@ class UnitDatabaseTest {
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
- .unitMapPrefixless(true);
+ final var database = new UnitDatabase();
+ final var prefixlessUnits = database.unitMapPrefixless(true);
database.addUnit("U", U);
database.addUnit("V", V);
@@ -478,13 +559,13 @@ class UnitDatabaseTest {
/**
* 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);
@@ -517,7 +598,7 @@ class UnitDatabaseTest {
@Test
public void testToString() {
- final UnitDatabase database = new UnitDatabase();
+ final var database = new UnitDatabase();
database.addUnit("J", J);
database.addUnit("K", J);
@@ -538,14 +619,14 @@ class UnitDatabaseTest {
/**
* 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);
@@ -560,13 +641,13 @@ class UnitDatabaseTest {
// 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);
@@ -579,14 +660,14 @@ class UnitDatabaseTest {
/**
* 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);
@@ -595,19 +676,17 @@ class UnitDatabaseTest {
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 var NUM_UNITS = database.unitMapPrefixless(true).size();
+ final var NUM_PREFIXES = database.prefixMap(true).size();
- final Iterator<String> nameIterator = database.unitMap().keySet()
- .iterator();
- final Iterator<Entry<String, Unit>> entryIterator = database.unitMap()
- .entrySet().iterator();
+ final var nameIterator = database.unitMap().keySet().iterator();
+ 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)) {
@@ -616,9 +695,9 @@ class UnitDatabaseTest {
}
// 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());
@@ -628,13 +707,13 @@ class UnitDatabaseTest {
}
// 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());
}
}
@@ -646,14 +725,14 @@ 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);
@@ -665,7 +744,7 @@ class UnitDatabaseTest {
// 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);
@@ -674,8 +753,61 @@ class UnitDatabaseTest {
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
+ * @since v1.0.0
+ */
+ @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
+ * @since v1.0.0
+ */
+ @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"));
+ }
+
}