Skip to content

Commit

Permalink
ICU-22781 Adding support for constant denominators
Browse files Browse the repository at this point in the history
See #3336
  • Loading branch information
younies authored and Squash Bot committed Jan 20, 2025
1 parent 2c5e021 commit 88a6fc1
Show file tree
Hide file tree
Showing 3 changed files with 453 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.text.FieldPosition;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -49,6 +50,7 @@
import com.ibm.icu.util.TimeUnit;
import com.ibm.icu.util.TimeUnitAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.MeasureUnit.Complexity;

/**
* This file contains regular unit tests.
Expand Down Expand Up @@ -1145,10 +1147,12 @@ public boolean hasSameBehavior(Object a, Object b)
}
System.out.println("MeasureFormatHandler.hasSameBehavior fails:");
if (!getLocaleEqual) {
System.out.println("- getLocale equality fails: old a1: " + a1.getLocale().getName() + "; test b1: " + b1.getLocale().getName());
System.out.println("- getLocale equality fails: old a1: " + a1.getLocale().getName() + "; test b1: "
+ b1.getLocale().getName());
}
if (!getWidthEqual) {
System.out.println("- getWidth equality fails: old a1: " + a1.getWidth().name() + "; test b1: " + b1.getWidth().name());
System.out.println("- getWidth equality fails: old a1: " + a1.getWidth().name() + "; test b1: "
+ b1.getWidth().name());
}
if (!numFmtHasSameBehavior) {
System.out.println("- getNumberFormat hasSameBehavior fails");
Expand Down Expand Up @@ -1311,6 +1315,110 @@ class TestCase {
null, MeasureUnit.forIdentifier(""));
}

@Test
public void TestAcceptableConstantDenominator() {
class ConstantDenominatorTestCase {
String identifier;
long expectedConstantDenominator;

ConstantDenominatorTestCase(String identifier, long expectedConstantDenominator) {
this.identifier = identifier;
this.expectedConstantDenominator = expectedConstantDenominator;
}
}

List<ConstantDenominatorTestCase> testCases = Arrays.asList(
new ConstantDenominatorTestCase("meter-per-1000", 1000),
new ConstantDenominatorTestCase("liter-per-1000-kiloliter", 1000),
new ConstantDenominatorTestCase("liter-per-kilometer", 0),
new ConstantDenominatorTestCase("second-per-1000-minute", 1000),
new ConstantDenominatorTestCase("gram-per-1000-kilogram", 1000),
new ConstantDenominatorTestCase("meter-per-100", 100),
// Test for constant denominators that are powers of 10
new ConstantDenominatorTestCase("portion-per-1", 1),
new ConstantDenominatorTestCase("portion-per-10", 10),
new ConstantDenominatorTestCase("portion-per-100", 100),
new ConstantDenominatorTestCase("portion-per-1000", 1000),
new ConstantDenominatorTestCase("portion-per-10000", 10000),
new ConstantDenominatorTestCase("portion-per-100000", 100000),
new ConstantDenominatorTestCase("portion-per-1000000", 1000000),
new ConstantDenominatorTestCase("portion-per-10000000", 10000000),
new ConstantDenominatorTestCase("portion-per-100000000", 100000000),
new ConstantDenominatorTestCase("portion-per-1000000000", 1000000000),
new ConstantDenominatorTestCase("portion-per-10000000000", 10000000000L),
new ConstantDenominatorTestCase("portion-per-100000000000", 100000000000L),
new ConstantDenominatorTestCase("portion-per-1000000000000", 1000000000000L),
new ConstantDenominatorTestCase("portion-per-10000000000000", 10000000000000L),
new ConstantDenominatorTestCase("portion-per-100000000000000", 100000000000000L),
new ConstantDenominatorTestCase("portion-per-1000000000000000", 1000000000000000L),
new ConstantDenominatorTestCase("portion-per-10000000000000000", 10000000000000000L),
new ConstantDenominatorTestCase("portion-per-100000000000000000", 100000000000000000L),
new ConstantDenominatorTestCase("portion-per-1000000000000000000", 1000000000000000000L),
// Test for constant denominators that are represented as scientific notation
// numbers.
new ConstantDenominatorTestCase("portion-per-1e9", 1000000000L),
new ConstantDenominatorTestCase("portion-per-1E9", 1000000000L),
new ConstantDenominatorTestCase("portion-per-10e9", 10000000000L),
new ConstantDenominatorTestCase("portion-per-10E9", 10000000000L),
new ConstantDenominatorTestCase("portion-per-1e10", 10000000000L),
new ConstantDenominatorTestCase("portion-per-1E10", 10000000000L),
new ConstantDenominatorTestCase("portion-per-1e3-kilometer", 1000),
// Test for constant denominators that are randomely selected.
new ConstantDenominatorTestCase("liter-per-12345-kilometer", 12345),
new ConstantDenominatorTestCase("per-1000-kilometer", 1000),
new ConstantDenominatorTestCase("liter-per-1000-kiloliter", 1000),
// Test for constant denominators that gives 0.
new ConstantDenominatorTestCase("meter", 0),
new ConstantDenominatorTestCase("meter-per-second", 0),
new ConstantDenominatorTestCase("meter-per-square-second", 0),
// NOTE: The following constant denominator should be 0. However, since
// `100-kilometer` is treated as a unit in CLDR,
// the unit does not have a constant denominator.
// This issue should be addressed in CLDR.
new ConstantDenominatorTestCase("meter-per-100-kilometer", 0),
// NOTE: the following CLDR identifier should be invalid, but because
// `100-kilometer` is considered a unit in CLDR,
// one `100` will be considered as a unit constant denominator and the other
// `100` will be considered part of the unit.
// This issue should be addressed in CLDR.
new ConstantDenominatorTestCase("meter-per-100-100-kilometer", 100));

for (ConstantDenominatorTestCase testCase : testCases) {
MeasureUnit unit = MeasureUnit.forIdentifier(testCase.identifier);
assertEquals("Constant denominator for " + testCase.identifier, testCase.expectedConstantDenominator,
unit.getConstantDenominator());
assertTrue("Complexity for " + testCase.identifier,
unit.getComplexity() == Complexity.COMPOUND || unit.getComplexity() == Complexity.SINGLE);
}
}

@Test
public void TestNonAcceptableConstantDenominator() {
class NonAcceptableConstantDenominatorTestCase {
String identifier;

NonAcceptableConstantDenominatorTestCase(String identifier) {
this.identifier = identifier;
}
}

List<NonAcceptableConstantDenominatorTestCase> testCases = Arrays.asList(
new NonAcceptableConstantDenominatorTestCase("meter-and-second"),
new NonAcceptableConstantDenominatorTestCase("meter-per--20--second"),
new NonAcceptableConstantDenominatorTestCase("meter-per-1000-1e9-second"),
new NonAcceptableConstantDenominatorTestCase("meter-per-1e20-second"));

for (NonAcceptableConstantDenominatorTestCase testCase : testCases) {
try {
MeasureUnit unit = MeasureUnit.forIdentifier(testCase.identifier);
unit.getConstantDenominator();
Assert.fail("An IllegalArgumentException must be thrown");
} catch (Exception e) {
continue;
}
}
}

@Test
public void TestInvalidIdentifiers() {
final String inputs[] = {
Expand Down Expand Up @@ -1348,6 +1456,17 @@ public void TestInvalidIdentifiers() {

// Compound units not supported in mixed units yet. TODO(CLDR-13701).
"kilonewton-meter-and-newton-meter",

// Invalid units because of invalid constant denominator
"per-1000",
"meter-per-1000-1000",
"meter-per-1000-second-1000-kilometer",
"1000-meter",
"meter-1000",
"meter-per-1000-1000",
"meter-per-1000-second-1000-kilometer",
"per-1000-and-per-1000",

};

for (String input : inputs) {
Expand Down
Loading

0 comments on commit 88a6fc1

Please sign in to comment.