summaryrefslogtreecommitdiff
path: root/src/test/java/sevenUnits/unit
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/sevenUnits/unit')
-rw-r--r--src/test/java/sevenUnits/unit/MultiUnitTest.java4
-rw-r--r--src/test/java/sevenUnits/unit/UnitDatabaseTest.java385
-rw-r--r--src/test/java/sevenUnits/unit/UnitTest.java92
3 files changed, 455 insertions, 26 deletions
diff --git a/src/test/java/sevenUnits/unit/MultiUnitTest.java b/src/test/java/sevenUnits/unit/MultiUnitTest.java
index d632118..39ee21c 100644
--- a/src/test/java/sevenUnits/unit/MultiUnitTest.java
+++ b/src/test/java/sevenUnits/unit/MultiUnitTest.java
@@ -25,10 +25,6 @@ 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}.
*
diff --git a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
index 1d5e503..2276d7c 100644
--- a/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
+++ b/src/test/java/sevenUnits/unit/UnitDatabaseTest.java
@@ -20,23 +20,26 @@ 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 static org.junit.jupiter.api.Assertions.fail;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Arrays;
+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 org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
-import sevenUnits.unit.LinearUnit;
-import sevenUnits.unit.NameSymbol;
-import sevenUnits.unit.Metric;
-import sevenUnits.unit.Unit;
-import sevenUnits.unit.UnitDatabase;
-import sevenUnits.unit.UnitPrefix;
+import sevenUnits.utils.UncertainDouble;
/**
* A test for the {@link UnitDatabase} class. This is NOT part of this program's
@@ -47,20 +50,70 @@ import sevenUnits.unit.UnitPrefix;
* @since v0.2.0
*/
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)
+ return true;
+ if (!(obj instanceof Map.Entry<?, ?>))
+ return false;
+ final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
+ 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;
+ 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;
+ 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))
+ 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);
+ 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"));
@@ -69,9 +122,120 @@ 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.
+ *
+ * @param <K> type of key
+ * @param <V> type of value
+ * @param key key in entry
+ * @param value value in entry
+ * @return entry
+ * @since 2021-10-07
+ */
+ 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}.
+ *
+ * @param loadTo database to load to
+ * @param path path of file to load
+ * @since 2021-10-04
+ */
+ private static void loadDimensionFile(UnitDatabase loadTo, String path) {
+ try (final InputStream testFile = UnitDatabaseTest.class
+ .getResourceAsStream(path)) {
+ loadTo.loadDimensionsFromStream(testFile);
+ } catch (final IOException e) {
+ fail(e.getClass() + " occurred upon loading file \"" + path + "\".");
+ }
+ }
+
+ /**
+ * Loads the unitfile at src/test/resources/[path] to the database
+ * {@code loadTo}.
+ *
+ * @param loadTo database to load to
+ * @param path path of file to load
+ * @since 2021-09-22
+ */
+ private static void loadUnitsFile(UnitDatabase loadTo, String path) {
+ try (final InputStream testFile = UnitDatabaseTest.class
+ .getResourceAsStream(path)) {
+ loadTo.loadUnitsFromStream(testFile);
+ } catch (final IOException e) {
+ fail(e.getClass() + " occurred upon loading file \"" + path + "\".");
+ }
+ }
+
+ /**
+ * 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();
+
+ 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");
+ assertEquals(expected, actual);
+
+ // check that negation works properly
+ assertEquals(2,
+ database.evaluateUnitExpression("J - -1 * J").getValueExact());
+ }
+
+ /**
+ * 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();
+
+ 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"));
+ assertEquals(Metric.METRE, database.getUnit("metre"));
+ assertEquals(Metric.METRE, database.getUnit("meter"));
+ 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}.
*
@@ -98,6 +262,160 @@ class UnitDatabaseTest {
}
/**
+ * A bunch of tests for invalid dimension files
+ *
+ * @param num which file to test
+ * @since 2021-10-04
+ */
+ @ParameterizedTest
+ @ValueSource(ints = { 1, 2, 3 })
+ public void testLoadingInvalidDimensionFile(int num) {
+ final UnitDatabase 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",
+ num);
+ final RuntimeException e = assertThrows(RuntimeException.class,
+ () -> loadDimensionFile(database, filename));
+ assertTrue(e instanceof IllegalArgumentException
+ || e instanceof NoSuchElementException);
+ }
+
+ /**
+ * A bunch of tests for invalid unit files
+ *
+ * @param num which file to test
+ * @since 2021-09-27
+ */
+ @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));
+ 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();
+ 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();
+
+ loadUnitsFile(database, "/test-unitsfile-valid2.txt");
+ assertEquals(7, database.getPrefix("A").getMultiplier());
+ assertEquals(11, database.getPrefix("B").getMultiplier());
+ assertEquals(13, database.getPrefix("C").getMultiplier());
+ }
+
+ /**
+ * Tests loading a valid unitfile with some units and preloaded prefixes
+ *
+ * @since 2021-09-22
+ */
+ @Test
+ public void testLoadingValidUnits() {
+ 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);
+
+ loadUnitsFile(database, "/test-unitsfile-valid1.txt");
+
+ final Unit expected1 = ((LinearUnit) U).withPrefix(A).withPrefix(B)
+ .withPrefix(C);
+ final Unit 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");
+ assertEquals(expected2, actual2);
+
+ final Unit expected3 = ((LinearUnit) U)
+ .times(A.getMultiplier() + C.getMultiplier() - B.getMultiplier());
+ final Unit actual3 = database.getUnit("test3");
+ assertEquals(expected3, actual3);
+
+ final UnitValue expected4 = UnitValue.of(U, 1);
+ final UnitValue 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();
+
+ 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 Set<String> expectedKeys = Set.of("U", "V", "W");
+ final Set<String> actualKeys = new HashSet<>();
+ while (keyIterator1.hasNext()) {
+ actualKeys.add(keyIterator1.next());
+ }
+ 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<>();
+ while (entryIterator1.hasNext()) {
+ actualEntries.add(entryIterator1.next());
+ }
+ assertEquals(expectedEntries, actualEntries);
+ assertEquals(expectedEntries, map1.entrySet());
+ }
+
+ /**
* Test that prefixes correctly apply to units.
*
* @since 2019-04-14
@@ -178,6 +496,45 @@ class UnitDatabaseTest {
assertThrows(NoSuchElementException.class, () -> database.getUnit("Z"));
}
+ @Test
+ public void testRemovableDuplicates() {
+ final Map<String, Unit> unitMap = new HashMap<>();
+ unitMap.put("meter", Metric.METRE);
+ 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,
+ entry("meter", Metric.METRE)));
+ assertFalse(UnitDatabase.isRemovableDuplicate(unitMap,
+ entry("metre", Metric.METRE)));
+ assertFalse(UnitDatabase.isRemovableDuplicate(unitMap,
+ entry("second", Metric.SECOND)));
+ }
+
+ @Test
+ public void testToString() {
+ final UnitDatabase 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.
*
@@ -211,6 +568,12 @@ class UnitDatabaseTest {
final Unit 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"));
}
/**
diff --git a/src/test/java/sevenUnits/unit/UnitTest.java b/src/test/java/sevenUnits/unit/UnitTest.java
index a980054..bb2e6a4 100644
--- a/src/test/java/sevenUnits/unit/UnitTest.java
+++ b/src/test/java/sevenUnits/unit/UnitTest.java
@@ -26,13 +26,8 @@ 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;
+import sevenUnits.utils.UncertainDouble;
/**
* Testing the various Unit classes. This is NOT part of this program's public
@@ -59,8 +54,10 @@ class UnitTest {
// 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);
+ 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);
@@ -77,6 +74,7 @@ class UnitTest {
// make sure errors happen when they should
assertThrows(IllegalArgumentException.class, () -> value1.plus(value4));
+ assertThrows(IllegalArgumentException.class, () -> value1.minus(value4));
}
@Test
@@ -128,7 +126,8 @@ class UnitTest {
public void testMultiplicationAndDivision() {
// test unit-times-unit multiplication
final LinearUnit generatedJoule = Metric.KILOGRAM
- .times(Metric.METRE.toExponent(2)).dividedBy(Metric.SECOND.toExponent(2));
+ .times(Metric.METRE.toExponent(2))
+ .dividedBy(Metric.SECOND.toExponent(2));
final LinearUnit actualJoule = Metric.JOULE;
assertEquals(generatedJoule, actualJoule);
@@ -138,16 +137,87 @@ class UnitTest {
final LinearUnit hour = Metric.SECOND.times(3600);
final LinearUnit generatedKPH = kilometre.dividedBy(hour);
- final LinearUnit actualKPH = Metric.METRE.dividedBy(Metric.SECOND).dividedBy(3.6);
+ 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 generatedKilometre = Metric.METRE
+ .withPrefix(Metric.KILO);
final LinearUnit actualKilometre = Metric.METRE.times(1000);
assertEquals(generatedKilometre, actualKilometre);
}
+
+ /**
+ * Tests converting an uncertain LinearUnitValue to a string.
+ *
+ * @since 2021-11-04
+ */
+ @Test
+ public void testValueToString1() {
+ final LinearUnitValue value = LinearUnitValue.of(Metric.METRE,
+ UncertainDouble.of(10, 0.24));
+
+ assertEquals("(10.0 ± 0.2) m", value.toString());
+ assertEquals("(10.0 ± 0.2) m", value.toString(true));
+ assertEquals("10.0 m", value.toString(false));
+ }
+
+ /**
+ * Tests converting a certain LinearUnitValue to a string.
+ *
+ * @since 2021-11-04
+ */
+ @Test
+ public void testValueToString2() {
+ final LinearUnitValue value = LinearUnitValue.of(Metric.METRE,
+ UncertainDouble.of(10, 0));
+
+ assertEquals("10.0 m", value.toString());
+ assertEquals("(10.0 ± 0.0) m", value.toString(true));
+ assertEquals("10.0 m", value.toString(false));
+ }
+
+ /**
+ * Tests converting an unnamed LinearUnitValue to a string.
+ *
+ * @since 2021-11-04
+ */
+ @Test
+ public void testValueToString3() {
+ final LinearUnitValue value = LinearUnitValue.of(
+ Metric.METRE.withName(NameSymbol.EMPTY),
+ UncertainDouble.of(10, 0.24));
+
+ assertEquals("10.0 unnamed unit (= 10.0 m)", value.toString(false));
+ }
+
+ /**
+ * Tests converting a named UnitValue to a string.
+ *
+ * @since 2021-11-04
+ */
+ @Test
+ public void testValueToString4() {
+ final UnitValue value = UnitValue.of(BritishImperial.FAHRENHEIT, 80);
+
+ assertEquals("80.0 \u00B0F", value.toString());
+ }
+
+ /**
+ * Tests converting an unnamed UnitValue to a string.
+ *
+ * @since 2021-11-04
+ */
+ @Test
+ public void testValueToString5() {
+ final UnitValue value = UnitValue
+ .of(USCustomary.FAHRENHEIT.withName(NameSymbol.EMPTY), 50);
+
+ assertEquals("50.0 unnamed unit (= 283.15 K)", value.toString());
+ }
}