ICU-20568 testConversions: test convertibility of unitsTest.txt test cases.

PR: https://github.com/sffc/icu/pull/39
Commit: 3202693e542e300e235096557777d4892548d676
diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp
index cbfb512..c264e09 100644
--- a/icu4c/source/test/intltest/intltest.cpp
+++ b/icu4c/source/test/intltest/intltest.cpp
@@ -2155,6 +2155,23 @@
     return TRUE;
 }
 
+UBool IntlTest::assertNotEquals(const char* message,
+                                int32_t expectedNot,
+                                int32_t actual) {
+    if (expectedNot == actual) {
+        errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "=0x" + toHex(actual) +
+              "; expected != " + expectedNot);
+        return FALSE;
+    }
+#ifdef VERBOSE_ASSERTIONS
+    else {
+        logln((UnicodeString)("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual) +
+              " != " + expectedNot);
+    }
+#endif
+    return TRUE;
+}
+
 static char ASSERT_BUF[256];
 
 static const char* extractToAssertBuf(const UnicodeString& message) {
@@ -2224,6 +2241,11 @@
                              const std::vector<std::string>& actual) {
     return assertEquals(extractToAssertBuf(message), expected, actual);
 }
+UBool IntlTest::assertNotEquals(const UnicodeString &message,
+                                int32_t expectedNot,
+                                int32_t actual) {
+    return assertNotEquals(extractToAssertBuf(message), expectedNot, actual);
+}
 
 #if !UCONFIG_NO_FORMATTING
 UBool IntlTest::assertEquals(const UnicodeString& message,
diff --git a/icu4c/source/test/intltest/intltest.h b/icu4c/source/test/intltest/intltest.h
index 4ee9b83..59a7679 100644
--- a/icu4c/source/test/intltest/intltest.h
+++ b/icu4c/source/test/intltest/intltest.h
@@ -306,6 +306,7 @@
     UBool assertEquals(const UnicodeString& message, const Formattable& expected,
                        const Formattable& actual);
 #endif
+    UBool assertNotEquals(const char* message, int32_t expectedNot, int32_t actual);
     UBool assertTrue(const UnicodeString& message, UBool condition, UBool quiet=FALSE, UBool possibleDataError=FALSE);
     UBool assertFalse(const UnicodeString& message, UBool condition, UBool quiet=FALSE, UBool possibleDataError=FALSE);
     UBool assertSuccess(const UnicodeString& message, UErrorCode ec);
@@ -320,6 +321,7 @@
     UBool assertEquals(const UnicodeString& message, const UnicodeSet& expected, const UnicodeSet& actual);
     UBool assertEquals(const UnicodeString& message,
         const std::vector<std::string>& expected, const std::vector<std::string>& actual);
+    UBool assertNotEquals(const UnicodeString& message, int32_t expectedNot, int32_t actual);
 
     virtual void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide !
 
diff --git a/icu4c/source/test/intltest/unitstest.cpp b/icu4c/source/test/intltest/unitstest.cpp
index 1f85e88..d3ecf60 100644
--- a/icu4c/source/test/intltest/unitstest.cpp
+++ b/icu4c/source/test/intltest/unitstest.cpp
@@ -67,55 +67,14 @@
         const StringPiece target;
         const UnitsConvertibilityState expectedState;
     } testCases[]{
-        {"meter", "foot", CONVERTIBLE},                                                    //
-        {"kilometer", "foot", CONVERTIBLE},                                                //
-        {"hectare", "square-foot", CONVERTIBLE},                                           //
-        {"kilometer-per-second", "second-per-meter", RECIPROCAL},                          //
-        {"square-meter", "square-foot", CONVERTIBLE},                                      //
-        {"kilometer-per-second", "foot-per-second", CONVERTIBLE},                          //
-        {"square-hectare", "p4-foot", CONVERTIBLE},                                        //
-        {"square-kilometer-per-second", "second-per-square-meter", RECIPROCAL},            //
-        // TODO: Remove the following test cases after hocking up unitsTest.txt.
-        {"g-force", "meter-per-square-second", CONVERTIBLE},                               //
-        {"ohm", "kilogram-square-meter-per-cubic-second-square-ampere", CONVERTIBLE},      //
-        {"electronvolt", "kilogram-square-meter-per-square-second", CONVERTIBLE},          //
-        {"dalton", "kilogram-square-meter-per-square-second", CONVERTIBLE},                //
-        {"joule", "kilogram-square-meter-per-square-second", CONVERTIBLE},                 //
-        {"meter-newton", "kilogram-square-meter-per-square-second", CONVERTIBLE},          //
-        {"foot-pound-force", "kilogram-square-meter-per-square-second", CONVERTIBLE},      //
-        {"calorie", "kilogram-square-meter-per-square-second", CONVERTIBLE},               //
-        {"kilojoule", "kilogram-square-meter-per-square-second", CONVERTIBLE},             //
-        {"british-thermal-unit", "kilogram-square-meter-per-square-second", CONVERTIBLE},  //
-        {"foodcalorie", "kilogram-square-meter-per-square-second", CONVERTIBLE},           //
-        {"kilocalorie", "kilogram-square-meter-per-square-second", CONVERTIBLE},           //
-        {"hour-kilowatt", "kilogram-square-meter-second-per-cubic-second", CONVERTIBLE},   //
-        {"therm-us", "kilogram-square-meter-per-square-second", CONVERTIBLE},              //
-        {"newton", "kilogram-meter-per-square-second", CONVERTIBLE},                       //
-        {"pound-force", "kilogram-meter-per-square-second", CONVERTIBLE},                  //
-        {"hertz", "revolution-per-second", CONVERTIBLE},                                   //
-        {"kilohertz", "revolution-per-second", CONVERTIBLE},                               //
-        {"megahertz", "revolution-per-second", CONVERTIBLE},                               //
-        {"gigahertz", "revolution-per-second", CONVERTIBLE},                               //
-        {"lux", "candela-square-meter-per-square-meter", CONVERTIBLE},                     //
-        {"milliwatt", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},              //
-        {"watt", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},                   //
-        {"horsepower", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},             //
-        {"kilowatt", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},               //
-        {"megawatt", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},               //
-        {"gigawatt", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},               //
-        {"solar-luminosity", "kilogram-square-meter-per-cubic-second", CONVERTIBLE},       //
-        {"pascal", "kilogram-per-meter-square-second", CONVERTIBLE},                       //
-        {"hectopascal", "kilogram-per-meter-square-second", CONVERTIBLE},                  //
-        {"millibar", "kilogram-per-meter-square-second", CONVERTIBLE},                     //
-        {"millimeter-ofhg", "kilogram-meter-per-square-meter-square-second", CONVERTIBLE}, //
-        {"kilopascal", "kilogram-per-meter-square-second", CONVERTIBLE},                   //
-        {"inch-ofhg", "kilogram-meter-per-square-meter-square-second", CONVERTIBLE},       //
-        {"bar", "kilogram-per-meter-square-second", CONVERTIBLE},                          //
-        {"atmosphere", "kilogram-per-meter-square-second", CONVERTIBLE},                   //
-        {"megapascal", "kilogram-per-meter-square-second", CONVERTIBLE},                   //
-        {"ofhg", "kilogram-per-square-meter-square-second", CONVERTIBLE},                  //
-        {"knot", "meter-per-second", CONVERTIBLE},                                         //
-        {"volt", "kilogram-square-meter-per-cubic-second-ampere", CONVERTIBLE},            //
+        {"meter", "foot", CONVERTIBLE},                                         //
+        {"kilometer", "foot", CONVERTIBLE},                                     //
+        {"hectare", "square-foot", CONVERTIBLE},                                //
+        {"kilometer-per-second", "second-per-meter", RECIPROCAL},               //
+        {"square-meter", "square-foot", CONVERTIBLE},                           //
+        {"kilometer-per-second", "foot-per-second", CONVERTIBLE},               //
+        {"square-hectare", "p4-foot", CONVERTIBLE},                             //
+        {"square-kilometer-per-second", "second-per-square-meter", RECIPROCAL}, //
     };
 
     for (const auto &testCase : testCases) {
@@ -265,13 +224,24 @@
     return StringPiece(start, length);
 }
 
