Skip to content

Commit

Permalink
CLDR-15954 Now that the infrastructure is in place, add a test of one…
Browse files Browse the repository at this point in the history
… test data file
  • Loading branch information
macchiati committed Mar 16, 2024
1 parent cfe4a4e commit 6d1c2e5
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 14 deletions.
2 changes: 1 addition & 1 deletion common/supplemental/units.xml
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ For terms of use, see http://www.unicode.org/copyright.html
<convertUnit source='revolution' baseUnit='revolution' systems="metric_adjacent ussystem uksystem"/>

<!-- substance-amount -->
<convertUnit source='item' baseUnit='item' systems="metric ussystem uksystem"/>
<convertUnit source='item' baseUnit='item' systems="metric_adjacent ussystem uksystem"/>
<convertUnit source='mole' baseUnit='item' factor='item_per_mole' systems="si metric prefixable"/>

<!-- portion -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ public static Rational of(BigDecimal bigDecimal) {
}
}

public static Rational of(double doubleValue) {
return of(new BigDecimal(doubleValue));
}

public enum FormatStyle {
/**
* Simple numerator / denominator, plain BigInteger.toString(), dropping " / 1". <br>
Expand Down Expand Up @@ -728,4 +732,8 @@ public boolean approximatelyEquals(Rational b, Rational epsilon) {
public boolean approximatelyEquals(Rational b) {
return approximatelyEquals(b, EPSILON);
}

public boolean approximatelyEquals(Number b) {
return approximatelyEquals(Rational.of(b.doubleValue()), EPSILON);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1825,19 +1825,27 @@ public Set<UnitSystem> getSystemsEnum(String unit) {
UnitId id = createUnitId(unit);

// we walk through all the units in the numerator and denominator, and keep the
// *intersection* of
// the units. So {ussystem} and {ussystem, uksystem} => ussystem
// Special case: {dmetric} intersect {metric} => {dmetric}. We do that by adding dmetric to
// any set with metric, then removing dmetric if there is a metric
// *intersection* of the units.
// So {ussystem} and {ussystem, uksystem} => ussystem
// Special case: {metric_adjacent} intersect {metric} => {metric_adjacent}.
// We do that by adding metric_adjacent to any set with metric,
// then removing metric_adjacent if there is a metric.
// Same for si_acceptable.
main:
for (Map<String, Integer> unitsToPowers :
Arrays.asList(id.denUnitsToPowers, id.numUnitsToPowers)) {
for (String subunit : unitsToPowers.keySet()) {
subunit = UnitConverter.stripPrefix(subunit, null);
Set<UnitSystem> systems = new TreeSet<>(sourceToSystems.get(subunit));
if (systems.contains(UnitSystem.metric)) {
systems.add(UnitSystem.metric_adjacent);
}
if (systems.contains(UnitSystem.si)) {
systems.add(UnitSystem.si_acceptable);
}

if (result == null) {
result = systems;
result = systems; // first setting
} else {
result.retainAll(systems);
}
Expand All @@ -1846,9 +1854,17 @@ public Set<UnitSystem> getSystemsEnum(String unit) {
}
}
}
return result == null || result.isEmpty()
? ImmutableSet.of(UnitSystem.other)
: ImmutableSet.copyOf(EnumSet.copyOf(result));
if (result == null || result.isEmpty()) {
return ImmutableSet.of(UnitSystem.other);
}
if (result.contains(UnitSystem.metric)) {
result.remove(UnitSystem.metric_adjacent);
}
if (result.contains(UnitSystem.si)) {
result.remove(UnitSystem.si_acceptable);
}

return ImmutableSet.copyOf(EnumSet.copyOf(result)); // the enum is to sort
}

// private void addSystems(Set<String> result, String subunit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,15 @@ public UnitPreference getUnitPreference(
Rational conversion = converter.convert(sourceAmount, sourceUnit, mu, false);
return new UnitPreference(conversion, mu, null);
}
String region = resolveRegion(locale);

return getUnitPreference(sourceAmount, sourceUnit, usage, region);
}

public UnitPreference getUnitPreference(
Rational sourceAmount, String sourceUnit, String usage, String region) {
UnitConverter converter = SupplementalDataInfo.getInstance().getUnitConverter();
String quantity = converter.getQuantityFromUnit(sourceUnit, false);
String baseUnit = converter.getBaseUnitFromQuantity(quantity);

Map<String, Multimap<String, UnitPreference>> usageToRegionsToInfo =
getFastMap().get(quantity);
Expand Down Expand Up @@ -296,7 +302,6 @@ public UnitPreference getUnitPreference(
sourceAmount = Rational.NEGATIVE_ONE;
}

String region = resolveRegion(locale);
Collection<UnitPreference> infoList = regionToInfo.get(region);
if (infoList == null || infoList.isEmpty()) {
infoList = regionToInfo.get("001");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -4519,17 +4521,104 @@ public void testQuantitiesMissingFromPreferences() {
"There are no explicit preferences for %s, but %s is not metric",
quantity, unit));
}
Set<UnitSystem> systems = converter.getSystemsEnum(pref.unit);
Set<UnitSystem> prefSystems = converter.getSystemsEnum(pref.unit);

String errorOrWarningString =
String.format(
"Test default preference is metric: input unit=%s, quantity=%s, pref-unit=%s, systems: %s",
unit, quantity, pref.unit, systems);
if (Collections.disjoint(systems, UnitSystem.SiOrMetric)) {
unit, quantity, pref.unit, prefSystems);
if (Collections.disjoint(prefSystems, UnitSystem.SiOrMetric)) {
Set<UnitSystem> prefSystems2 = converter.getSystemsEnum(pref.unit);
errln(errorOrWarningString);
} else {
logln("OK " + errorOrWarningString);
}
}
}

public void testUnitPreferencesTest() {
try {
UnitPreferences prefs = SDI.getUnitPreferences();

// # Quantity; Usage; Region; Input (r); Input (d); Input Unit; Output (r);
// Output (d); Output Unit
// Example:
// area; default; 001; 1100000; 1100000.0; square-meter;
// 11/10; 1.1; square-kilometer
// duration; media; 001; 66; 66.0; second; 1; minute; 6;
// 6.0; second
Files.lines(Path.of(CLDRPaths.TEST_DATA + "units/unitPreferencesTest.txt"))
.forEach(
line -> {
if (line.startsWith("#") || line.isBlank()) {
return;
}
try {
List<String> parts = SPLIT_SEMI.splitToList(line);
Map<String, Long> highMixed_unit_identifiers =
new LinkedHashMap<>();
String quantity = parts.get(0);
String usage = parts.get(1);
String region = parts.get(2);
Rational inputRational = Rational.of(parts.get(3));
double inputDouble = Double.parseDouble(parts.get(4));
String inputUnit = parts.get(5);
// account for multi-part output
int size = parts.size();
// This section has larger elements with integer values
for (int i = 6; i < size - 3; i += 2) {
highMixed_unit_identifiers.put(
parts.get(i + 1), Long.parseLong(parts.get(i)));
}
Rational expectedValue = Rational.of(parts.get(size - 3));
Double expectedValueDouble =
Double.parseDouble(parts.get(size - 2));
String expectedOutputUnit = parts.get(size - 1);

// Check that the double values are approximately the same as
// the Rational ones
assertTrue(
String.format(
"input rational ~ input double, %s %s",
inputRational, inputDouble),
inputRational.approximatelyEquals(inputDouble));
assertTrue(
String.format(
"output rational ~ output double, %s %s",
expectedValue, expectedValueDouble),
expectedValue.approximatelyEquals(expectedValueDouble));

// check that the quantity is consistent
String expectedQuantity =
converter.getQuantityFromUnit(inputUnit, false);
assertEquals(
"Input: Quantity consistency check",
expectedQuantity,
quantity);

// TODO handle mixed_unit_identifiers
if (!highMixed_unit_identifiers.isEmpty()) {
warnln("mixed_unit_identifiers not yet checked: " + line);
return;
}
// check output unit, then value
UnitPreference unitPreference =
prefs.getUnitPreference(
inputRational, inputUnit, usage, region);
String actualUnit = unitPreference.unit;
assertEquals("Output unit", expectedOutputUnit, actualUnit);

Rational actualValue =
converter.convert(
inputRational, inputUnit, actualUnit, false);
assertEquals(
"Output numeric value", expectedValue, actualValue);
} catch (Exception e) {
errln(e.getMessage() + "\n\t" + line);
}
});
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}

0 comments on commit 6d1c2e5

Please sign in to comment.