+// Used for passing context to unitsTestDataLineFn via u_parseDelimitedFile.
+struct UnitsTestContext {
+    // Provides access to UnitsTest methods like logln.
+    UnitsTest *unitsTest;
+    // Conversion rates: does not take ownership.
+    ConversionRates *conversionRates;
+};
+
 /**
- * Deals with a single data-driven unit test for unit conversions. This
- * UParseLineFn for use by u_parseDelimitedFile is intended for "unitsTest.txt".
+ * WIP(hugovdm): deals with a single data-driven unit test for unit conversions.
+ * This is a UParseLineFn as required by u_parseDelimitedFile.
+ *
+ * context must point at a UnitsTestContext struct.
  */
 void unitsTestDataLineFn(void *context, char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) {
-    if (U_FAILURE(*pErrorCode)) return;
-    UnitsTest* unitsTest = (UnitsTest*)context;
+    if (U_FAILURE(*pErrorCode)) { return; }
+    UnitsTestContext *ctx = (UnitsTestContext *)context;
+    UnitsTest* unitsTest = ctx->unitsTest;
     (void)fieldCount; // unused UParseLineFn variable
     IcuTestErrorCode status(*unitsTest, "unitsTestDatalineFn");
 
@@ -287,10 +257,10 @@
     unum_close(nf);
 
     MeasureUnit sourceUnit = MeasureUnit::forIdentifier(x, status);
-    if (status.errIfFailureAndReset("forIdentifier(\"%.*s\")", x.length(), x.data())) return;
+    if (status.errIfFailureAndReset("forIdentifier(\"%.*s\")", x.length(), x.data())) { return; }
 
     MeasureUnit targetUnit = MeasureUnit::forIdentifier(y, status);
-    if (status.errIfFailureAndReset("forIdentifier(\"%.*s\")", y.length(), y.data())) return;
+    if (status.errIfFailureAndReset("forIdentifier(\"%.*s\")", y.length(), y.data())) { return; }
 
     unitsTest->logln("Quantity (Category): \"%.*s\", "
                      "Expected value of \"1000 %.*s in %.*s\": %f, "
@@ -298,35 +268,29 @@
                      quantity.length(), quantity.data(), x.length(), x.data(), y.length(), y.data(),
                      expected, commentConversionFormula.length(), commentConversionFormula.data());
 
-    // WIP(hugovdm): hook this up to actual tests.
+    // Convertibility:
+    auto convertibility = checkConvertibility(sourceUnit, targetUnit, *ctx->conversionRates, status);
+    if (status.errIfFailureAndReset("checkConvertibility(<%s>, <%s>, ...)", sourceUnit.getIdentifier(),
+                                    targetUnit.getIdentifier())) {
+        return;
+    }
+    CharString msg;
+    msg.append("convertible: ", status)
+        .append(sourceUnit.getIdentifier(), status)
+        .append(" -> ", status)
+        .append(targetUnit.getIdentifier(), status);
+    if (status.errIfFailureAndReset("msg construction")) { return; }
+    unitsTest->assertNotEquals(msg.data(), UNCONVERTIBLE, convertibility);
 
-    // // Convertibility:
-    // MaybeStackVector<MeasureUnit> units;
-    // units.emplaceBack(sourceUnit);
-    // units.emplaceBack(targetUnit);
-    // const auto &conversionRateInfoList = getConversionRatesInfo(units, status);
-    // if (status.errIfFailureAndReset("getConversionRatesInfo(...)")) return;
-
-    // auto actualState = checkUnitsState(sourceUnit, targetUnit, conversionRateInfoList, status);
-    // if (status.errIfFailureAndReset("checkUnitsState(<%s>, <%s>, ...)", sourceUnit.getIdentifier(),
-    //                                 targetUnit.getIdentifier())) {
+    // TODO(hugovdm,younies): the following code can be uncommented (and
+    // fixed) once merged with a UnitConverter branch:
+    // UnitConverter converter(sourceUnit, targetUnit, unitsTest->conversionRates_, status);
+    // if (status.errIfFailureAndReset("constructor: UnitConverter(<%s>, <%s>, status)",
+    //                                 sourceUnit.getIdentifier(), targetUnit.getIdentifier())) {
     //     return;
     // }
-
-    // CharString msg;
-    // msg.append("convertible: ", status)
-    //     .append(sourceUnit.getIdentifier(), status)
-    //     .append(" -> ", status)
-    //     .append(targetUnit.getIdentifier(), status);
-    // if (status.errIfFailureAndReset("msg construction")) return;
-
-    // unitsTest->assertTrue(msg.data(), actualState != UNCONVERTIBLE);
-
-    // TODO(hugovdm,younies): add conversion testing in unitsTestDataLineFn:
-    //
-    // UnitConverter converter(sourceUnit, targetUnit, status);
-    // double got = converter.convert(1000, status);
-    // unitsTest->assertEqualsNear(quantity.data(), expected, got, 0.0001);
+    // double got = converter.convert(1000);
+    // unitsTest->assertEqualsNear(fields[0][0], expected, got, 0.0001);
 }
 
 /**
@@ -349,7 +313,9 @@
     path.appendPathPart("units", errorCode);
     path.appendPathPart(filename, errorCode);
 
-    u_parseDelimitedFile(path.data(), ';', fields, kNumFields, unitsTestDataLineFn, this, errorCode);
+    ConversionRates rates(errorCode);
+    UnitsTestContext ctx = {this, &rates};
+    u_parseDelimitedFile(path.data(), ';', fields, kNumFields, unitsTestDataLineFn, &ctx, errorCode);
     if (errorCode.errIfFailureAndReset("error parsing %s: %s\n", path.data(), u_errorName(errorCode))) {
         return;
     }
diff --git a/icu4c/source/test/testdata/units/unitsTest.txt b/icu4c/source/test/testdata/units/unitsTest.txt
index 2ab615d..31b0e25 100644
--- a/icu4c/source/test/testdata/units/unitsTest.txt
+++ b/icu4c/source/test/testdata/units/unitsTest.txt
@@ -142,7 +142,7 @@
 pressure    ;   millimeter-ofhg ;   kilogram-meter-per-square-meter-square-second   ;   133.322387415 * x   ;   133322.4
 pressure    ;   kilopascal  ;   kilogram-per-meter-square-second    ;   1,000 * x   ;   1000000.0
 pressure    ;   inch-ofhg   ;   kilogram-meter-per-square-meter-square-second   ;   3,386.388640341 * x ;   3386389.0
-#WIP(MeasureUnit parsing bug)#pressure    ;   pound-force-per-square-inch ;   kilogram-meter-per-square-meter-square-second   ;   111,205,540.3815125/16,129 * x  ;   6894757.0
+pressure    ;   pound-force-per-square-inch ;   kilogram-meter-per-square-meter-square-second   ;   111,205,540.3815125/16,129 * x  ;   6894757.0
 pressure    ;   bar ;   kilogram-per-meter-square-second    ;   100,000 * x ;   1.0E8
 pressure    ;   atmosphere  ;   kilogram-per-meter-square-second    ;   101,325 * x ;   1.01325E8
 pressure    ;   megapascal  ;   kilogram-per-meter-square-second    ;   1,000,000 * x   ;   1.0E9