]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/numfmtst.cpp
ICU-57166.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
index 2f71c908d9b16ebdbc82ac375bca0647fef3a254..d877f3e443d7e5c1ac07744efb3746e8768326f1 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT:
- * Copyright (c) 1997-2010, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 /* Modification History:
@@ -15,6 +15,7 @@
 #include "numfmtst.h"
 #include "unicode/dcfmtsym.h"
 #include "unicode/decimfmt.h"
+#include "unicode/localpointer.h"
 #include "unicode/ucurr.h"
 #include "unicode/ustring.h"
 #include "unicode/measfmt.h"
 #include <float.h>
 #include <string.h>
 #include <stdlib.h>
+#include "cmemory.h"
 #include "cstring.h"
 #include "unicode/numsys.h"
+#include "fmtableimp.h"
+#include "numberformattesttuple.h"
+#include "datadrivennumberformattestsuite.h"
+#include "unicode/msgfmt.h"
+
+class NumberFormatTestDataDriven : public DataDrivenNumberFormatTestSuite {
+protected:
+UBool isFormatPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status);
+UBool isToPatternPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status);
+UBool isParsePass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status);
+UBool isParseCurrencyPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status);
+};
+
+static DigitList &strToDigitList(
+        const UnicodeString &str,
+        DigitList &digitList,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return digitList;
+    }
+    if (str == "NaN") {
+        digitList.set(uprv_getNaN());
+        return digitList;
+    }
+    if (str == "-Inf") {
+        digitList.set(-1*uprv_getInfinity());
+        return digitList;
+    }
+    if (str == "Inf") {
+        digitList.set(uprv_getInfinity());
+        return digitList;
+    }
+    CharString formatValue;
+    formatValue.appendInvariantChars(str, status);
+    digitList.set(StringPiece(formatValue.data()), status, 0);
+    return digitList;
+}
+
+static UnicodeString &format(
+        const DecimalFormat &fmt,
+        const DigitList &digitList,
+        UnicodeString &appendTo,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return appendTo;
+    }
+    FieldPosition fpos(FieldPosition::DONT_CARE);
+    return fmt.format(digitList, appendTo, fpos, status);
+}
+
+template<class T>
+static UnicodeString &format(
+        const DecimalFormat &fmt,
+        T value,
+        UnicodeString &appendTo,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return appendTo;
+    }
+    FieldPosition fpos(FieldPosition::DONT_CARE);
+    return fmt.format(value, appendTo, fpos, status);
+}
+
+static void adjustDecimalFormat(
+        const NumberFormatTestTuple &tuple,
+        DecimalFormat &fmt,
+        UnicodeString &appendErrorMessage) {
+    if (tuple.minIntegerDigitsFlag) {
+        fmt.setMinimumIntegerDigits(tuple.minIntegerDigits);
+    }
+    if (tuple.maxIntegerDigitsFlag) {
+        fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits);
+    }
+    if (tuple.minFractionDigitsFlag) {
+        fmt.setMinimumFractionDigits(tuple.minFractionDigits);
+    }
+    if (tuple.maxFractionDigitsFlag) {
+        fmt.setMaximumFractionDigits(tuple.maxFractionDigits);
+    }
+    if (tuple.currencyFlag) {
+        UErrorCode status = U_ZERO_ERROR;
+        UnicodeString currency(tuple.currency);
+        const UChar *terminatedCurrency = currency.getTerminatedBuffer();
+        fmt.setCurrency(terminatedCurrency, status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("Error setting currency.");
+        }
+    }
+    if (tuple.minGroupingDigitsFlag) {
+        fmt.setMinimumGroupingDigits(tuple.minGroupingDigits);
+    }
+    if (tuple.useSigDigitsFlag) {
+        fmt.setSignificantDigitsUsed(tuple.useSigDigits != 0);
+    }
+    if (tuple.minSigDigitsFlag) {
+        fmt.setMinimumSignificantDigits(tuple.minSigDigits);
+    }
+    if (tuple.maxSigDigitsFlag) {
+        fmt.setMaximumSignificantDigits(tuple.maxSigDigits);
+    }
+    if (tuple.useGroupingFlag) {
+        fmt.setGroupingUsed(tuple.useGrouping != 0);
+    }
+    if (tuple.multiplierFlag) {
+        fmt.setMultiplier(tuple.multiplier);
+    }
+    if (tuple.roundingIncrementFlag) {
+        fmt.setRoundingIncrement(tuple.roundingIncrement);
+    }
+    if (tuple.formatWidthFlag) {
+        fmt.setFormatWidth(tuple.formatWidth);
+    }
+    if (tuple.padCharacterFlag) {
+        fmt.setPadCharacter(tuple.padCharacter);
+    }
+    if (tuple.useScientificFlag) {
+        fmt.setScientificNotation(tuple.useScientific != 0);
+    }
+    if (tuple.groupingFlag) {
+        fmt.setGroupingSize(tuple.grouping);
+    }
+    if (tuple.grouping2Flag) {
+        fmt.setSecondaryGroupingSize(tuple.grouping2);
+    }
+    if (tuple.roundingModeFlag) {
+        fmt.setRoundingMode(tuple.roundingMode);
+    }
+    if (tuple.currencyUsageFlag) {
+        UErrorCode status = U_ZERO_ERROR;
+        fmt.setCurrencyUsage(tuple.currencyUsage, &status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("CurrencyUsage: error setting.");
+        }
+    }
+    if (tuple.minimumExponentDigitsFlag) {
+        fmt.setMinimumExponentDigits(tuple.minimumExponentDigits);
+    }
+    if (tuple.exponentSignAlwaysShownFlag) {
+        fmt.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
+    }
+    if (tuple.decimalSeparatorAlwaysShownFlag) {
+        fmt.setDecimalSeparatorAlwaysShown(
+                tuple.decimalSeparatorAlwaysShown != 0);
+    }
+    if (tuple.padPositionFlag) {
+        fmt.setPadPosition(tuple.padPosition);
+    }
+    if (tuple.positivePrefixFlag) {
+        fmt.setPositivePrefix(tuple.positivePrefix);
+    }
+    if (tuple.positiveSuffixFlag) {
+        fmt.setPositiveSuffix(tuple.positiveSuffix);
+    }
+    if (tuple.negativePrefixFlag) {
+        fmt.setNegativePrefix(tuple.negativePrefix);
+    }
+    if (tuple.negativeSuffixFlag) {
+        fmt.setNegativeSuffix(tuple.negativeSuffix);
+    }
+    if (tuple.localizedPatternFlag) {
+        UErrorCode status = U_ZERO_ERROR;
+        fmt.applyLocalizedPattern(tuple.localizedPattern, status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("Error setting localized pattern.");
+        }
+    }
+    fmt.setLenient(NFTT_GET_FIELD(tuple, lenient, 1) != 0);
+    if (tuple.parseIntegerOnlyFlag) {
+        fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
+    }
+    if (tuple.decimalPatternMatchRequiredFlag) {
+        fmt.setDecimalPatternMatchRequired(
+                tuple.decimalPatternMatchRequired != 0);
+    }
+    if (tuple.parseNoExponentFlag) {
+        UErrorCode status = U_ZERO_ERROR;
+        fmt.setAttribute(
+                UNUM_PARSE_NO_EXPONENT,
+                tuple.parseNoExponent,
+                status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("Error setting parse no exponent flag.");
+        }
+    }
+}
+
+static DecimalFormat *newDecimalFormat(
+        const Locale &locale,
+        const UnicodeString &pattern,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    LocalPointer<DecimalFormatSymbols> symbols(
+            new DecimalFormatSymbols(locale, status), status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    UParseError perror;
+    LocalPointer<DecimalFormat> result(new DecimalFormat(
+            pattern, symbols.getAlias(), perror, status), status);
+    if (!result.isNull()) {
+        symbols.orphan();
+    }
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    return result.orphan();
+}
+
+static DecimalFormat *newDecimalFormat(
+        const NumberFormatTestTuple &tuple,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    Locale en("en");
+    return newDecimalFormat(
+            NFTT_GET_FIELD(tuple, locale, en),
+            NFTT_GET_FIELD(tuple, pattern, "0"),
+            status);
+}
+
+UBool NumberFormatTestDataDriven::isFormatPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error creating DecimalFormat.");
+        return FALSE;
+    }
+    adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+    if (appendErrorMessage.length() > 0) {
+        return FALSE;
+    }
+    DigitList digitList;
+    strToDigitList(tuple.format, digitList, status);
+    {
+        UnicodeString appendTo;
+        format(*fmtPtr, digitList, appendTo, status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("Error formatting.");
+            return FALSE;
+        }
+        if (appendTo != tuple.output) {
+            appendErrorMessage.append(
+                    UnicodeString("Expected: ") + tuple.output + ", got: " + appendTo);
+            return FALSE;
+        }
+    }
+    double doubleVal = digitList.getDouble();
+    {
+        UnicodeString appendTo;
+        format(*fmtPtr, doubleVal, appendTo, status);
+        if (U_FAILURE(status)) {
+            appendErrorMessage.append("Error formatting.");
+            return FALSE;
+        }
+        if (appendTo != tuple.output) {
+            appendErrorMessage.append(
+                    UnicodeString("double Expected: ") + tuple.output + ", got: " + appendTo);
+            return FALSE;
+        }
+    }
+    if (!uprv_isNaN(doubleVal) && !uprv_isInfinite(doubleVal) && doubleVal == uprv_floor(doubleVal)) {
+        int64_t intVal = digitList.getInt64();
+        {
+            UnicodeString appendTo;
+            format(*fmtPtr, intVal, appendTo, status);
+            if (U_FAILURE(status)) {
+                appendErrorMessage.append("Error formatting.");
+                return FALSE;
+            }
+            if (appendTo != tuple.output) {
+                appendErrorMessage.append(
+                        UnicodeString("int64 Expected: ") + tuple.output + ", got: " + appendTo);
+                return FALSE;
+            }
+        }
+    }
+    return TRUE;
+}
+
+UBool NumberFormatTestDataDriven::isToPatternPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error creating DecimalFormat.");
+        return FALSE;
+    }
+    adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+    if (appendErrorMessage.length() > 0) {
+        return FALSE;
+    }
+    if (tuple.toPatternFlag) {
+        UnicodeString actual;
+        fmtPtr->toPattern(actual);
+        if (actual != tuple.toPattern) {
+            appendErrorMessage.append(
+                    UnicodeString("Expected: ") + tuple.toPattern + ", got: " + actual + ". ");
+        }
+    }
+    if (tuple.toLocalizedPatternFlag) {
+        UnicodeString actual;
+        fmtPtr->toLocalizedPattern(actual);
+        if (actual != tuple.toLocalizedPattern) {
+            appendErrorMessage.append(
+                    UnicodeString("Expected: ") + tuple.toLocalizedPattern + ", got: " + actual + ". ");
+        }
+    }
+    return appendErrorMessage.length() == 0;
+}
+
+UBool NumberFormatTestDataDriven::isParsePass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error creating DecimalFormat.");
+        return FALSE;
+    }
+    adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+    if (appendErrorMessage.length() > 0) {
+        return FALSE;
+    }
+    Formattable result;
+    ParsePosition ppos;
+    fmtPtr->parse(tuple.parse, result, ppos);
+    if (ppos.getIndex() == 0) {
+        if (tuple.output != "fail") {
+            appendErrorMessage.append("Parse failed but was expected to succeed.");
+            return FALSE;
+        }
+        return TRUE;
+    }
+    UnicodeString resultStr(UnicodeString::fromUTF8(result.getDecimalNumber(status)));
+    if (tuple.output == "fail") {
+        appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
+        return FALSE;
+    }
+    DigitList expected;
+    strToDigitList(tuple.output, expected, status);
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error parsing.");
+        return FALSE;
+    }
+    if (expected != *result.getDigitList()) {
+        appendErrorMessage.append(
+                    UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+UBool NumberFormatTestDataDriven::isParseCurrencyPass(
+        const NumberFormatTestTuple &tuple,
+        UnicodeString &appendErrorMessage,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error creating DecimalFormat.");
+        return FALSE;
+    }
+    adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+    if (appendErrorMessage.length() > 0) {
+        return FALSE;
+    }
+    ParsePosition ppos;
+    LocalPointer<CurrencyAmount> currAmt(
+            fmtPtr->parseCurrency(tuple.parse, ppos));
+    if (ppos.getIndex() == 0) {
+        if (tuple.output != "fail") {
+            appendErrorMessage.append("Parse failed but was expected to succeed.");
+            return FALSE;
+        }
+        return TRUE;
+    }
+    UnicodeString currStr(currAmt->getISOCurrency());
+    Formattable resultFormattable(currAmt->getNumber());
+    UnicodeString resultStr(UnicodeString::fromUTF8(resultFormattable.getDecimalNumber(status)));
+    if (tuple.output == "fail") {
+        appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
+        return FALSE;
+    }
+    DigitList expected;
+    strToDigitList(tuple.output, expected, status);
+    if (U_FAILURE(status)) {
+        appendErrorMessage.append("Error parsing.");
+        return FALSE;
+    }
+    if (expected != *currAmt->getNumber().getDigitList()) {
+        appendErrorMessage.append(
+                    UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
+        return FALSE;
+    }
+    if (currStr != tuple.outputCurrency) {
+        appendErrorMessage.append(UnicodeString(
+                "Expected currency: ") + tuple.outputCurrency + ", got: " + currStr + ". ");
+        return FALSE;
+    }
+    return TRUE;
+}
 
 //#define NUMFMTST_CACHE_DEBUG 1
-#ifdef NUMFMTST_CACHE_DEBUG
 #include "stdio.h" /* for sprintf */
-#endif
-
 // #include "iostream"   // for cout
 
 //#define NUMFMTST_DEBUG 1
 
-
 static const UChar EUR[] = {69,85,82,0}; // "EUR"
 static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
 
+
 // *****************************************************************************
 // class NumberFormatTest
 // *****************************************************************************
 
-#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
-
 #define CHECK(status,str) if (U_FAILURE(status)) { errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; }
 #define CHECK_DATA(status,str) if (U_FAILURE(status)) { dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; }
 
 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
 {
-    // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
-    switch (index) {
-        CASE(0,TestCurrencySign);
-        CASE(1,TestCurrency);
-        CASE(2,TestParse);
-        CASE(3,TestRounding487);
-        CASE(4,TestQuotes);
-        CASE(5,TestExponential);
-        CASE(6,TestPatterns);
-
-        // Upgrade to alphaWorks - liu 5/99
-        CASE(7,TestExponent);
-        CASE(8,TestScientific);
-        CASE(9,TestPad);
-        CASE(10,TestPatterns2);
-        CASE(11,TestSecondaryGrouping);
-        CASE(12,TestSurrogateSupport);
-        CASE(13,TestAPI);
-
-        CASE(14,TestCurrencyObject);
-        CASE(15,TestCurrencyPatterns);
-        //CASE(16,TestDigitList);
-        CASE(16,TestWhiteSpaceParsing);
-        CASE(17,TestComplexCurrency);  // This test removed because CLDR no longer uses choice formats in currency symbols.
-        CASE(18,TestRegCurrency);
-        CASE(19,TestSymbolsWithBadLocale);
-        CASE(20,TestAdoptDecimalFormatSymbols);
-
-        CASE(21,TestScientific2);
-        CASE(22,TestScientificGrouping);
-        CASE(23,TestInt64);
-
-        CASE(24,TestPerMill);
-        CASE(25,TestIllegalPatterns);
-        CASE(26,TestCases);
-
-        CASE(27,TestCurrencyNames);
-        CASE(28,TestCurrencyAmount);
-        CASE(29,TestCurrencyUnit);
-        CASE(30,TestCoverage);
-        CASE(31,TestJB3832);
-        CASE(32,TestHost);
-        CASE(33,TestHostClone);
-        CASE(34,TestCurrencyFormat);
-        CASE(35,TestRounding);
-        CASE(36,TestNonpositiveMultiplier);
-        CASE(37,TestNumberingSystems);
-        CASE(38,TestSpaceParsing);
-        CASE(39,TestMultiCurrencySign);
-        CASE(40,TestCurrencyFormatForMixParsing);
-        CASE(41,TestDecimalFormatCurrencyParse);
-        CASE(42,TestCurrencyIsoPluralFormat);
-        CASE(43,TestCurrencyParsing);
-        CASE(44,TestParseCurrencyInUCurr);
-        CASE(45,TestFormatAttributes);
-        CASE(46,TestFieldPositionIterator);
-        CASE(47,TestDecimal);
-        CASE(48,TestCurrencyFractionDigits);
-        CASE(49,TestExponentParse); 
-        CASE(50,TestLenientParse);
-        default: name = ""; break;
-    }
+  TESTCASE_AUTO_BEGIN;
+  TESTCASE_AUTO(TestCurrencySign);
+  TESTCASE_AUTO(TestCurrency);
+  TESTCASE_AUTO(TestParse);
+  TESTCASE_AUTO(TestRounding487);
+  TESTCASE_AUTO(TestQuotes);
+  TESTCASE_AUTO(TestExponential);
+  TESTCASE_AUTO(TestPatterns);
+
+  // Upgrade to alphaWorks - liu 5/99
+  TESTCASE_AUTO(TestExponent);
+  TESTCASE_AUTO(TestScientific);
+  TESTCASE_AUTO(TestPad);
+  TESTCASE_AUTO(TestPatterns2);
+  TESTCASE_AUTO(TestSecondaryGrouping);
+  TESTCASE_AUTO(TestSurrogateSupport);
+  TESTCASE_AUTO(TestAPI);
+
+  TESTCASE_AUTO(TestCurrencyObject);
+  TESTCASE_AUTO(TestCurrencyPatterns);
+  //TESTCASE_AUTO(TestDigitList);
+  TESTCASE_AUTO(TestWhiteSpaceParsing);
+  TESTCASE_AUTO(TestComplexCurrency);  // This test removed because CLDR no longer uses choice formats in currency symbols.
+  TESTCASE_AUTO(TestRegCurrency);
+  TESTCASE_AUTO(TestSymbolsWithBadLocale);
+  TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
+
+  TESTCASE_AUTO(TestScientific2);
+  TESTCASE_AUTO(TestScientificGrouping);
+  TESTCASE_AUTO(TestInt64);
+
+  TESTCASE_AUTO(TestPerMill);
+  TESTCASE_AUTO(TestIllegalPatterns);
+  TESTCASE_AUTO(TestCases);
+
+  TESTCASE_AUTO(TestCurrencyNames);
+  TESTCASE_AUTO(TestCurrencyAmount);
+  TESTCASE_AUTO(TestCurrencyUnit);
+  TESTCASE_AUTO(TestCoverage);
+  TESTCASE_AUTO(TestJB3832);
+  TESTCASE_AUTO(TestHost);
+  TESTCASE_AUTO(TestHostClone);
+  TESTCASE_AUTO(TestCurrencyFormat);
+  TESTCASE_AUTO(TestRounding);
+  TESTCASE_AUTO(TestNonpositiveMultiplier);
+  TESTCASE_AUTO(TestNumberingSystems);
+  TESTCASE_AUTO(TestSpaceParsing);
+  TESTCASE_AUTO(TestMultiCurrencySign);
+  TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
+  TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
+  TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
+  TESTCASE_AUTO(TestCurrencyParsing);
+  TESTCASE_AUTO(TestParseCurrencyInUCurr);
+  TESTCASE_AUTO(TestFormatAttributes);
+  TESTCASE_AUTO(TestFieldPositionIterator);
+  TESTCASE_AUTO(TestDecimal);
+  TESTCASE_AUTO(TestCurrencyFractionDigits);
+  TESTCASE_AUTO(TestExponentParse); 
+  TESTCASE_AUTO(TestExplicitParents); 
+  TESTCASE_AUTO(TestLenientParse);
+  TESTCASE_AUTO(TestAvailableNumberingSystems);
+  TESTCASE_AUTO(TestRoundingPattern);
+  TESTCASE_AUTO(Test9087);
+  TESTCASE_AUTO(TestFormatFastpaths);
+  TESTCASE_AUTO(TestFormattableSize);
+  TESTCASE_AUTO(TestUFormattable);
+  TESTCASE_AUTO(TestSignificantDigits);
+  TESTCASE_AUTO(TestShowZero);
+  TESTCASE_AUTO(TestCompatibleCurrencies);
+  TESTCASE_AUTO(TestBug9936);
+  TESTCASE_AUTO(TestParseNegativeWithFaLocale);
+  TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
+  TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
+  TESTCASE_AUTO(TestParseSignsAndMarks);
+  TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
+  TESTCASE_AUTO(Test10468ApplyPattern);
+  TESTCASE_AUTO(TestRoundingScientific10542);
+  TESTCASE_AUTO(TestZeroScientific10547);
+  TESTCASE_AUTO(TestAccountingCurrency);
+  TESTCASE_AUTO(TestEquality);
+  TESTCASE_AUTO(TestCurrencyUsage);
+  TESTCASE_AUTO(TestNumberFormatTestTuple);
+  TESTCASE_AUTO(TestDataDriven);
+  TESTCASE_AUTO(TestDoubleLimit11439);
+  TESTCASE_AUTO(TestFastPathConsistent11524);
+  TESTCASE_AUTO(TestGetAffixes);
+  TESTCASE_AUTO(TestToPatternScientific11648);
+  TESTCASE_AUTO(TestBenchmark);
+  TESTCASE_AUTO(TestCtorApplyPatternDifference);
+  TESTCASE_AUTO(TestFractionalDigitsForCurrency);
+  TESTCASE_AUTO(TestFormatCurrencyPlural);
+  TESTCASE_AUTO(Test11868);
+  TESTCASE_AUTO(Test10727_RoundingZero);
+  TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
+  TESTCASE_AUTO(Test11475_signRecognition);
+  TESTCASE_AUTO(Test11640_getAffixes);
+  TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
+  TESTCASE_AUTO_END;
 }
 
 // -------------------------------------
@@ -156,18 +619,19 @@ NumberFormatTest::TestAPI(void)
     }
 
     ParsePosition ppos;
-    test->parseCurrency("",bla,ppos);
-    if(U_FAILURE(status)) {
-        errln("Problems accessing the parseCurrency function for NumberFormat");
+    LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
+    // old test for (U_FAILURE(status)) was bogus here, method does not set status!
+    if (ppos.getIndex()) {
+        errln("Parsed empty string as currency");
     }
 
     delete test;
   }
 }
 
-class StubNumberForamt :public NumberFormat{
+class StubNumberFormat :public NumberFormat{
 public:
-    StubNumberForamt(){};
+    StubNumberFormat(){};
     virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
         return appendTo;
     }
@@ -195,7 +659,7 @@ public:
 
 void
 NumberFormatTest::TestCoverage(void){
-    StubNumberForamt stub;
+    StubNumberFormat stub;
     UnicodeString agent("agent");
     FieldPosition pos;
     int64_t num = 4;
@@ -213,7 +677,7 @@ NumberFormatTest::TestPatterns(void)
     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
 
     const char* pat[]    = { "#.#", "#.", ".#", "#" };
-    int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
+    int32_t pat_length = UPRV_LENGTHOF(pat);
     const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
     const char* num[]    = { "0",   "0.", ".0", "0" };
     for (int32_t i=0; i<pat_length; ++i)
@@ -270,7 +734,7 @@ NumberFormatTest::TestExponential(void)
     DecimalFormatSymbols sym(Locale::getUS(), status);
     if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
     const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]"  };
-    int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
+    int32_t pat_length = UPRV_LENGTHOF(pat);
 
 // The following #if statements allow this test to be built and run on
 // platforms that do not have standard IEEE numerics.  For example,
@@ -282,7 +746,7 @@ NumberFormatTest::TestExponential(void)
 
 #if DBL_MAX_10_EXP > 300
     double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
-    int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
+    int32_t val_length = UPRV_LENGTHOF(val);
     const char* valFormat[] =
     {
         // 0.####E0
@@ -303,7 +767,7 @@ NumberFormatTest::TestExponential(void)
     };
 #elif DBL_MAX_10_EXP > 70
     double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
-    int32_t val_length = sizeof(val) / sizeof(val[0]);
+    int32_t val_length = UPRV_LENGTHOF(val);
     char* valFormat[] =
     {
         // 0.####E0
@@ -332,7 +796,7 @@ NumberFormatTest::TestExponential(void)
 #endif
 
     int32_t lval[] = { 0, -1, 1, 123456789 };
-    int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
+    int32_t lval_length = UPRV_LENGTHOF(lval);
     const char* lvalFormat[] =
     {
         // 0.####E0
@@ -376,7 +840,7 @@ NumberFormatTest::TestExponential(void)
                 a = af.getLong();
             else if (af.getType() == Formattable::kDouble) {
                 a = af.getDouble();
-#if defined(OS390) || defined(OS400)
+#if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
                 // S/390 will show a failure like this:
                 //| -3.141592652999999e-271 -format-> -3.1416E-271
                 //|                          -parse-> -3.1416e-271
@@ -497,6 +961,10 @@ void
 NumberFormatTest::TestInt64() {
     UErrorCode status = U_ZERO_ERROR;
     DecimalFormat fmt("#.#E0",status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        return;
+    }
     fmt.setMaximumFractionDigits(20);
     if (U_SUCCESS(status)) {
         expect(fmt, (Formattable)(int64_t)0, "0E0");
@@ -689,15 +1157,15 @@ NumberFormatTest::escape(UnicodeString& s)
 // -------------------------------------
 static const char* testCases[][2]= {
      /* locale ID */  /* expected */
-    {"ca_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+    {"ca_ES_PREEURO", "\\u20A7\\u00A01.150" },
     {"de_LU_PREEURO", "1,150\\u00A0F" },
     {"el_GR_PREEURO", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
-    {"en_BE_PREEURO", "1.150,50\\u00A0BF" },
-    {"es_ES_PREEURO", "\\u20A7\\u00A01.150" },
-    {"eu_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+    {"en_BE_PREEURO", "1.150,50\\u00A0BEF" },
+    {"es_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+    {"eu_ES_PREEURO", "\\u20A7\\u00A01.150" },
     {"gl_ES_PREEURO", "1.150\\u00A0\\u20A7" },
-    {"it_IT_PREEURO", "IT\\u20A4\\u00A01.150" },
-    {"pt_PT_PREEURO", "1,150$50\\u00A0Esc."},
+    {"it_IT_PREEURO", "ITL\\u00A01.150" },
+    {"pt_PT_PREEURO", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
     {"en_US@currency=JPY", "\\u00A51,150"},
     {"en_US@currency=jpy", "\\u00A51,150"},
     {"en-US-u-cu-jpy", "\\u00A51,150"}
@@ -723,6 +1191,7 @@ NumberFormatTest::TestCurrency(void)
     s.truncate(0);
     char loc[256]={0};
     int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
+    (void)len;  // Suppress unused variable warning.
     currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
     currencyFmt->format(1.50, s);
     logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
@@ -740,7 +1209,7 @@ NumberFormatTest::TestCurrency(void)
     if (U_FAILURE(status))
         errln((UnicodeString)"FAIL: Status " + (int32_t)status);
 
-    for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
+    for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
         status = U_ZERO_ERROR;
         const char *localeID = testCases[i][0];
         UnicodeString expected(testCases[i][1], -1, US_INV);
@@ -793,7 +1262,7 @@ void NumberFormatTest::TestCurrencyObject() {
                    1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
 
     expectCurrency(*fmt, Locale("fr", "CH", ""),
-                   1234.56, "CHF1,234.55"); // 0.05 rounding
+                   1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
 
     expectCurrency(*fmt, Locale::getUS(),
                    1234.56, "$1,234.56");
@@ -810,10 +1279,10 @@ void NumberFormatTest::TestCurrencyObject() {
     expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
 
     expectCurrency(*fmt, Locale::getJapan(),
-                   1234.56, CharsToUnicodeString("1 235 \\u00A5JP")); // Yen
+                   1234.56, CharsToUnicodeString("1 235 JPY")); // Yen
 
     expectCurrency(*fmt, Locale("fr", "CH", ""),
-                   1234.56, "1 234,55 CHF"); // 0.05 rounding
+                   1234.56, "1 234,56 CHF"); // no more 0.05 rounding here, see cldrbug 5548
 
     expectCurrency(*fmt, Locale::getUS(),
                    1234.56, "1 234,56 $US");
@@ -836,9 +1305,7 @@ NumberFormatTest::TestParse(void)
     UnicodeString arg("0");
     DecimalFormat* format = new DecimalFormat("00", status);
     //try {
-        Formattable n;
-
-        format->parse(arg, n, status);
+        Formattable n; format->parse(arg, n, status);
         logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
         if (n.getType() != Formattable::kLong ||
             n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
@@ -853,10 +1320,10 @@ NumberFormatTest::TestParse(void)
 // -------------------------------------
 
 static const char *lenientAffixTestCases[] = {
-               "(1)",
-               "( 1)",
-               "(1 )",
-               "( 1 )"
+        "(1)",
+        "( 1)",
+        "(1 )",
+        "( 1 )"
 };
 
 static const char *lenientMinusTestCases[] = {
@@ -866,33 +1333,34 @@ static const char *lenientMinusTestCases[] = {
 };
 
 static const char *lenientCurrencyTestCases[] = {
-               "$1,000",
-               "$ 1,000",
-               "$1000",
-               "$ 1000",
-               "$1 000.00",
-               "$ 1 000.00",
-               "$ 1\\u00A0000.00",
-               "1000.00"
+        "$1,000",
+        "$ 1,000",
+        "$1000",
+        "$ 1000",
+        "$1 000.00",
+        "$ 1 000.00",
+        "$ 1\\u00A0000.00",
+        "1000.00"
 };
 
+// changed from () to - per cldrbug 5674
 static const char *lenientNegativeCurrencyTestCases[] = {
-               "($1,000)",
-               "($ 1,000)",
-               "($1000)",
-               "($ 1000)",
-               "($1 000.00)",
-               "($ 1 000.00)",
-               "( $ 1,000.00 )",
-               "($ 1\\u00A0000.00)",
-               "(1000.00)"
+        "-$1,000",
+        "-$ 1,000",
+        "-$1000",
+        "-$ 1000",
+        "-$1 000.00",
+        "-$ 1 000.00",
+        "- $ 1,000.00 ",
+        "-$ 1\\u00A0000.00",
+        "-1000.00"
 };
 
 static const char *lenientPercentTestCases[] = {
-               "25%",
-               " 25%",
-               " 25 %",
-               "25 %",
+        "25%",
+        " 25%",
+        " 25 %",
+       "25 %",
                "25\\u00A0%",
                "25"
 };
@@ -915,8 +1383,6 @@ static const char *strictFailureTestCases[] = {
                "1,000,.0"
 };
 
-#define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
-
 /**
  * Test lenient parsing.
  */
@@ -927,155 +1393,176 @@ NumberFormatTest::TestLenientParse(void)
     DecimalFormat *format = new DecimalFormat("(#,##0)", status);
     Formattable n;
 
-    format->setParseStrict(FALSE);
-    for (int32_t t = 0; t < ARRAY_SIZE (lenientAffixTestCases); t += 1) {
-       UnicodeString testCase = ctou(lenientAffixTestCases[t]);
-
-        format->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+    if (format == NULL || U_FAILURE(status)) {
+        dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
+    } else {
+        format->setLenient(TRUE);
+        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
+               UnicodeString testCase = ctou(lenientAffixTestCases[t]);
 
-        if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
-               n.getLong() != 1) {
-               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
-               status = U_ZERO_ERROR;
-        }
-   }
+            format->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
 
-    delete format;
+            if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
+               n.getLong() != 1) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
+               status = U_ZERO_ERROR;
+            }
+       }
+       delete format;
+    }
 
     Locale en_US("en_US");
     Locale sv_SE("sv_SE");
     
-    NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, NumberFormat::kNumberStyle, status);
+    NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
     
-    mFormat->setParseStrict(FALSE);
-    for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
-        UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-        
-        mFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-        
-        if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
-            errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
-            status = U_ZERO_ERROR;
+    if (mFormat == NULL || U_FAILURE(status)) {
+        dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
+    } else {
+        mFormat->setLenient(TRUE);
+        for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
+            UnicodeString testCase = ctou(lenientMinusTestCases[t]);
+            
+            mFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+            
+            if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
+                errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+                status = U_ZERO_ERROR;
+            }
         }
+        delete mFormat;
     }
     
-    delete mFormat;
-    
-    mFormat = NumberFormat::createInstance(en_US, NumberFormat::kNumberStyle, status);
+    mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
     
-    mFormat->setParseStrict(FALSE);
-    for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
-        UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-        
-        mFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-        
-        if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
-            errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
-            status = U_ZERO_ERROR;
+    if (mFormat == NULL || U_FAILURE(status)) {
+        dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
+    } else {
+        mFormat->setLenient(TRUE);
+        for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
+            UnicodeString testCase = ctou(lenientMinusTestCases[t]);
+            
+            mFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+            
+            if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
+                errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+                status = U_ZERO_ERROR;
+            }
         }
+        delete mFormat;
     }
     
-    delete mFormat;
-    
-    NumberFormat *cFormat = NumberFormat::createInstance(en_US, NumberFormat::kCurrencyStyle, status);
+    NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
 
-    cFormat->setParseStrict(FALSE);
-    for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
-       UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
+    if (cFormat == NULL || U_FAILURE(status)) {
+        dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
+    } else {
+        cFormat->setLenient(TRUE);
+        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
+               UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
 
-        cFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+            cFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
 
-        if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
-               n.getLong() != 1000) {
-               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
-               status = U_ZERO_ERROR;
+            if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
+               n.getLong() != 1000) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
+               status = U_ZERO_ERROR;
+            }
         }
-   }
 
-    for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
-       UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
+        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
+               UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
 
-        cFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+            cFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
 
-        if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
-               n.getLong() != -1000) {
-               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\"");
-               status = U_ZERO_ERROR;
+            if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
+               n.getLong() != -1000) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\"");
+               status = U_ZERO_ERROR;
+            }
         }
-   }
 
-    delete cFormat;
+        delete cFormat;
+    }
 
     NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
 
-    pFormat->setParseStrict(FALSE);
-    for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
-       UnicodeString testCase = ctou(lenientPercentTestCases[t]);
+    if (pFormat == NULL || U_FAILURE(status)) {
+        dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
+    } else {
+        pFormat->setLenient(TRUE);
+        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
+               UnicodeString testCase = ctou(lenientPercentTestCases[t]);
 
-       pFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
+               pFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
 
-        if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
-               n.getDouble() != 0.25) {
-               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
-               status = U_ZERO_ERROR;
+            if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
+               n.getDouble() != 0.25) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
+               status = U_ZERO_ERROR;
+            }
         }
-   }
 
-    for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
-       UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
+        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
+               UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
 
-       pFormat->parse(testCase, n, status);
-        logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
+               pFormat->parse(testCase, n, status);
+            logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
 
-        if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
-               n.getDouble() != -0.25) {
-               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
-               status = U_ZERO_ERROR;
+            if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
+               n.getDouble() != -0.25) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
+               status = U_ZERO_ERROR;
+            }
         }
-   }
 
-   delete pFormat;
+        delete pFormat;
+    }
 
    // Test cases that should fail with a strict parse and pass with a
    // lenient parse.
    NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
-
-   // first, make sure that they fail with a strict parse
-   for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
-          UnicodeString testCase = ctou(strictFailureTestCases[t]);
-
-          nFormat->parse(testCase, n, status);
-          logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
-          if (! U_FAILURE(status)) {
-                  errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
-          }
-
-          status = U_ZERO_ERROR;
-   }
-
-   // then, make sure that they pass with a lenient parse
-   nFormat->setParseStrict(FALSE);
-   for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
-          UnicodeString testCase = ctou(strictFailureTestCases[t]);
-
-          nFormat->parse(testCase, n, status);
-          logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
-          if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
-                       n.getLong() != 1000) {
-                  errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
-                  status = U_ZERO_ERROR;
-          }
+    
+   if (nFormat == NULL || U_FAILURE(status)) {
+       dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
+   } else { 
+       // first, make sure that they fail with a strict parse
+       for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
+              UnicodeString testCase = ctou(strictFailureTestCases[t]);
+
+              nFormat->parse(testCase, n, status);
+              logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+
+              if (! U_FAILURE(status)) {
+                      errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+              }
+
+              status = U_ZERO_ERROR;
+       }
+
+       // then, make sure that they pass with a lenient parse
+       nFormat->setLenient(TRUE);
+       for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
+              UnicodeString testCase = ctou(strictFailureTestCases[t]);
+
+              nFormat->parse(testCase, n, status);
+              logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+
+              if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
+                       n.getLong() != 1000) {
+                      errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+                      status = U_ZERO_ERROR;
+              }
+       }
+
+       delete nFormat;
    }
-
-   delete nFormat;
 }
 
 // -------------------------------------
@@ -1241,7 +1728,7 @@ void NumberFormatTest::TestScientific(void) {
     // Test pattern round-trip
     const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
                           "0.###E0;[0.###E0]" };
-    int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
+    int32_t PAT_length = UPRV_LENGTHOF(PAT);
     int32_t DIGITS[] = {
         // min int, max int, min frac, max frac
         0, 1, 0, 0, // "#E0"
@@ -1804,15 +2291,15 @@ void NumberFormatTest::TestCurrencyNames(void) {
                                              UCURR_SYMBOL_NAME,
                                              &isChoiceFormat, &len, &ec)),
                                              possibleDataError);
-    assertEquals("USD.getName(SYMBOL_NAME)",
+    assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
                  UnicodeString("US$"),
-                 UnicodeString(ucurr_getName(USD, "en_AU",
+                 UnicodeString(ucurr_getName(USD, "en_NZ",
                                              UCURR_SYMBOL_NAME,
                                              &isChoiceFormat, &len, &ec)),
                                              possibleDataError);
     assertEquals("CAD.getName(SYMBOL_NAME)",
                  UnicodeString("CA$"),
-                 UnicodeString(ucurr_getName(CAD, "en_AU",
+                 UnicodeString(ucurr_getName(CAD, "en_NZ",
                                              UCURR_SYMBOL_NAME,
                                              &isChoiceFormat, &len, &ec)),
                                              possibleDataError);
@@ -1842,9 +2329,9 @@ void NumberFormatTest::TestCurrencyNames(void) {
     assertTrue("ucurr_getName (en_US default)",
                     U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
 
-    ucurr_getName(CAD, "vi", UCURR_LONG_NAME, &isChoiceFormat,
+    ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
                             &len, &ec);
-    assertTrue("ucurr_getName (vi default)",
+    assertTrue("ucurr_getName (ti default)",
                     U_USING_DEFAULT_WARNING == ec, TRUE);
 
     // Test that a default warning is being returned when falling back to root. JB 4536.
@@ -1859,6 +2346,8 @@ void NumberFormatTest::TestCurrencyNames(void) {
 void NumberFormatTest::TestCurrencyUnit(void){
     UErrorCode ec = U_ZERO_ERROR;
     static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
+    static const UChar BAD[] = {63, 63, 63, 0}; /*???*/
+    static const UChar BAD2[] = {63, 63, 65, 0}; /*???*/
     CurrencyUnit cu(USD, ec);
     assertSuccess("CurrencyUnit", ec);
 
@@ -1874,6 +2363,23 @@ void NumberFormatTest::TestCurrencyUnit(void){
     if (!(*cu3 == cu)){
         errln("CurrencyUnit cloned object should be same");
     }
+    CurrencyUnit bad(BAD, ec);
+    assertSuccess("CurrencyUnit", ec);
+    if (cu.getIndex() == bad.getIndex()) {
+        errln("Indexes of different currencies should differ.");
+    }
+    CurrencyUnit bad2(BAD2, ec);
+    assertSuccess("CurrencyUnit", ec);
+    if (bad2.getIndex() != bad.getIndex()) {
+        errln("Indexes of unrecognized currencies should be the same.");
+    }
+    if (bad == bad2) {
+        errln("Different unrecognized currencies should not be equal.");
+    }
+    bad = bad2;
+    if (bad != bad2) {
+        errln("Currency unit assignment should be the same.");
+    }
     delete cu3;
 }
 
@@ -1902,37 +2408,49 @@ void NumberFormatTest::TestCurrencyAmount(void){
 
 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
     Locale locDefault;
-    Locale locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
-    UErrorCode status = U_ZERO_ERROR;
-    UnicodeString intlCurrencySymbol((UChar)0xa4);
-
-    intlCurrencySymbol.append((UChar)0xa4);
+    static const char *badLocales[] = {
+        // length < ULOC_FULLNAME_CAPACITY
+        "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
+
+        // length > ULOC_FULLNAME_CAPACITY
+        "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
+    }; // expect U_USING_DEFAULT_WARNING for both
+
+    unsigned int i;
+    for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
+        const char *localeName = badLocales[i];
+        Locale locBad(localeName);
+        UErrorCode status = U_ZERO_ERROR;
+        UnicodeString intlCurrencySymbol((UChar)0xa4);
 
-    logln("Current locale is %s", Locale::getDefault().getName());
-    Locale::setDefault(locBad, status);
-    logln("Current locale is %s", Locale::getDefault().getName());
-    DecimalFormatSymbols mySymbols(status);
-    if (status != U_USING_FALLBACK_WARNING) {
-        errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
-    }
-    if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
-        errln("DecimalFormatSymbols does not have the right locale.");
-    }
-    int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
-    for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
-        logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ")
-            + prettify(mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum)));
+        intlCurrencySymbol.append((UChar)0xa4);
 
-        if (mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum).length() == 0
-            && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
-            && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
-        {
-            errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
+        logln("Current locale is %s", Locale::getDefault().getName());
+        Locale::setDefault(locBad, status);
+        logln("Current locale is %s", Locale::getDefault().getName());
+        DecimalFormatSymbols mySymbols(status);
+        if (status != U_USING_DEFAULT_WARNING) {
+            errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
+        }
+        if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
+            errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
+        }
+        int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
+        for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
+            UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
+            logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
+            if (symbolString.length() == 0
+                && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
+                && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
+            {
+                errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
+            }
         }
+
+        status = U_ZERO_ERROR;
+        Locale::setDefault(locDefault, status);
+        logln("Current locale is %s", Locale::getDefault().getName());
     }
-    status = U_ZERO_ERROR;
-    Locale::setDefault(locDefault, status);
-    logln("Current locale is %s", Locale::getDefault().getName());
 }
 
 /**
@@ -2220,6 +2738,12 @@ void NumberFormatTest::TestCases() {
                     if (!tokens.next(tok, ec)) goto error;
                     continue;
                 }
+            } else if (mfmt == NULL) {
+                errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
+                if (!tokens.next(tok, ec)) goto error;
+                if (!tokens.next(tok, ec)) goto error;
+                if (!tokens.next(tok, ec)) goto error;
+                continue;
             }
             // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
             if (!tokens.next(currAmt, ec)) goto error;
@@ -2480,12 +3004,12 @@ void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
 }
 
 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
-                              const UnicodeString& exp,
+                              const UnicodeString& exp, UBool rt,
                               UErrorCode status) {
     if (fmt == NULL || U_FAILURE(status)) {
         dataerrln("FAIL: NumberFormat constructor");
     } else {
-        expect(*fmt, n, exp);
+        expect(*fmt, n, exp, rt);
     }
     delete fmt;
 }
@@ -2576,11 +3100,79 @@ void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
               ", expected " + pos + " " + width + " " + pad);
     }
 }
+
+// This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale  - FIXME
+void NumberFormatTest::TestCompatibleCurrencies() {
+/*
+    static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
+    static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<NumberFormat> fmt(
+        NumberFormat::createCurrencyInstance(Locale::getUS(), status));
+    if (U_FAILURE(status)) {
+        errln("Could not create number format instance.");
+        return;
+    }
+    logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmt, JPY, 1235,  "\\u00A51,235");
+    logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmt, JPY, 1235,  "\\uFFE51,235");
+    logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmt, CNY, 1235,  "CN\\u00A51,235");
+
+    LocalPointer<NumberFormat> fmtTW(
+        NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
+
+    logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmtTW, CNY, 1235,  "\\u00A51,235");
+    logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmtTW, CNY, 1235,  "\\uFFE51,235");
+
+    LocalPointer<NumberFormat> fmtJP(
+        NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
+
+    logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmtJP, JPY, 1235,  "\\u00A51,235");
+    logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
+    expectParseCurrency(*fmtJP, JPY, 1235,  "\\uFFE51,235");
+    
+    // more..
+*/
+}
+
+void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
+    ParsePosition ppos;
+    UnicodeString utext = ctou(text);
+    LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
+    if (!ppos.getIndex()) {
+        errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
+        return;
+    }
+    UErrorCode status = U_ZERO_ERROR;
+
+    char theInfo[100];
+    sprintf(theInfo, "For locale %s, string \"%s\", currency ",
+            fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
+            text);
+    u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
+    
+    char theOperation[100];
+
+    uprv_strcpy(theOperation, theInfo);
+    uprv_strcat(theOperation, ", check amount:");
+    assertTrue(theOperation, amount ==  currencyAmount->getNumber().getDouble(status));
+
+    uprv_strcpy(theOperation, theInfo);
+    uprv_strcat(theOperation, ", check currency:");
+    assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
+}
+  
+
 void NumberFormatTest::TestJB3832(){
     const char* localeID = "pt_PT@currency=PTE";
     Locale loc(localeID);
     UErrorCode status = U_ZERO_ERROR;
-    UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
+    UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
     UnicodeString s;
     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
     if(U_FAILURE(status)){
@@ -2601,16 +3193,24 @@ void NumberFormatTest::TestJB3832(){
 
 void NumberFormatTest::TestHost()
 {
-#ifdef U_WINDOWS
+#if U_PLATFORM_USES_ONLY_WIN32_API
     Win32NumberTest::testLocales(this);
 #endif
-    for (NumberFormat::EStyles k = NumberFormat::kNumberStyle;
-         k < NumberFormat::kStyleCount; k = (NumberFormat::EStyles)(k+1)) {
+    Locale loc("en_US@compat=host");
+    for (UNumberFormatStyle k = UNUM_DECIMAL;
+         k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
         UErrorCode status = U_ZERO_ERROR;
-        Locale loc("en_US@compat=host");
-        NumberFormat *full = NumberFormat::createInstance(loc, status);
-        if (full == NULL || U_FAILURE(status)) {
-            dataerrln("FAIL: Can't create number instance for host - %s", u_errorName(status));
+        LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
+        if (!NumberFormat::isStyleSupported(k)) {
+            if (status != U_UNSUPPORTED_ERROR) {
+                errln("FAIL: expected style %d to be unsupported - %s",
+                      k, u_errorName(status));
+            }
+            continue;
+        }
+        if (full.isNull() || U_FAILURE(status)) {
+            dataerrln("FAIL: Can't create number instance of style %d for host - %s",
+                      k, u_errorName(status));
             return;
         }
         UnicodeString result1;
@@ -2626,7 +3226,6 @@ void NumberFormatTest::TestHost()
             errln("FAIL: Can't parse for host");
             return;
         }
-        delete full;
     }
 }
 
@@ -2748,20 +3347,57 @@ void NumberFormatTest::TestRounding() {
     delete df;
 }
 
-void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
-    df->setRoundingIncrement(increment);
-    double lastParsed=INT32_MIN; //Intger.MIN_VALUE
-    for (int i=-iterations; i<=iterations;i++) {
-        double iValue=base+(increment*(i*0.1));
-        double smallIncrement=0.00000001;
-        if (iValue!=0) {
-            smallIncrement*=iValue;
-        }
-        //we not only test the value, but some values in a small range around it
-        lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
-        lastParsed=checkRound(df, iValue, lastParsed);
-        lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
-    }
+void NumberFormatTest::TestRoundingPattern() {
+    UErrorCode status = U_ZERO_ERROR;
+    struct {
+        UnicodeString  pattern;
+        double        testCase;
+        UnicodeString expected;
+    } tests[] = {
+            { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
+            { (UnicodeString)"#50",    1230,  (UnicodeString)"1250" }
+    };
+    int32_t numOfTests = UPRV_LENGTHOF(tests);
+    UnicodeString result;
+
+    DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
+    if (U_FAILURE(status)) {
+        dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
+        return;
+    }
+
+    for (int32_t i = 0; i < numOfTests; i++) {
+        result.remove();
+
+        df->applyPattern(tests[i].pattern, status);
+        if (U_FAILURE(status)) {
+            errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
+        }
+
+        df->format(tests[i].testCase, result);
+
+        if (result != tests[i].expected) {
+            errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
+        }
+    }
+
+    delete df;
+}
+
+void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
+    df->setRoundingIncrement(increment);
+    double lastParsed=INT32_MIN; //Intger.MIN_VALUE
+    for (int i=-iterations; i<=iterations;i++) {
+        double iValue=base+(increment*(i*0.1));
+        double smallIncrement=0.00000001;
+        if (iValue!=0) {
+            smallIncrement*=iValue;
+        }
+        //we not only test the value, but some values in a small range around it
+        lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
+        lastParsed=checkRound(df, iValue, lastParsed);
+        lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
+    }
 }
 
 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
@@ -2854,24 +3490,41 @@ void NumberFormatTest::TestNonpositiveMultiplier() {
     //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
 }
 
+typedef struct {
+    const char * stringToParse;
+    int          parsedPos;
+    int          errorIndex;
+    UBool        lenient;
+} TestSpaceParsingItem;
 
 void
 NumberFormatTest::TestSpaceParsing() {
     // the data are:
     // the string to be parsed, parsed position, parsed error index
-    const char* DATA[][3] = {
-        {"$124", "4", "-1"},
-        {"$124 $124", "4", "-1"},
-        {"$124 ", "4", "-1"},
-        {"$ 124 ", "5", "-1"},
-        {"$\\u00A0124 ", "5", "-1"},
-        {" $ 124 ", "6", "-1"},
-        //{"124$", "4", "-1"}, // TODO: need to handle trailing currency correctly
-        {"124$", "3", "-1"},
-        //{"124 $", "5", "-1"},  // TODO: OK or not, need currency spacing rule
-        {"124 $", "4", "-1"},
+    const TestSpaceParsingItem DATA[] = {
+        // TOTO: Update the following TODOs, some may be handled now
+        {"$124",           4, -1, FALSE},
+        {"$124 $124",      4, -1, FALSE},
+        {"$124 ",          4, -1, FALSE},
+        //{"$ 124 ",       5, -1, FALSE}, // TODO: need to handle space correctly
+        //{"$\\u00A0124 ", 5, -1, FALSE}, // TODO: need to handle space correctly
+        {"$ 124 ",         0,  1, FALSE}, // errorIndex used to be 0, now 1 (better)
+        {"$\\u00A0124 ",   5, -1, FALSE}, // errorIndex used to be 0, now 1 (better) *Apple change from open source*
+        {" $ 124 ",        0,  0, FALSE}, // TODO: need to handle space correctly
+        {"124$",           0,  3, FALSE}, // TODO: need to handle space correctly
+        // {"124 $",       5, -1, FALSE}, // TODO: OK or not, need currency spacing rule
+        {"124 $",          0,  3, FALSE},
+        {"$124",           4, -1, TRUE},
+        {"$124 $124",      4, -1, TRUE},
+        {"$124 ",          4, -1, TRUE},
+        {"$ 124 ",         5, -1, TRUE},
+        {"$\\u00A0124 ",   5, -1, TRUE},
+        {" $ 124 ",        6, -1, TRUE},
+        //{"124$",         4, -1, TRUE}, // TODO: need to handle trailing currency correctly
+        {"124$",           3, -1, TRUE},
+        //{"124 $",        5, -1, TRUE}, // TODO: OK or not, need currency spacing rule
+        {"124 $",          4, -1, TRUE},
     };
-
     UErrorCode status = U_ZERO_ERROR;
     Locale locale("en_US");
     NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
@@ -2880,18 +3533,17 @@ NumberFormatTest::TestSpaceParsing() {
         delete foo;
         return;
     }
-
-    foo->setParseStrict(FALSE);
-    for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+    for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
         ParsePosition parsePosition(0);
-        UnicodeString stringToBeParsed = ctou(DATA[i][0]);
-        int parsedPosition = atoi(DATA[i][1]);
-        int errorIndex = atoi(DATA[i][2]);
+        UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
+        int parsedPosition = DATA[i].parsedPos;
+        int errorIndex = DATA[i].errorIndex;
+        foo->setLenient(DATA[i].lenient);
         Formattable result;
         foo->parse(stringToBeParsed, result, parsePosition);
         if (parsePosition.getIndex() != parsedPosition ||
             parsePosition.getErrorIndex() != errorIndex) {
-            errln("FAILED parse " + stringToBeParsed + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
+            errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
         }
         if (parsePosition.getErrorIndex() == -1 &&
             result.getType() == Formattable::kLong &&
@@ -2905,57 +3557,65 @@ NumberFormatTest::TestSpaceParsing() {
 /**
  * Test using various numbering systems and numbering system keyword.
  */
+typedef struct {
+    const char *localeName;
+    double      value;
+    UBool        isRBNF;
+    const char *expectedResult;
+} TestNumberingSystemItem;
+
 void NumberFormatTest::TestNumberingSystems() {
-    UErrorCode ec = U_ZERO_ERROR;
 
-    Locale loc1("en", "US", "", "numbers=thai");
-    Locale loc2("en", "US", "", "numbers=hebr");
-    Locale loc3("en", "US", "", "numbers=arabext");
-    Locale loc4("en", "US", "", "numbers=foobar");
-    Locale loc5("ar", "EG", "", ""); // ar_EG uses arab numbering system
-    Locale loc6("ar", "MA", "", ""); // ar_MA uses latn numbering system
-    Locale loc7("en", "US", "", "numbers=hanidec");
+    const TestNumberingSystemItem DATA[] = {
+        { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
+        { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
+        { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
+        { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
+        { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
+        { "ar_MA", 1234.567, FALSE, "1.234,567" },
+        { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
+        { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
+        { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
+        { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
+        { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
+        { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
+        { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
+        { NULL, 0, FALSE, NULL }
+    };
 
-    NumberFormat* fmt1= NumberFormat::createInstance(loc1, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(en_US@numbers=thai) - %s", u_errorName(ec));
-    }
-    NumberFormat* fmt2= NumberFormat::createInstance(loc2, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(en_US@numbers=hebr) - %s", u_errorName(ec));
-    }
-    NumberFormat* fmt3= NumberFormat::createInstance(loc3, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(en_US@numbers=arabext) - %s", u_errorName(ec));
-    }
-    NumberFormat* fmt5= NumberFormat::createInstance(loc5, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(ar_EG) - %s", u_errorName(ec));
-    }
-    NumberFormat* fmt6= NumberFormat::createInstance(loc6, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(ar_MA) - %s", u_errorName(ec));
-    }
+    UErrorCode ec;
 
-    NumberFormat* fmt7= NumberFormat::createInstance(loc7, ec);
-    if (U_FAILURE(ec)) {
-        dataerrln("FAIL: getInstance(en_US@numbers=hanidec) - %s", u_errorName(ec));
-    }
+    const TestNumberingSystemItem *item;
+    for (item = DATA; item->localeName != NULL; item++) {
+        ec = U_ZERO_ERROR;
+        Locale loc = Locale::createFromName(item->localeName);
+
+        NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
+        if (U_FAILURE(ec)) {
+            dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
+            continue;
+        }
+        // Clone to test ticket #10682
+        NumberFormat *fmt = (NumberFormat *) origFmt->clone();
+        delete origFmt;
 
-    if (U_SUCCESS(ec) && fmt1 != NULL && fmt2 != NULL && fmt3 != NULL && 
-                         fmt5 != NULL && fmt6 != NULL && fmt7 != NULL) {
-        expect2(*fmt1, 1234.567, CharsToUnicodeString("\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57"));
-        expect3(*fmt2, 5678.0, CharsToUnicodeString("\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7"));
-        expect2(*fmt3, 1234.567, CharsToUnicodeString("\\u06F1,\\u06F2\\u06F3\\u06F4.\\u06F5\\u06F6\\u06F7"));
-        expect2(*fmt5, 1234.567, CharsToUnicodeString("\\u0661\\u066c\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667"));
-        expect2(*fmt6, 1234.567, CharsToUnicodeString("1.234,567"));
-        expect2(*fmt7, 1234.567, CharsToUnicodeString("\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03"));
+        
+        if (item->isRBNF) {
+            expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
+        } else {
+            expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
+        }
+        delete fmt;
     }
 
+
     // Test bogus keyword value
+    ec = U_ZERO_ERROR;
+    Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
     NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
     if ( ec != U_UNSUPPORTED_ERROR ) {
         errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
+        delete fmt4;
     }
 
     ec = U_ZERO_ERROR;
@@ -2978,13 +3638,7 @@ void NumberFormatTest::TestNumberingSystems() {
 
     delete ns1;
     delete ns;
-    delete fmt1;
-    delete fmt2;
-    delete fmt3;
-    delete fmt4;
-    delete fmt5;
-    delete fmt6;
-    delete fmt7;
+
 }
 
 
@@ -3001,7 +3655,7 @@ NumberFormatTest::TestMultiCurrencySign() {
         // for US locale
         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
         {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
-        {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollar1.00"},
+        {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
         // for CHINA locale
         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\uFFE51,234.56", "CNY1,234.56", "\\u4EBA\\u6C11\\u5E011,234.56"},
         {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\uFFE51,234.56)", "(CNY1,234.56)", "(\\u4EBA\\u6C11\\u5E011,234.56)"},
@@ -3013,7 +3667,7 @@ NumberFormatTest::TestMultiCurrencySign() {
     const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
     UnicodeString tripleCurrencyStr(tripleCurrencySign);
 
-    for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
+    for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
         const char* locale = DATA[i][0];
         UnicodeString pat = ctou(DATA[i][1]);
         double numberToBeFormat = atof(DATA[i][2]);
@@ -3094,7 +3748,7 @@ NumberFormatTest::TestCurrencyFormatForMixParsing() {
         "1,234.56 US dollars"
     };
     const CurrencyAmount* curramt = NULL;
-    for (uint32_t i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+    for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
         UnicodeString stringToBeParsed = ctou(formats[i]);
         logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
         Formattable result;
@@ -3149,7 +3803,7 @@ NumberFormatTest::TestDecimalFormatCurrencyParse() {
         {"USD1,234.56", "1234.56"},
         {"1,234.56 US dollar", "1234.56"},
     };
-    for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+    for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
         UnicodeString stringToBeParsed = ctou(DATA[i][0]);
         double parsedResult = atof(DATA[i][1]);
         UErrorCode status = U_ZERO_ERROR;
@@ -3169,7 +3823,7 @@ NumberFormatTest::TestDecimalFormatCurrencyParse() {
 
 void
 NumberFormatTest::TestCurrencyIsoPluralFormat() {
-    const char* DATA[][6] = {
+    static const char* DATA[][6] = {
         // the data are:
         // locale,
         // currency amount to be formatted,
@@ -3178,34 +3832,30 @@ NumberFormatTest::TestCurrencyIsoPluralFormat() {
         // format result using ISOCURRENCYSTYLE,
         // format result using PLURALCURRENCYSTYLE,
 
-        {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
+        {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
         {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
-        {"en_US", "-1234.56", "USD", "($1,234.56)", "(USD1,234.56)", "-1,234.56 US dollars"},
-        {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00 \\u7F8E\\u5143"},
-        {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56 \\u7F8E\\u5143"},
-        // wrong ISO code {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"},
-        // wrong ISO code {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"},
-        {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4EBA\\u6C11\\u5E01"},
-        {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56 \\u4EBA\\u6C11\\u5E01"},
-        {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"},
-        {"ru_RU", "2", "RUB", "2,00\\u00A0\\u0440\\u0443\\u0431.", "2,00\\u00A0RUB", "2,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0445 \\u0440\\u0443\\u0431\\u043B\\u044F"},
-        {"ru_RU", "5", "RUB", "5,00\\u00A0\\u0440\\u0443\\u0431.", "5,00\\u00A0RUB", "5,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0445 \\u0440\\u0443\\u0431\\u043B\\u0435\\u0439"},
+        {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
+        {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00\\u7F8E\\u5143"},
+        {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56\\u7F8E\\u5143"},
+        {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+        {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
+        {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
+        {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
+        {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
         // test locale without currency information
         {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
         // test choice format
-        {"es_AR", "1", "INR", "Rs\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
+        {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
+    };
+    static const UNumberFormatStyle currencyStyles[] = {
+        UNUM_CURRENCY,
+        UNUM_CURRENCY_ISO,
+        UNUM_CURRENCY_PLURAL
     };
 
-    for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
-      for (NumberFormat::EStyles k = NumberFormat::kCurrencyStyle;
-           k <= NumberFormat::kPluralCurrencyStyle;
-           k = (NumberFormat::EStyles)(k+1)) {
-        // k represents currency format style.
-        if ( k != NumberFormat::kCurrencyStyle &&
-             k != NumberFormat::kIsoCurrencyStyle &&
-             k != NumberFormat::kPluralCurrencyStyle ) {
-            continue;
-        }
+    for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
+      for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
+        UNumberFormatStyle k = currencyStyles[kIndex];
         const char* localeString = DATA[i][0];
         double numberToBeFormat = atof(DATA[i][1]);
         const char* currencyISOCode = DATA[i][2];
@@ -3228,10 +3878,7 @@ NumberFormatTest::TestCurrencyIsoPluralFormat() {
 
         UnicodeString strBuf;
         numFmt->format(numberToBeFormat, strBuf);
-        int resultDataIndex = k;
-        if ( k == NumberFormat::kCurrencyStyle ) {
-            resultDataIndex = k+2;
-        }
+        int resultDataIndex = 3 + kIndex;
         // DATA[i][resultDataIndex] is the currency format result
         // using 'k' currency style.
         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
@@ -3271,7 +3918,7 @@ NumberFormatTest::TestCurrencyIsoPluralFormat() {
 
 void
 NumberFormatTest::TestCurrencyParsing() {
-    const char* DATA[][6] = {
+    static const char* DATA[][6] = {
         // the data are:
         // locale,
         // currency amount to be formatted,
@@ -3280,19 +3927,33 @@ NumberFormatTest::TestCurrencyParsing() {
         // format result using ISOCURRENCYSTYLE,
         // format result using PLURALCURRENCYSTYLE,
         {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
-        {"pa_IN", "1", "USD", "US$\\u00a0\\u0a67.\\u0a66\\u0a66", "USD\\u00a0\\u0a67.\\u0a66\\u0a66", "\\u0a67.\\u0a66\\u0a66 USD"},
-        {"es_AR", "1", "USD", "US$\\u00a01,00", "USD\\u00a01,00", "1,00 d\\u00f3lar estadounidense"},
-        {"ar_EG", "1", "USD", "US$\\u00a0\\u0661\\u066b\\u0660\\u0660", "USD\\u00a0\\u0661\\u066b\\u0660\\u0660", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
-        {"fa_CA", "1", "USD", "\\u06f1\\u066b\\u06f0\\u06f0\\u00a0US$", "\\u06f1\\u066b\\u06f0\\u06f0\\u00a0USD", "\\u06f1\\u066b\\u06f0\\u06f0\\u0020\\u062f\\u0644\\u0627\\u0631\\u0020\\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
-        {"he_IL", "1", "USD", "1.00\\u00a0US$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
-        {"hr_HR", "1", "USD", "1,00\\u00a0$", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
-        {"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 USD"},
-        {"it_IT", "1", "USD", "US$\\u00a01,00", "USD\\u00a01,00", "1,00 Dollaro Statunitense"},
+        {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
+        {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
+        {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
+        {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u200e\\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627\\u06f1\\u066b\\u06f0\\u06f0"},
+        {"he_IL", "1", "USD", "1.00\\u00a0$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
+        {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
+        {"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 Dolar Amerika Serikat"},
+        {"it_IT", "1", "USD", "1,00\\u00a0US$", "1,00\\u00a0USD", "1,00 Dollaro Statunitense"},
         {"ko_KR", "1", "USD", "US$1.00", "USD1.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
-        {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00 \\u7c73\\u30c9\\u30eb"},
-        {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4EBA\\u6C11\\u5E01"},
-        {"zh_TW", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
-        {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"},
+        {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00\\u7c73\\u30c9\\u30eb"},
+        {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+        {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
+        {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
+        {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u5713"},
+        {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
+        {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
+        {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}
+    };
+    static const UNumberFormatStyle currencyStyles[] = {
+        UNUM_CURRENCY,
+        UNUM_CURRENCY_ISO,
+        UNUM_CURRENCY_PLURAL
+    };
+    static const char* currencyStyleNames[] = {
+      "UNUM_CURRENCY",
+      "UNUM_CURRENCY_ISO",
+      "UNUM_CURRENCY_PLURAL"
     };
 
 #ifdef NUMFMTST_CACHE_DEBUG
@@ -3300,33 +3961,26 @@ int deadloop = 0;
 for (;;) {
     printf("loop: %d\n", deadloop++);
 #endif
-    for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
-      for (NumberFormat::EStyles k = NumberFormat::kCurrencyStyle;
-           k <= NumberFormat::kPluralCurrencyStyle;
-           k = (NumberFormat::EStyles)(k+1)) {
-        // k represents currency format style.
-        if ( k != NumberFormat::kCurrencyStyle &&
-             k != NumberFormat::kIsoCurrencyStyle &&
-             k != NumberFormat::kPluralCurrencyStyle ) {
-            continue;
-        }
+    for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) {  /* i = test case #  - should be i=0*/
+      for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
+        UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
         const char* localeString = DATA[i][0];
         double numberToBeFormat = atof(DATA[i][1]);
         const char* currencyISOCode = DATA[i][2];
         Locale locale(localeString);
         UErrorCode status = U_ZERO_ERROR;
         NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
+        logln("#%d NumberFormat(%s, %s) Currency=%s\n",
+              i, localeString, currencyStyleNames[kIndex], 
+              currencyISOCode);
+
         if (U_FAILURE(status)) {
             delete numFmt;
             dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
             continue;
         }
-        // TODO: need to be UChar*
         UChar currencyCode[4];
-        currencyCode[0] = currencyISOCode[0];
-        currencyCode[1] = currencyISOCode[1];
-        currencyCode[2] = currencyISOCode[2];
-        currencyCode[3] = currencyISOCode[3];
+        u_charsToUChars(currencyISOCode, currencyCode, 4);
         numFmt->setCurrency(currencyCode, status);
         if (U_FAILURE(status)) {
             delete numFmt;
@@ -3334,13 +3988,10 @@ for (;;) {
             continue;
         }
 
-        /*
         UnicodeString strBuf;
         numFmt->format(numberToBeFormat, strBuf);
-        int resultDataIndex = k;
-        if ( k == NumberFormat::kCurrencyStyle ) {
-            resultDataIndex = k+2;
-        }
+        /*
+        int resultDataIndex = 3 + kIndex;
         // DATA[i][resultDataIndex] is the currency format result
         // using 'k' currency style.
         UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
@@ -3359,20 +4010,21 @@ for (;;) {
             UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
             UErrorCode status = U_ZERO_ERROR;
             Formattable parseResult;
+            logln("parse(%s)", DATA[i][j]);
             numFmt->parse(oneCurrencyFormatResult, parseResult, status);
             if (U_FAILURE(status) ||
                 (parseResult.getType() == Formattable::kDouble &&
                  parseResult.getDouble() != numberToBeFormat) ||
                 (parseResult.getType() == Formattable::kLong &&
                  parseResult.getLong() != numberToBeFormat)) {
-                errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
-                      localeString + " failed roundtripping the number" +
-                      "(i,k,j): " + i + ", " + k + ", " + j);
+                errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
+                      "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+".  Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
                 if (parseResult.getType() == Formattable::kDouble) {
-                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
+                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
                 } else {
-                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
+                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
                 }
+                errln((UnicodeString)" round-trip would be: " + strBuf);
             }
         }
         delete numFmt;
@@ -3393,7 +4045,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "US dollar1.00",
         "US dollars1.00",
         "$1.00",
-        "AU$1.00",
+        "A$1.00",
         "ADP1.00",
         "ADP1.00",
         "AED1.00",
@@ -3411,7 +4063,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "AON1.00",
         "AOR1.00",
         "AOR1.00",
-        "AR$1.00",
+        "ARS1.00",
         "ARA1.00",
         "ARA1.00",
         "ARP1.00",
@@ -3424,14 +4076,10 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "AZM1.00",
         "AZM1.00",
         "AZN1.00",
-        "Af1.00",
-        "Afghan Afghani (1927-2002)1.00",
-        "Afghan Afghani (AFA)1.00",
-        "Afghan Afghani1.00",
+        "Afghan Afghani (1927\\u20132002)1.00",
+        "Afghan afghani (1927\\u20132002)1.00",
         "Afghan Afghani1.00",
-        "Afghan Afghanis (AFA)1.00",
         "Afghan Afghanis1.00",
-        "Afl.1.00",
         "Albanian Lek1.00",
         "Albanian lek1.00",
         "Albanian lek\\u00eb1.00",
@@ -3441,26 +4089,26 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Andorran Peseta1.00",
         "Andorran peseta1.00",
         "Andorran pesetas1.00",
-        "Angolan Kwanza (1977-1991)1.00",
-        "Angolan Readjusted Kwanza (1995-1999)1.00",
+        "Angolan Kwanza (1977\\u20131991)1.00",
+        "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
         "Angolan Kwanza1.00",
-        "Angolan New Kwanza (1990-2000)1.00",
-        "Angolan kwanza (1977-1991)1.00",
-        "Angolan readjusted kwanza (1995-1999)1.00",
+        "Angolan New Kwanza (1990\\u20132000)1.00",
+        "Angolan kwanza (1977\\u20131991)1.00",
+        "Angolan readjusted kwanza (1995\\u20131999)1.00",
         "Angolan kwanza1.00",
-        "Angolan kwanzas (1977-1991)1.00",
-        "Angolan readjusted kwanzas (1995-1999)1.00",
+        "Angolan kwanzas (1977\\u20131991)1.00",
+        "Angolan readjusted kwanzas (1995\\u20131999)1.00",
         "Angolan kwanzas1.00",
-        "Angolan new kwanza (1990-2000)1.00",
-        "Angolan new kwanzas (1990-2000)1.00",
+        "Angolan new kwanza (1990\\u20132000)1.00",
+        "Angolan new kwanzas (1990\\u20132000)1.00",
         "Argentine Austral1.00",
-        "Argentine Peso (1983-1985)1.00",
+        "Argentine Peso (1983\\u20131985)1.00",
         "Argentine Peso1.00",
         "Argentine austral1.00",
         "Argentine australs1.00",
-        "Argentine peso (1983-1985)1.00",
+        "Argentine peso (1983\\u20131985)1.00",
         "Argentine peso1.00",
-        "Argentine pesos (1983-1985)1.00",
+        "Argentine pesos (1983\\u20131985)1.00",
         "Argentine pesos1.00",
         "Armenian Dram1.00",
         "Armenian dram1.00",
@@ -3473,25 +4121,22 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Austrian Schilling1.00",
         "Austrian schilling1.00",
         "Austrian schillings1.00",
-        "Azerbaijani Manat (1993-2006)1.00",
+        "Azerbaijani Manat (1993\\u20132006)1.00",
         "Azerbaijani Manat1.00",
-        "Azerbaijani manat (1993-2006)1.00",
+        "Azerbaijani manat (1993\\u20132006)1.00",
         "Azerbaijani manat1.00",
-        "Azerbaijani manats (1993-2006)1.00",
+        "Azerbaijani manats (1993\\u20132006)1.00",
         "Azerbaijani manats1.00",
-        "BN$1.00",
         "BAD1.00",
         "BAD1.00",
         "BAM1.00",
         "BBD1.00",
-        "BD$1.00",
         "BDT1.00",
         "BEC1.00",
         "BEC1.00",
         "BEF1.00",
         "BEL1.00",
         "BEL1.00",
-        "BF1.00",
         "BGL1.00",
         "BGN1.00",
         "BGN1.00",
@@ -3524,7 +4169,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "BYB1.00",
         "BYB1.00",
         "BYR1.00",
-        "BZ$1.00",
         "BZD1.00",
         "Bahamian Dollar1.00",
         "Bahamian dollar1.00",
@@ -3538,11 +4182,10 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Barbadian Dollar1.00",
         "Barbadian dollar1.00",
         "Barbadian dollars1.00",
-        "Bds$1.00",
-        "Belarusian New Ruble (1994-1999)1.00",
+        "Belarusian New Ruble (1994\\u20131999)1.00",
         "Belarusian Ruble1.00",
-        "Belarusian new ruble (1994-1999)1.00",
-        "Belarusian new rubles (1994-1999)1.00",
+        "Belarusian new ruble (1994\\u20131999)1.00",
+        "Belarusian new rubles (1994\\u20131999)1.00",
         "Belarusian ruble1.00",
         "Belarusian rubles1.00",
         "Belgian Franc (convertible)1.00",
@@ -3573,41 +4216,38 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Bolivian Boliviano1.00",
         "Bolivian Bolivianos1.00",
         "Bosnia-Herzegovina Convertible Mark1.00",
-        "Bosnia-Herzegovina Dinar (1992-1994)1.00",
+        "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
         "Bosnia-Herzegovina convertible mark1.00",
         "Bosnia-Herzegovina convertible marks1.00",
-        "Bosnia-Herzegovina dinar (1992-1994)1.00",
-        "Bosnia-Herzegovina dinars (1992-1994)1.00",
+        "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
+        "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
         "Botswanan Pula1.00",
         "Botswanan pula1.00",
         "Botswanan pulas1.00",
-        "Br1.00",
-        "Brazilian New Cruzado (1989-1990)1.00",
-        "Brazilian Cruzado (1986-1989)1.00",
-        "Brazilian Cruzeiro (1990-1993)1.00",
-        "Brazilian New Cruzeiro (1967-1986)1.00",
-        "Brazilian Cruzeiro (1993-1994)1.00",
+        "Brazilian New Cruzado (1989\\u20131990)1.00",
+        "Brazilian Cruzado (1986\\u20131989)1.00",
+        "Brazilian Cruzeiro (1990\\u20131993)1.00",
+        "Brazilian New Cruzeiro (1967\\u20131986)1.00",
+        "Brazilian Cruzeiro (1993\\u20131994)1.00",
         "Brazilian Real1.00",
-        "Brazilian new cruzado (1989-1990)1.00",
-        "Brazilian new cruzados (1989-1990)1.00",
-        "Brazilian cruzado (1986-1989)1.00",
-        "Brazilian cruzados (1986-1989)1.00",
-        "Brazilian cruzeiro (1990-1993)1.00",
-        "Brazilian new cruzeiro (1967-1986)1.00",
-        "Brazilian cruzeiro (1993-1994)1.00",
-        "Brazilian cruzeiros (1990-1993)1.00",
-        "Brazilian new cruzeiros (1967-1986)1.00",
-        "Brazilian cruzeiros (1993-1994)1.00",
+        "Brazilian new cruzado (1989\\u20131990)1.00",
+        "Brazilian new cruzados (1989\\u20131990)1.00",
+        "Brazilian cruzado (1986\\u20131989)1.00",
+        "Brazilian cruzados (1986\\u20131989)1.00",
+        "Brazilian cruzeiro (1990\\u20131993)1.00",
+        "Brazilian new cruzeiro (1967\\u20131986)1.00",
+        "Brazilian cruzeiro (1993\\u20131994)1.00",
+        "Brazilian cruzeiros (1990\\u20131993)1.00",
+        "Brazilian new cruzeiros (1967\\u20131986)1.00",
+        "Brazilian cruzeiros (1993\\u20131994)1.00",
         "Brazilian real1.00",
         "Brazilian reals1.00",
-        "British Pound Sterling1.00",
-        "British pound sterling1.00",
-        "British pounds sterling1.00",
+        "British Pound1.00",
+        "British pound1.00",
+        "British pounds1.00",
         "Brunei Dollar1.00",
         "Brunei dollar1.00",
         "Brunei dollars1.00",
-        "Bs1.00",
-        "Bs.F.1.00",
         "Bulgarian Hard Lev1.00",
         "Bulgarian Lev1.00",
         "Bulgarian Leva1.00",
@@ -3620,18 +4260,16 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Burundian Franc1.00",
         "Burundian franc1.00",
         "Burundian francs1.00",
-        "C$1.00",
         "CA$1.00",
         "CAD1.00",
         "CDF1.00",
         "CDF1.00",
-        "CF1.00",
-        "CFA Franc BCEAO1.00",
-        "CFA Franc BEAC1.00",
-        "CFA franc BCEAO1.00",
-        "CFA franc BEAC1.00",
-        "CFA francs BCEAO1.00",
-        "CFA francs BEAC1.00",
+        "West African CFA Franc1.00",
+        "Central African CFA Franc1.00",
+        "West African CFA franc1.00",
+        "Central African CFA franc1.00",
+        "West African CFA francs1.00",
+        "Central African CFA francs1.00",
         "CFP Franc1.00",
         "CFP franc1.00",
         "CFP francs1.00",
@@ -3641,12 +4279,10 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "CHF1.00",
         "CHW1.00",
         "CHW1.00",
-        "CL$1.00",
         "CLF1.00",
         "CLF1.00",
         "CLP1.00",
         "CNY1.00",
-        "CO$1.00",
         "COP1.00",
         "COU1.00",
         "COU1.00",
@@ -3710,7 +4346,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Czechoslovak Hard Koruna1.00",
         "Czechoslovak hard koruna1.00",
         "Czechoslovak hard korunas1.00",
-        "DA1.00",
         "DDM1.00",
         "DDM1.00",
         "DEM1.00",
@@ -3722,14 +4357,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Danish Krone1.00",
         "Danish krone1.00",
         "Danish kroner1.00",
-        "Db1.00",
         "German Mark1.00",
         "German mark1.00",
         "German marks1.00",
         "Djiboutian Franc1.00",
         "Djiboutian franc1.00",
         "Djiboutian francs1.00",
-        "Dkr1.00",
         "Dominican Peso1.00",
         "Dominican peso1.00",
         "Dominican pesos1.00",
@@ -3774,7 +4407,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Eritrean Nakfa1.00",
         "Eritrean nakfa1.00",
         "Eritrean nakfas1.00",
-        "Esc1.00",
         "Estonian Kroon1.00",
         "Estonian kroon1.00",
         "Estonian kroons1.00",
@@ -3797,8 +4429,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "European unit of account (XBD)1.00",
         "European units of account (XBC)1.00",
         "European units of account (XBD)1.00",
-        "FJ$1.00",
-        "FBu1.00",
         "FIM1.00",
         "FIM1.00",
         "FJD1.00",
@@ -3809,7 +4439,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Falkland Islands Pound1.00",
         "Falkland Islands pound1.00",
         "Falkland Islands pounds1.00",
-        "Fdj1.00",
         "Fijian Dollar1.00",
         "Fijian dollar1.00",
         "Fijian dollars1.00",
@@ -3826,13 +4455,10 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "French francs1.00",
         "French gold franc1.00",
         "French gold francs1.00",
-        "Ft1.00",
-        "GY$1.00",
         "GBP1.00",
         "GEK1.00",
         "GEK1.00",
         "GEL1.00",
-        "FG1.00",
         "GHC1.00",
         "GHC1.00",
         "GHS1.00",
@@ -3862,11 +4488,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Georgian kupon larits1.00",
         "Georgian lari1.00",
         "Georgian laris1.00",
-        "Ghanaian Cedi (1979-2007)1.00",
+        "Ghanaian Cedi (1979\\u20132007)1.00",
         "Ghanaian Cedi1.00",
-        "Ghanaian cedi (1979-2007)1.00",
+        "Ghanaian cedi (1979\\u20132007)1.00",
         "Ghanaian cedi1.00",
-        "Ghanaian cedis (1979-2007)1.00",
+        "Ghanaian cedis (1979\\u20132007)1.00",
         "Ghanaian cedis1.00",
         "Gibraltar Pound1.00",
         "Gibraltar pound1.00",
@@ -3921,7 +4547,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "INR1.00",
         "IQD1.00",
         "IRR1.00",
-        "IR\\u00a31.00",
         "ISK1.00",
         "ISK1.00",
         "ITL1.00",
@@ -3950,8 +4575,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Italian Lira1.00",
         "Italian lira1.00",
         "Italian liras1.00",
-        "J$1.00",
-        "JD1.00",
         "JMD1.00",
         "JOD1.00",
         "JPY1.00",
@@ -3963,8 +4586,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Jordanian Dinar1.00",
         "Jordanian dinar1.00",
         "Jordanian dinars1.00",
-        "Ksh1.00",
-        "KD1.00",
         "KES1.00",
         "KGS1.00",
         "KHR1.00",
@@ -3988,15 +4609,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Kyrgystani Som1.00",
         "Kyrgystani som1.00",
         "Kyrgystani soms1.00",
-        "Kz1.00",
-        "K\\u010d1.00",
         "HNL1.00",
         "LAK1.00",
         "LAK1.00",
         "LBP1.00",
-        "LD1.00",
         "LKR1.00",
-        "LB\\u00a31.00",
         "LRD1.00",
         "LRD1.00",
         "LSL1.00",
@@ -4042,7 +4659,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Lithuanian litai1.00",
         "Lithuanian talonas1.00",
         "Lithuanian talonases1.00",
-        "Lm1.00",
         "Luxembourgian Convertible Franc1.00",
         "Luxembourg Financial Franc1.00",
         "Luxembourgian Franc1.00",
@@ -4075,7 +4691,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "MTL1.00",
         "MTP1.00",
         "MTP1.00",
-        "MTn1.00",
         "MUR1.00",
         "MUR1.00",
         "MVR1.00",
@@ -4128,12 +4743,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Mauritian rupee1.00",
         "Mauritian rupees1.00",
         "Mexican Peso1.00",
-        "Mexican Silver Peso (1861-1992)1.00",
+        "Mexican Silver Peso (1861\\u20131992)1.00",
         "Mexican Investment Unit1.00",
         "Mexican peso1.00",
         "Mexican pesos1.00",
-        "Mexican silver peso (1861-1992)1.00",
-        "Mexican silver pesos (1861-1992)1.00",
+        "Mexican silver peso (1861\\u20131992)1.00",
+        "Mexican silver pesos (1861\\u20131992)1.00",
         "Mexican investment unit1.00",
         "Mexican investment units1.00",
         "Moldovan Leu1.00",
@@ -4154,18 +4769,14 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Mozambican escudos1.00",
         "Mozambican metical1.00",
         "Mozambican meticals1.00",
-        "Mt1.00",
-        "Myanma Kyat1.00",
-        "Myanma kyat1.00",
-        "Myanma kyats1.00",
-        "N$1.00",
+        "Myanmar Kyat1.00",
+        "Myanmar kyat1.00",
+        "Myanmar kyats1.00",
         "NAD1.00",
-        "NAf.1.00",
         "NGN1.00",
         "NIC1.00",
         "NIO1.00",
         "NIO1.00",
-        "Nkr1.00",
         "NLG1.00",
         "NLG1.00",
         "NOK1.00",
@@ -4191,11 +4802,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "New Zealand dollar1.00",
         "New Zealand dollars1.00",
         "Nicaraguan C\\u00f3rdoba1.00",
-        "Nicaraguan C\\u00f3rdoba (1988-1991)1.00",
+        "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
         "Nicaraguan c\\u00f3rdoba1.00",
         "Nicaraguan c\\u00f3rdobas1.00",
-        "Nicaraguan c\\u00f3rdoba (1988-1991)1.00",
-        "Nicaraguan c\\u00f3rdobas (1988-1991)1.00",
+        "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
+        "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
         "Nigerian Naira1.00",
         "Nigerian naira1.00",
         "Nigerian nairas1.00",
@@ -4205,26 +4816,24 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Norwegian Krone1.00",
         "Norwegian krone1.00",
         "Norwegian kroner1.00",
-        "NPRs1.00",
-        "Nu.1.00",
         "OMR1.00",
-        "Mozambican Metical (1980-2006)1.00",
-        "Mozambican metical (1980-2006)1.00",
-        "Mozambican meticals (1980-2006)1.00",
-        "Romanian Lei (1952-2006)1.00",
-        "Romanian Leu (1952-2006)1.00",
-        "Romanian leu (1952-2006)1.00",
-        "Serbian Dinar (2002-2006)1.00",
-        "Serbian dinar (2002-2006)1.00",
-        "Serbian dinars (2002-2006)1.00",
-        "Sudanese Dinar (1992-2007)1.00",
-        "Sudanese Pound (1957-1998)1.00",
-        "Sudanese dinar (1992-2007)1.00",
-        "Sudanese dinars (1992-2007)1.00",
-        "Sudanese pound (1957-1998)1.00",
-        "Sudanese pounds (1957-1998)1.00",
-        "Turkish Lira (1922-2005)1.00",
-        "Turkish Lira (1922-2005)1.00",
+        "Mozambican Metical (1980\\u20132006)1.00",
+        "Mozambican metical (1980\\u20132006)1.00",
+        "Mozambican meticals (1980\\u20132006)1.00",
+        "Romanian Lei (1952\\u20132006)1.00",
+        "Romanian Leu (1952\\u20132006)1.00",
+        "Romanian leu (1952\\u20132006)1.00",
+        "Serbian Dinar (2002\\u20132006)1.00",
+        "Serbian dinar (2002\\u20132006)1.00",
+        "Serbian dinars (2002\\u20132006)1.00",
+        "Sudanese Dinar (1992\\u20132007)1.00",
+        "Sudanese Pound (1957\\u20131998)1.00",
+        "Sudanese dinar (1992\\u20132007)1.00",
+        "Sudanese dinars (1992\\u20132007)1.00",
+        "Sudanese pound (1957\\u20131998)1.00",
+        "Sudanese pounds (1957\\u20131998)1.00",
+        "Turkish Lira (1922\\u20132005)1.00",
+        "Turkish Lira (1922\\u20132005)1.00",
         "Omani Rial1.00",
         "Omani rial1.00",
         "Omani rials1.00",
@@ -4262,19 +4871,19 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Paraguayan guaranis1.00",
         "Peruvian Inti1.00",
         "Peruvian Nuevo Sol1.00",
-        "Peruvian Sol (1863-1965)1.00",
+        "Peruvian Sol (1863\\u20131965)1.00",
         "Peruvian inti1.00",
         "Peruvian intis1.00",
         "Peruvian nuevo sol1.00",
         "Peruvian nuevos soles1.00",
-        "Peruvian sol (1863-1965)1.00",
-        "Peruvian soles (1863-1965)1.00",
+        "Peruvian sol (1863\\u20131965)1.00",
+        "Peruvian soles (1863\\u20131965)1.00",
         "Philippine Peso1.00",
         "Philippine peso1.00",
         "Philippine pesos1.00",
         "Platinum1.00",
         "Platinum1.00",
-        "Polish Zloty (1950-1995)1.00",
+        "Polish Zloty (1950\\u20131995)1.00",
         "Polish Zloty1.00",
         "Polish zlotys1.00",
         "Polish zloty (PLZ)1.00",
@@ -4286,21 +4895,15 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Portuguese Guinea escudos1.00",
         "Portuguese escudo1.00",
         "Portuguese escudos1.00",
-        "PKRs1.00",
         "GTQ1.00",
         "QAR1.00",
-        "QR1.00",
         "Qatari Rial1.00",
         "Qatari rial1.00",
         "Qatari rials1.00",
-        "R1.00",
-        "R$1.00",
-        "RD$1.00",
         "RHD1.00",
         "RHD1.00",
         "RINET Funds1.00",
         "RINET Funds1.00",
-        "RM1.00",
         "CN\\u00a51.00",
         "ROL1.00",
         "ROL1.00",
@@ -4309,7 +4912,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "RSD1.00",
         "RSD1.00",
         "RUB1.00",
-        "RUB1.00",
         "RUR1.00",
         "RUR1.00",
         "RWF1.00",
@@ -4320,17 +4922,15 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Romanian Leu1.00",
         "Romanian lei1.00",
         "Romanian leu1.00",
-        "Rp1.00",
-        "Russian Ruble (1991-1998)1.00",
+        "Russian Ruble (1991\\u20131998)1.00",
         "Russian Ruble1.00",
-        "Russian ruble (1991-1998)1.00",
+        "Russian ruble (1991\\u20131998)1.00",
         "Russian ruble1.00",
-        "Russian rubles (1991-1998)1.00",
+        "Russian rubles (1991\\u20131998)1.00",
         "Russian rubles1.00",
         "Rwandan Franc1.00",
         "Rwandan franc1.00",
         "Rwandan francs1.00",
-        "S$1.00",
         "SAR1.00",
         "SBD1.00",
         "SCR1.00",
@@ -4344,19 +4944,15 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "SGD1.00",
         "SHP1.00",
         "SHP1.00",
-        "SI$1.00",
         "SIT1.00",
         "SIT1.00",
         "SKK1.00",
-        "Skr1.00",
-        "SLRs1.00",
         "SLL1.00",
         "SLL1.00",
         "SOS1.00",
         "SRD1.00",
         "SRD1.00",
         "SRG1.00",
-        "SRe1.00",
         "STD1.00",
         "SUR1.00",
         "SUR1.00",
@@ -4364,12 +4960,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "SVC1.00",
         "SYP1.00",
         "SZL1.00",
-        "Saint Helena Pound1.00",
-        "Saint Helena pound1.00",
-        "Saint Helena pounds1.00",
-        "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobra1.00",
-        "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobra1.00",
-        "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobras1.00",
+        "St. Helena Pound1.00",
+        "St. Helena pound1.00",
+        "St. Helena pounds1.00",
+        "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
+        "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
+        "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
         "Saudi Riyal1.00",
         "Saudi riyal1.00",
         "Saudi riyals1.00",
@@ -4379,8 +4975,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Seychellois Rupee1.00",
         "Seychellois rupee1.00",
         "Seychellois rupees1.00",
-        "Sf1.00",
-        "Ssh1.00",
         "Sierra Leonean Leone1.00",
         "Sierra Leonean leone1.00",
         "Sierra Leonean leones1.00",
@@ -4389,7 +4983,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Singapore Dollar1.00",
         "Singapore dollar1.00",
         "Singapore dollars1.00",
-        "Sk1.00",
         "Slovak Koruna1.00",
         "Slovak koruna1.00",
         "Slovak korunas1.00",
@@ -4448,14 +5041,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Syrian Pound1.00",
         "Syrian pound1.00",
         "Syrian pounds1.00",
-        "TSh1.00",
-        "T$1.00",
         "THB1.00",
         "TJR1.00",
         "TJR1.00",
         "TJS1.00",
         "TJS1.00",
-        "TL1.00",
         "TMM1.00",
         "TMM1.00",
         "TND1.00",
@@ -4466,7 +5056,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "TRL1.00",
         "TRY1.00",
         "TRY1.00",
-        "TT$1.00",
         "TTD1.00",
         "TWD1.00",
         "TZS1.00",
@@ -4490,13 +5079,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Timorese Escudo1.00",
         "Timorese escudo1.00",
         "Timorese escudos1.00",
-        "Tk1.00",
         "Tongan Pa\\u02bbanga1.00",
         "Tongan pa\\u02bbanga1.00",
         "Tongan pa\\u02bbanga1.00",
-        "Trinidad and Tobago Dollar1.00",
-        "Trinidad and Tobago dollar1.00",
-        "Trinidad and Tobago dollars1.00",
+        "Trinidad & Tobago Dollar1.00",
+        "Trinidad & Tobago dollar1.00",
+        "Trinidad & Tobago dollars1.00",
         "Tunisian Dinar1.00",
         "Tunisian dinar1.00",
         "Tunisian dinars1.00",
@@ -4506,7 +5094,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Turkmenistani Manat1.00",
         "Turkmenistani manat1.00",
         "Turkmenistani manat1.00",
-        "USh1.00",
         "UAE dirham1.00",
         "UAE dirhams1.00",
         "UAH1.00",
@@ -4515,7 +5102,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "UGS1.00",
         "UGS1.00",
         "UGX1.00",
-        "UM1.00",
         "US Dollar (Next day)1.00",
         "US Dollar (Same day)1.00",
         "US Dollar1.00",
@@ -4537,11 +5123,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "UYU1.00",
         "UZS1.00",
         "UZS1.00",
-        "Ugandan Shilling (1966-1987)1.00",
+        "Ugandan Shilling (1966\\u20131987)1.00",
         "Ugandan Shilling1.00",
-        "Ugandan shilling (1966-1987)1.00",
+        "Ugandan shilling (1966\\u20131987)1.00",
         "Ugandan shilling1.00",
-        "Ugandan shillings (1966-1987)1.00",
+        "Ugandan shillings (1966\\u20131987)1.00",
         "Ugandan shillings1.00",
         "Ukrainian Hryvnia1.00",
         "Ukrainian Karbovanets1.00",
@@ -4552,33 +5138,31 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Colombian Real Value Unit1.00",
         "United Arab Emirates Dirham1.00",
         "Unknown Currency1.00",
-        "$U1.00",
-        "Uruguayan Peso (1975-1993)1.00",
+        "Uruguayan Peso (1975\\u20131993)1.00",
         "Uruguayan Peso1.00",
         "Uruguayan Peso (Indexed Units)1.00",
-        "Uruguayan peso (1975-1993)1.00",
+        "Uruguayan peso (1975\\u20131993)1.00",
         "Uruguayan peso (indexed units)1.00",
         "Uruguayan peso1.00",
-        "Uruguayan pesos (1975-1993)1.00",
+        "Uruguayan pesos (1975\\u20131993)1.00",
         "Uruguayan pesos (indexed units)1.00",
         "Uruguayan pesos1.00",
-        "Uzbekistan Som1.00",
-        "Uzbekistan som1.00",
-        "Uzbekistan som1.00",
+        "Uzbekistani Som1.00",
+        "Uzbekistani som1.00",
+        "Uzbekistani som1.00",
         "VEB1.00",
         "VEF1.00",
         "VND1.00",
-        "VT1.00",
         "VUV1.00",
         "Vanuatu Vatu1.00",
         "Vanuatu vatu1.00",
         "Vanuatu vatus1.00",
         "Venezuelan Bol\\u00edvar1.00",
-        "Venezuelan Bol\\u00edvar (1871-2008)1.00",
+        "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
         "Venezuelan bol\\u00edvar1.00",
         "Venezuelan bol\\u00edvars1.00",
-        "Venezuelan bol\\u00edvar (1871-2008)1.00",
-        "Venezuelan bol\\u00edvars (1871-2008)1.00",
+        "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
+        "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
         "Vietnamese Dong1.00",
         "Vietnamese dong1.00",
         "Vietnamese dong1.00",
@@ -4644,16 +5228,15 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Yemeni dinars1.00",
         "Yemeni rial1.00",
         "Yemeni rials1.00",
-        "Yugoslavian Convertible Dinar (1990-1992)1.00",
-        "Yugoslavian Hard Dinar (1966-1990)1.00",
-        "Yugoslavian New Dinar (1994-2002)1.00",
-        "Yugoslavian convertible dinar (1990-1992)1.00",
-        "Yugoslavian convertible dinars (1990-1992)1.00",
-        "Yugoslavian hard dinar (1966-1990)1.00",
-        "Yugoslavian hard dinars (1966-1990)1.00",
-        "Yugoslavian new dinar (1994-2002)1.00",
-        "Yugoslavian new dinars (1994-2002)1.00",
-        "Z$1.00",
+        "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
+        "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
+        "Yugoslavian New Dinar (1994\\u20132002)1.00",
+        "Yugoslavian convertible dinar (1990\\u20131992)1.00",
+        "Yugoslavian convertible dinars (1990\\u20131992)1.00",
+        "Yugoslavian hard dinar (1966\\u20131990)1.00",
+        "Yugoslavian hard dinars (1966\\u20131990)1.00",
+        "Yugoslavian new dinar (1994\\u20132002)1.00",
+        "Yugoslavian new dinars (1994\\u20132002)1.00",
         "ZAL1.00",
         "ZAL1.00",
         "ZAR1.00",
@@ -4664,44 +5247,31 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "ZRZ1.00",
         "ZRZ1.00",
         "ZWD1.00",
-        "Zairean New Zaire (1993-1998)1.00",
-        "Zairean Zaire (1971-1993)1.00",
-        "Zairean new zaire (1993-1998)1.00",
-        "Zairean new zaires (1993-1998)1.00",
-        "Zairean zaire (1971-1993)1.00",
-        "Zairean zaires (1971-1993)1.00",
+        "Zairean New Zaire (1993\\u20131998)1.00",
+        "Zairean Zaire (1971\\u20131993)1.00",
+        "Zairean new zaire (1993\\u20131998)1.00",
+        "Zairean new zaires (1993\\u20131998)1.00",
+        "Zairean zaire (1971\\u20131993)1.00",
+        "Zairean zaires (1971\\u20131993)1.00",
         "Zambian Kwacha1.00",
         "Zambian kwacha1.00",
         "Zambian kwachas1.00",
-        "Zimbabwean Dollar (1980-2008)1.00",
-        "Zimbabwean dollar (1980-2008)1.00",
-        "Zimbabwean dollars (1980-2008)1.00",
+        "Zimbabwean Dollar (1980\\u20132008)1.00",
+        "Zimbabwean dollar (1980\\u20132008)1.00",
+        "Zimbabwean dollars (1980\\u20132008)1.00",
         "euro1.00",
         "euros1.00",
-        "man.1.00",
-        "Turkish lira (1922-2005)1.00",
+        "Turkish lira (1922\\u20132005)1.00",
         "special drawing rights1.00",
         "Colombian real value unit1.00",
         "Colombian real value units1.00",
-        "unknown/invalid currency1.00",
-        "z\\u01421.00",
+        "unknown currency1.00",
         "\\u00a31.00",
-        "CY\\u00a31.00",
         "\\u00a51.00",
-        "\\u0e3f1.00",
         "\\u20ab1.00",
-        "\\u20a11.00",
-        "Pts1.00",
         "\\u20aa1.00",
         "\\u20ac1.00",
         "\\u20b91.00",
-        "\\u20a61.00",
-        "\\u20ae1.00",
-        "IT\\u20a41.00",
-        // for GHS
-        // for PHP
-        // for PYG
-        // for UAH
         //
         // Following has extra text, should be parsed correctly too
         "$1.00 random",
@@ -4710,7 +5280,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 US dollars random",
         "1.00 Afghan Afghani random",
         "1.00 Afghan Afghani random",
-        "1.00 Afghan Afghanis (AFA) random",
+        "1.00 Afghan Afghanis (1927\\u20131992) random",
         "1.00 Afghan Afghanis random",
         "1.00 Albanian Lek random",
         "1.00 Albanian lek random",
@@ -4721,26 +5291,26 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Andorran Peseta random",
         "1.00 Andorran peseta random",
         "1.00 Andorran pesetas random",
-        "1.00 Angolan Kwanza (1977-1990) random",
-        "1.00 Angolan Readjusted Kwanza (1995-1999) random",
+        "1.00 Angolan Kwanza (1977\\u20131990) random",
+        "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
         "1.00 Angolan Kwanza random",
-        "1.00 Angolan New Kwanza (1990-2000) random",
-        "1.00 Angolan kwanza (1977-1991) random",
-        "1.00 Angolan readjusted kwanza (1995-1999) random",
+        "1.00 Angolan New Kwanza (1990\\u20132000) random",
+        "1.00 Angolan kwanza (1977\\u20131991) random",
+        "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
         "1.00 Angolan kwanza random",
-        "1.00 Angolan kwanzas (1977-1991) random",
-        "1.00 Angolan readjusted kwanzas (1995-1999) random",
+        "1.00 Angolan kwanzas (1977\\u20131991) random",
+        "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
         "1.00 Angolan kwanzas random",
-        "1.00 Angolan new kwanza (1990-2000) random",
-        "1.00 Angolan new kwanzas (1990-2000) random",
+        "1.00 Angolan new kwanza (1990\\u20132000) random",
+        "1.00 Angolan new kwanzas (1990\\u20132000) random",
         "1.00 Argentine Austral random",
-        "1.00 Argentine Peso (1983-1985) random",
+        "1.00 Argentine Peso (1983\\u20131985) random",
         "1.00 Argentine Peso random",
         "1.00 Argentine austral random",
         "1.00 Argentine australs random",
-        "1.00 Argentine peso (1983-1985) random",
+        "1.00 Argentine peso (1983\\u20131985) random",
         "1.00 Argentine peso random",
-        "1.00 Argentine pesos (1983-1985) random",
+        "1.00 Argentine pesos (1983\\u20131985) random",
         "1.00 Argentine pesos random",
         "1.00 Armenian Dram random",
         "1.00 Armenian dram random",
@@ -4753,11 +5323,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Austrian Schilling random",
         "1.00 Austrian schilling random",
         "1.00 Austrian schillings random",
-        "1.00 Azerbaijani Manat (1993-2006) random",
+        "1.00 Azerbaijani Manat (1993\\u20132006) random",
         "1.00 Azerbaijani Manat random",
-        "1.00 Azerbaijani manat (1993-2006) random",
+        "1.00 Azerbaijani manat (1993\\u20132006) random",
         "1.00 Azerbaijani manat random",
-        "1.00 Azerbaijani manats (1993-2006) random",
+        "1.00 Azerbaijani manats (1993\\u20132006) random",
         "1.00 Azerbaijani manats random",
         "1.00 Bahamian Dollar random",
         "1.00 Bahamian dollar random",
@@ -4771,10 +5341,10 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Barbadian Dollar random",
         "1.00 Barbadian dollar random",
         "1.00 Barbadian dollars random",
-        "1.00 Belarusian New Ruble (1994-1999) random",
+        "1.00 Belarusian New Ruble (1994\\u20131999) random",
         "1.00 Belarusian Ruble random",
-        "1.00 Belarusian new ruble (1994-1999) random",
-        "1.00 Belarusian new rubles (1994-1999) random",
+        "1.00 Belarusian new ruble (1994\\u20131999) random",
+        "1.00 Belarusian new rubles (1994\\u20131999) random",
         "1.00 Belarusian ruble random",
         "1.00 Belarusian rubles random",
         "1.00 Belgian Franc (convertible) random",
@@ -4805,35 +5375,35 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Bolivian Boliviano random",
         "1.00 Bolivian Bolivianos random",
         "1.00 Bosnia-Herzegovina Convertible Mark random",
-        "1.00 Bosnia-Herzegovina Dinar (1992-1994) random",
+        "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
         "1.00 Bosnia-Herzegovina convertible mark random",
         "1.00 Bosnia-Herzegovina convertible marks random",
-        "1.00 Bosnia-Herzegovina dinar (1992-1994) random",
-        "1.00 Bosnia-Herzegovina dinars (1992-1994) random",
+        "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
+        "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
         "1.00 Botswanan Pula random",
         "1.00 Botswanan pula random",
         "1.00 Botswanan pulas random",
-        "1.00 Brazilian New Cruzado (1989-1990) random",
-        "1.00 Brazilian Cruzado (1986-1989) random",
-        "1.00 Brazilian Cruzeiro (1990-1993) random",
-        "1.00 Brazilian New Cruzeiro (1967-1986) random",
-        "1.00 Brazilian Cruzeiro (1993-1994) random",
+        "1.00 Brazilian New Cruzado (1989\\u20131990) random",
+        "1.00 Brazilian Cruzado (1986\\u20131989) random",
+        "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
+        "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
+        "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
         "1.00 Brazilian Real random",
-        "1.00 Brazilian new cruzado (1989-1990) random",
-        "1.00 Brazilian new cruzados (1989-1990) random",
-        "1.00 Brazilian cruzado (1986-1989) random",
-        "1.00 Brazilian cruzados (1986-1989) random",
-        "1.00 Brazilian cruzeiro (1990-1993) random",
-        "1.00 Brazilian new cruzeiro (1967-1986) random",
-        "1.00 Brazilian cruzeiro (1993-1994) random",
-        "1.00 Brazilian cruzeiros (1990-1993) random",
-        "1.00 Brazilian new cruzeiros (1967-1986) random",
-        "1.00 Brazilian cruzeiros (1993-1994) random",
+        "1.00 Brazilian new cruzado (1989\\u20131990) random",
+        "1.00 Brazilian new cruzados (1989\\u20131990) random",
+        "1.00 Brazilian cruzado (1986\\u20131989) random",
+        "1.00 Brazilian cruzados (1986\\u20131989) random",
+        "1.00 Brazilian cruzeiro (1990\\u20131993) random",
+        "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
+        "1.00 Brazilian cruzeiro (1993\\u20131994) random",
+        "1.00 Brazilian cruzeiros (1990\\u20131993) random",
+        "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
+        "1.00 Brazilian cruzeiros (1993\\u20131994) random",
         "1.00 Brazilian real random",
         "1.00 Brazilian reals random",
-        "1.00 British Pound Sterling random",
-        "1.00 British pound sterling random",
-        "1.00 British pounds sterling random",
+        "1.00 British Pound random",
+        "1.00 British pound random",
+        "1.00 British pounds random",
         "1.00 Brunei Dollar random",
         "1.00 Brunei dollar random",
         "1.00 Brunei dollars random",
@@ -4982,11 +5552,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Georgian kupon larits random",
         "1.00 Georgian lari random",
         "1.00 Georgian laris random",
-        "1.00 Ghanaian Cedi (1979-2007) random",
+        "1.00 Ghanaian Cedi (1979\\u20132007) random",
         "1.00 Ghanaian Cedi random",
-        "1.00 Ghanaian cedi (1979-2007) random",
+        "1.00 Ghanaian cedi (1979\\u20132007) random",
         "1.00 Ghanaian cedi random",
-        "1.00 Ghanaian cedis (1979-2007) random",
+        "1.00 Ghanaian cedis (1979\\u20132007) random",
         "1.00 Ghanaian cedis random",
         "1.00 Gibraltar Pound random",
         "1.00 Gibraltar pound random",
@@ -5141,12 +5711,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Mauritian rupee random",
         "1.00 Mauritian rupees random",
         "1.00 Mexican Peso random",
-        "1.00 Mexican Silver Peso (1861-1992) random",
+        "1.00 Mexican Silver Peso (1861\\u20131992) random",
         "1.00 Mexican Investment Unit random",
         "1.00 Mexican peso random",
         "1.00 Mexican pesos random",
-        "1.00 Mexican silver peso (1861-1992) random",
-        "1.00 Mexican silver pesos (1861-1992) random",
+        "1.00 Mexican silver peso (1861\\u20131992) random",
+        "1.00 Mexican silver pesos (1861\\u20131992) random",
         "1.00 Mexican investment unit random",
         "1.00 Mexican investment units random",
         "1.00 Moldovan Leu random",
@@ -5167,9 +5737,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Mozambican escudos random",
         "1.00 Mozambican metical random",
         "1.00 Mozambican meticals random",
-        "1.00 Myanma Kyat random",
-        "1.00 Myanma kyat random",
-        "1.00 Myanma kyats random",
+        "1.00 Myanmar Kyat random",
+        "1.00 Myanmar kyat random",
+        "1.00 Myanmar kyats random",
         "1.00 Namibian Dollar random",
         "1.00 Namibian dollar random",
         "1.00 Namibian dollars random",
@@ -5188,11 +5758,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 New Zealand dollar random",
         "1.00 New Zealand dollars random",
         "1.00 Nicaraguan C\\u00f3rdoba random",
-        "1.00 Nicaraguan C\\u00f3rdoba (1988-1991) random",
+        "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
         "1.00 Nicaraguan c\\u00f3rdoba random",
         "1.00 Nicaraguan c\\u00f3rdoba random",
-        "1.00 Nicaraguan c\\u00f3rdoba (1988-1991) random",
-        "1.00 Nicaraguan c\\u00f3rdobas (1988-1991) random",
+        "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
+        "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
         "1.00 Nigerian Naira random",
         "1.00 Nigerian naira random",
         "1.00 Nigerian nairas random",
@@ -5202,23 +5772,23 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Norwegian Krone random",
         "1.00 Norwegian krone random",
         "1.00 Norwegian kroner random",
-        "1.00 Mozambican Metical (1980-2006) random",
-        "1.00 Mozambican metical (1980-2006) random",
-        "1.00 Mozambican meticals (1980-2006) random",
-        "1.00 Romanian Lei (1952-2006) random",
-        "1.00 Romanian Leu (1952-2006) random",
-        "1.00 Romanian leu (1952-2006) random",
-        "1.00 Serbian Dinar (2002-2006) random",
-        "1.00 Serbian dinar (2002-2006) random",
-        "1.00 Serbian dinars (2002-2006) random",
-        "1.00 Sudanese Dinar (1992-2007) random",
-        "1.00 Sudanese Pound (1957-1998) random",
-        "1.00 Sudanese dinar (1992-2007) random",
-        "1.00 Sudanese dinars (1992-2007) random",
-        "1.00 Sudanese pound (1957-1998) random",
-        "1.00 Sudanese pounds (1957-1998) random",
-        "1.00 Turkish Lira (1922-2005) random",
-        "1.00 Turkish Lira (1922-2005) random",
+        "1.00 Mozambican Metical (1980\\u20132006) random",
+        "1.00 Mozambican metical (1980\\u20132006) random",
+        "1.00 Mozambican meticals (1980\\u20132006) random",
+        "1.00 Romanian Lei (1952\\u20132006) random",
+        "1.00 Romanian Leu (1952\\u20132006) random",
+        "1.00 Romanian leu (1952\\u20132006) random",
+        "1.00 Serbian Dinar (2002\\u20132006) random",
+        "1.00 Serbian dinar (2002\\u20132006) random",
+        "1.00 Serbian dinars (2002\\u20132006) random",
+        "1.00 Sudanese Dinar (1992\\u20132007) random",
+        "1.00 Sudanese Pound (1957\\u20131998) random",
+        "1.00 Sudanese dinar (1992\\u20132007) random",
+        "1.00 Sudanese dinars (1992\\u20132007) random",
+        "1.00 Sudanese pound (1957\\u20131998) random",
+        "1.00 Sudanese pounds (1957\\u20131998) random",
+        "1.00 Turkish Lira (1922\\u20132005) random",
+        "1.00 Turkish Lira (1922\\u20132005) random",
         "1.00 Omani Rial random",
         "1.00 Omani rial random",
         "1.00 Omani rials random",
@@ -5238,19 +5808,19 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Paraguayan guaranis random",
         "1.00 Peruvian Inti random",
         "1.00 Peruvian Nuevo Sol random",
-        "1.00 Peruvian Sol (1863-1965) random",
+        "1.00 Peruvian Sol (1863\\u20131965) random",
         "1.00 Peruvian inti random",
         "1.00 Peruvian intis random",
         "1.00 Peruvian nuevo sol random",
         "1.00 Peruvian nuevos soles random",
-        "1.00 Peruvian sol (1863-1965) random",
-        "1.00 Peruvian soles (1863-1965) random",
+        "1.00 Peruvian sol (1863\\u20131965) random",
+        "1.00 Peruvian soles (1863\\u20131965) random",
         "1.00 Philippine Peso random",
         "1.00 Philippine peso random",
         "1.00 Philippine pesos random",
         "1.00 Platinum random",
         "1.00 Platinum random",
-        "1.00 Polish Zloty (1950-1995) random",
+        "1.00 Polish Zloty (1950\\u20131995) random",
         "1.00 Polish Zloty random",
         "1.00 Polish zlotys random",
         "1.00 Polish zloty (PLZ) random",
@@ -5273,21 +5843,21 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Romanian Leu random",
         "1.00 Romanian lei random",
         "1.00 Romanian leu random",
-        "1.00 Russian Ruble (1991-1998) random",
+        "1.00 Russian Ruble (1991\\u20131998) random",
         "1.00 Russian Ruble random",
-        "1.00 Russian ruble (1991-1998) random",
+        "1.00 Russian ruble (1991\\u20131998) random",
         "1.00 Russian ruble random",
-        "1.00 Russian rubles (1991-1998) random",
+        "1.00 Russian rubles (1991\\u20131998) random",
         "1.00 Russian rubles random",
         "1.00 Rwandan Franc random",
         "1.00 Rwandan franc random",
         "1.00 Rwandan francs random",
-        "1.00 Saint Helena Pound random",
-        "1.00 Saint Helena pound random",
-        "1.00 Saint Helena pounds random",
-        "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobra random",
-        "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobra random",
-        "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobras random",
+        "1.00 St. Helena Pound random",
+        "1.00 St. Helena pound random",
+        "1.00 St. Helena pounds random",
+        "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
+        "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
+        "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
         "1.00 Saudi Riyal random",
         "1.00 Saudi riyal random",
         "1.00 Saudi riyals random",
@@ -5381,9 +5951,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Timorese Escudo random",
         "1.00 Timorese escudo random",
         "1.00 Timorese escudos random",
-        "1.00 Trinidad and Tobago Dollar random",
-        "1.00 Trinidad and Tobago dollar random",
-        "1.00 Trinidad and Tobago dollars random",
+        "1.00 Trinidad & Tobago Dollar random",
+        "1.00 Trinidad & Tobago dollar random",
+        "1.00 Trinidad & Tobago dollars random",
         "1.00 Tunisian Dinar random",
         "1.00 Tunisian dinar random",
         "1.00 Tunisian dinars random",
@@ -5402,11 +5972,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 US dollars (next day) random",
         "1.00 US dollars (same day) random",
         "1.00 US dollars random",
-        "1.00 Ugandan Shilling (1966-1987) random",
+        "1.00 Ugandan Shilling (1966\\u20131987) random",
         "1.00 Ugandan Shilling random",
-        "1.00 Ugandan shilling (1966-1987) random",
+        "1.00 Ugandan shilling (1966\\u20131987) random",
         "1.00 Ugandan shilling random",
-        "1.00 Ugandan shillings (1966-1987) random",
+        "1.00 Ugandan shillings (1966\\u20131987) random",
         "1.00 Ugandan shillings random",
         "1.00 Ukrainian Hryvnia random",
         "1.00 Ukrainian Karbovanets random",
@@ -5417,26 +5987,26 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Colombian Real Value Unit random",
         "1.00 United Arab Emirates Dirham random",
         "1.00 Unknown Currency random",
-        "1.00 Uruguayan Peso (1975-1993) random",
+        "1.00 Uruguayan Peso (1975\\u20131993) random",
         "1.00 Uruguayan Peso random",
         "1.00 Uruguayan Peso (Indexed Units) random",
-        "1.00 Uruguayan peso (1975-1993) random",
+        "1.00 Uruguayan peso (1975\\u20131993) random",
         "1.00 Uruguayan peso (indexed units) random",
         "1.00 Uruguayan peso random",
-        "1.00 Uruguayan pesos (1975-1993) random",
+        "1.00 Uruguayan pesos (1975\\u20131993) random",
         "1.00 Uruguayan pesos (indexed units) random",
-        "1.00 Uzbekistan Som random",
-        "1.00 Uzbekistan som random",
-        "1.00 Uzbekistan som random",
+        "1.00 Uzbekistani Som random",
+        "1.00 Uzbekistani som random",
+        "1.00 Uzbekistani som random",
         "1.00 Vanuatu Vatu random",
         "1.00 Vanuatu vatu random",
         "1.00 Vanuatu vatus random",
         "1.00 Venezuelan Bol\\u00edvar random",
-        "1.00 Venezuelan Bol\\u00edvar (1871-2008) random",
+        "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
         "1.00 Venezuelan bol\\u00edvar random",
         "1.00 Venezuelan bol\\u00edvars random",
-        "1.00 Venezuelan bol\\u00edvar (1871-2008) random",
-        "1.00 Venezuelan bol\\u00edvars (1871-2008) random",
+        "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
+        "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
         "1.00 Vietnamese Dong random",
         "1.00 Vietnamese dong random",
         "1.00 Vietnamese dong random",
@@ -5455,34 +6025,34 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "1.00 Yemeni dinars random",
         "1.00 Yemeni rial random",
         "1.00 Yemeni rials random",
-        "1.00 Yugoslavian Convertible Dinar (1990-1992) random",
-        "1.00 Yugoslavian Hard Dinar (1966-1990) random",
-        "1.00 Yugoslavian New Dinar (1994-2002) random",
-        "1.00 Yugoslavian convertible dinar (1990-1992) random",
-        "1.00 Yugoslavian convertible dinars (1990-1992) random",
-        "1.00 Yugoslavian hard dinar (1966-1990) random",
-        "1.00 Yugoslavian hard dinars (1966-1990) random",
-        "1.00 Yugoslavian new dinar (1994-2002) random",
-        "1.00 Yugoslavian new dinars (1994-2002) random",
-        "1.00 Zairean New Zaire (1993-1998) random",
-        "1.00 Zairean Zaire (1971-1993) random",
-        "1.00 Zairean new zaire (1993-1998) random",
-        "1.00 Zairean new zaires (1993-1998) random",
-        "1.00 Zairean zaire (1971-1993) random",
-        "1.00 Zairean zaires (1971-1993) random",
+        "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
+        "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
+        "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
+        "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
+        "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
+        "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
+        "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
+        "1.00 Yugoslavian new dinar (1994\\u20132002) random",
+        "1.00 Yugoslavian new dinars (1994\\u20132002) random",
+        "1.00 Zairean New Zaire (1993\\u20131998) random",
+        "1.00 Zairean Zaire (1971\\u20131993) random",
+        "1.00 Zairean new zaire (1993\\u20131998) random",
+        "1.00 Zairean new zaires (1993\\u20131998) random",
+        "1.00 Zairean zaire (1971\\u20131993) random",
+        "1.00 Zairean zaires (1971\\u20131993) random",
         "1.00 Zambian Kwacha random",
         "1.00 Zambian kwacha random",
         "1.00 Zambian kwachas random",
-        "1.00 Zimbabwean Dollar (1980-2008) random",
-        "1.00 Zimbabwean dollar (1980-2008) random",
-        "1.00 Zimbabwean dollars (1980-2008) random",
+        "1.00 Zimbabwean Dollar (1980\\u20132008) random",
+        "1.00 Zimbabwean dollar (1980\\u20132008) random",
+        "1.00 Zimbabwean dollars (1980\\u20132008) random",
         "1.00 euro random",
         "1.00 euros random",
-        "1.00 Turkish lira (1922-2005) random",
+        "1.00 Turkish lira (1922\\u20132005) random",
         "1.00 special drawing rights random",
         "1.00 Colombian real value unit random",
         "1.00 Colombian real value units random",
-        "1.00 unknown/invalid currency random",
+        "1.00 unknown currency random",
     };
 
     const char* WRONG_DATA[] = {
@@ -5523,24 +6093,24 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "AW1.00",
         "AZ1.00",
         "Afghan Afghan1.00",
-        "Afghan Afghani (1927-20021.00",
+        "Afghan Afghani (1927\\u201320021.00",
         "Afl1.00",
         "Albanian Le1.00",
         "Algerian Dina1.00",
         "Andorran Peset1.00",
         "Angolan Kwanz1.00",
-        "Angolan Kwanza (1977-19901.00",
-        "Angolan Readjusted Kwanza (1995-19991.00",
-        "Angolan New Kwanza (1990-20001.00",
+        "Angolan Kwanza (1977\\u201319901.00",
+        "Angolan Readjusted Kwanza (1995\\u201319991.00",
+        "Angolan New Kwanza (1990\\u201320001.00",
         "Argentine Austra1.00",
         "Argentine Pes1.00",
-        "Argentine Peso (1983-19851.00",
+        "Argentine Peso (1983\\u201319851.00",
         "Armenian Dra1.00",
         "Aruban Flori1.00",
         "Australian Dolla1.00",
         "Austrian Schillin1.00",
         "Azerbaijani Mana1.00",
-        "Azerbaijani Manat (1993-20061.00",
+        "Azerbaijani Manat (1993\\u201320061.00",
         "B1.00",
         "BA1.00",
         "BB1.00",
@@ -5563,7 +6133,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Bangladeshi Tak1.00",
         "Barbadian Dolla1.00",
         "Bds1.00",
-        "Belarusian New Ruble (1994-19991.00",
+        "Belarusian New Ruble (1994\\u201319991.00",
         "Belarusian Rubl1.00",
         "Belgian Fran1.00",
         "Belgian Franc (convertible1.00",
@@ -5580,8 +6150,8 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Brazilian Cruzad1.00",
         "Brazilian Cruzado Nov1.00",
         "Brazilian Cruzeir1.00",
-        "Brazilian Cruzeiro (1990-19931.00",
-        "Brazilian New Cruzeiro (1967-19861.00",
+        "Brazilian Cruzeiro (1990\\u201319931.00",
+        "Brazilian New Cruzeiro (1967\\u201319861.00",
         "Brazilian Rea1.00",
         "British Pound Sterlin1.00",
         "Brunei Dolla1.00",
@@ -5592,8 +6162,6 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "C1.00",
         "CA1.00",
         "CD1.00",
-        "CFA Franc BCEA1.00",
-        "CFA Franc BEA1.00",
         "CFP Fran1.00",
         "CFP1.00",
         "CH1.00",
@@ -5690,7 +6258,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Georgian Kupon Lari1.00",
         "Georgian Lar1.00",
         "Ghanaian Ced1.00",
-        "Ghanaian Cedi (1979-20071.00",
+        "Ghanaian Cedi (1979\\u201320071.00",
         "Gibraltar Poun1.00",
         "Gol1.00",
         "Greek Drachm1.00",
@@ -5796,7 +6364,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Mauritanian Ouguiy1.00",
         "Mauritian Rupe1.00",
         "Mexican Pes1.00",
-        "Mexican Silver Peso (1861-19921.00",
+        "Mexican Silver Peso (1861\\u201319921.00",
         "Mexican Investment Uni1.00",
         "Moldovan Le1.00",
         "Mongolian Tugri1.00",
@@ -5804,7 +6372,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Moroccan Fran1.00",
         "Mozambican Escud1.00",
         "Mozambican Metica1.00",
-        "Myanma Kya1.00",
+        "Myanmar Kya1.00",
         "N1.00",
         "NA1.00",
         "NAf1.00",
@@ -5821,7 +6389,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Dutch Guilde1.00",
         "Israeli New Sheqe1.00",
         "New Zealand Dolla1.00",
-        "Nicaraguan C\\u00f3rdoba (1988-19911.00",
+        "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
         "Nicaraguan C\\u00f3rdob1.00",
         "Nigerian Nair1.00",
         "North Korean Wo1.00",
@@ -5829,11 +6397,11 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Nr1.00",
         "OM1.00",
         "Old Mozambican Metica1.00",
-        "Romanian Leu (1952-20061.00",
-        "Serbian Dinar (2002-20061.00",
-        "Sudanese Dinar (1992-20071.00",
-        "Sudanese Pound (1957-19981.00",
-        "Turkish Lira (1922-20051.00",
+        "Romanian Leu (1952\\u201320061.00",
+        "Serbian Dinar (2002\\u201320061.00",
+        "Sudanese Dinar (1992\\u201320071.00",
+        "Sudanese Pound (1957\\u201319981.00",
+        "Turkish Lira (1922\\u201320051.00",
         "Omani Ria1.00",
         "PA1.00",
         "PE1.00",
@@ -5849,12 +6417,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Papua New Guinean Kin1.00",
         "Paraguayan Guaran1.00",
         "Peruvian Int1.00",
-        "Peruvian Sol (1863-19651.00",
+        "Peruvian Sol (1863\\u201319651.00",
         "Peruvian Sol Nuev1.00",
         "Philippine Pes1.00",
         "Platinu1.00",
         "Polish Zlot1.00",
-        "Polish Zloty (1950-19951.00",
+        "Polish Zloty (1950\\u201319951.00",
         "Portuguese Escud1.00",
         "Portuguese Guinea Escud1.00",
         "Pr1.00",
@@ -5870,7 +6438,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Rhodesian Dolla1.00",
         "Romanian Le1.00",
         "Russian Rubl1.00",
-        "Russian Ruble (1991-19981.00",
+        "Russian Ruble (1991\\u201319981.00",
         "Rwandan Fran1.00",
         "S1.00",
         "SA1.00",
@@ -5890,8 +6458,8 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "SV1.00",
         "SY1.00",
         "SZ1.00",
-        "Saint Helena Poun1.00",
-        "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobr1.00",
+        "St. Helena Poun1.00",
+        "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
         "Saudi Riya1.00",
         "Serbian Dina1.00",
         "Seychellois Rupe1.00",
@@ -5938,7 +6506,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Thai Bah1.00",
         "Timorese Escud1.00",
         "Tongan Pa\\u20bbang1.00",
-        "Trinidad and Tobago Dolla1.00",
+        "Trinidad & Tobago Dolla1.00",
         "Tunisian Dina1.00",
         "Turkish Lir1.00",
         "Turkmenistani Mana1.00",
@@ -5953,17 +6521,17 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "UY1.00",
         "UZ1.00",
         "Ugandan Shillin1.00",
-        "Ugandan Shilling (1966-19871.00",
+        "Ugandan Shilling (1966\\u201319871.00",
         "Ukrainian Hryvni1.00",
         "Ukrainian Karbovanet1.00",
         "Colombian Real Value Uni1.00",
         "United Arab Emirates Dirha1.00",
         "Unknown Currenc1.00",
         "Ur1.00",
-        "Uruguay Peso (1975-19931.00",
+        "Uruguay Peso (1975\\u201319931.00",
         "Uruguay Peso Uruguay1.00",
         "Uruguay Peso (Indexed Units1.00",
-        "Uzbekistan So1.00",
+        "Uzbekistani So1.00",
         "V1.00",
         "VE1.00",
         "VN1.00",
@@ -5972,6 +6540,8 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Venezuelan Bol\\u00edva1.00",
         "Venezuelan Bol\\u00edvar Fuert1.00",
         "Vietnamese Don1.00",
+        "West African CFA Fran1.00",
+        "Central African CFA Fran1.00",
         "WIR Eur1.00",
         "WIR Fran1.00",
         "WS1.00",
@@ -5993,17 +6563,17 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
         "Yemeni Dina1.00",
         "Yemeni Ria1.00",
         "Yugoslavian Convertible Dina1.00",
-        "Yugoslavian Hard Dinar (1966-19901.00",
+        "Yugoslavian Hard Dinar (1966\\u201319901.00",
         "Yugoslavian New Dina1.00",
         "Z1.00",
         "ZA1.00",
         "ZM1.00",
         "ZR1.00",
         "ZW1.00",
-        "Zairean New Zaire (1993-19981.00",
+        "Zairean New Zaire (1993\\u201319981.00",
         "Zairean Zair1.00",
         "Zambian Kwach1.00",
-        "Zimbabwean Dollar (1980-20081.00",
+        "Zimbabwean Dollar (1980\\u201320081.00",
         "dra1.00",
         "lar1.00",
         "le1.00",
@@ -6012,17 +6582,20 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
     };
 
     Locale locale("en_US");
-    for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
+    for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
       UnicodeString formatted = ctou(DATA[i]);
       UErrorCode status = U_ZERO_ERROR;
-      NumberFormat* numFmt = NumberFormat::createInstance(locale, NumberFormat::kCurrencyStyle, status);
-      Formattable parseResult;
-      ParsePosition parsePos(0); 
+      NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
       if (numFmt != NULL && U_SUCCESS(status)) {
-          numFmt->parseCurrency(formatted, parseResult, parsePos);
-          if ( parseResult.getDouble(status) != 1.0 || U_FAILURE(status) || parsePos.getErrorIndex() != -1 ) {
-              errln("wrong parsing, " + formatted);
-              errln("data: " + formatted);
+          ParsePosition parsePos;
+          LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
+          if (parsePos.getIndex() > 0) {
+              double doubleVal = currAmt->getNumber().getDouble(status);
+              if ( doubleVal != 1.0 ) {
+                  errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
+              }
+          } else {
+              errln("Failed to parse as currency: " + formatted);
           }
       } else {
           dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
@@ -6032,18 +6605,16 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
       delete numFmt;
     }
 
-    for (uint32_t i=0; i<sizeof(WRONG_DATA)/sizeof(WRONG_DATA[0]); ++i) {
+    for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
       UnicodeString formatted = ctou(WRONG_DATA[i]);
       UErrorCode status = U_ZERO_ERROR;
-      NumberFormat* numFmt = NumberFormat::createInstance(locale, NumberFormat::kCurrencyStyle, status);
-      Formattable parseResult;
+      NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
       if (numFmt != NULL && U_SUCCESS(status)) {
-          numFmt->parse(formatted, parseResult, status);
-          if (!U_FAILURE(status) ||
-              (parseResult.getType() == Formattable::kDouble &&
-               parseResult.getDouble() == 1.0)) {
-              errln("parsed but should not be: " + formatted);
-              errln("data: " + formatted);
+          ParsePosition parsePos;
+          LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
+          if (parsePos.getIndex() > 0) {
+              double doubleVal = currAmt->getNumber().getDouble(status);
+              errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
           }
       } else {
           dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
@@ -6155,19 +6726,19 @@ void NumberFormatTest::TestFieldPositionIterator() {
 void NumberFormatTest::TestFormatAttributes() {
   Locale locale("en_US");
   UErrorCode status = U_ZERO_ERROR;
-  DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, NumberFormat::kCurrencyStyle, status);
+  DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
     if (failure(status, "NumberFormat::createInstance", TRUE)) return;
   double val = 12345.67;
   
   {
     int32_t expected[] = {
-      NumberFormat::kCurrencyField, 0, 1,
-      NumberFormat::kGroupingSeparatorField, 3, 4,
-      NumberFormat::kIntegerField, 1, 7,
-      NumberFormat::kDecimalSeparatorField, 7, 8,
-      NumberFormat::kFractionField, 8, 10,
+      UNUM_CURRENCY_FIELD, 0, 1,
+      UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
+      UNUM_INTEGER_FIELD, 1, 7,
+      UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
+      UNUM_FRACTION_FIELD, 8, 10,
     };
-    int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+    int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
 
     FieldPositionIterator posIter;
     UnicodeString result;
@@ -6175,32 +6746,32 @@ void NumberFormatTest::TestFormatAttributes() {
     expectPositions(posIter, expected, tupleCount, result);
   }
   {
-    FieldPosition fp(NumberFormat::kIntegerField);
+    FieldPosition fp(UNUM_INTEGER_FIELD);
     UnicodeString result;
     decFmt->format(val, result, fp);
-    expectPosition(fp, NumberFormat::kIntegerField, 1, 7, result);
+    expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
   }
   {
-    FieldPosition fp(NumberFormat::kFractionField);
+    FieldPosition fp(UNUM_FRACTION_FIELD);
     UnicodeString result;
     decFmt->format(val, result, fp);
-    expectPosition(fp, NumberFormat::kFractionField, 8, 10, result);
+    expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
   }
   delete decFmt;
 
-  decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, NumberFormat::kScientificStyle, status);
+  decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
   val = -0.0000123;
   {
     int32_t expected[] = {
-      NumberFormat::kSignField, 0, 1,
-      NumberFormat::kIntegerField, 1, 2,
-      NumberFormat::kDecimalSeparatorField, 2, 3,
-      NumberFormat::kFractionField, 3, 5,
-      NumberFormat::kExponentSymbolField, 5, 6,
-      NumberFormat::kExponentSignField, 6, 7,
-      NumberFormat::kExponentField, 7, 8
+      UNUM_SIGN_FIELD, 0, 1,
+      UNUM_INTEGER_FIELD, 1, 2,
+      UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
+      UNUM_FRACTION_FIELD, 3, 5,
+      UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
+      UNUM_EXPONENT_SIGN_FIELD, 6, 7,
+      UNUM_EXPONENT_FIELD, 7, 8
     };
-    int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+    int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
 
     FieldPositionIterator posIter;
     UnicodeString result;
@@ -6208,16 +6779,16 @@ void NumberFormatTest::TestFormatAttributes() {
     expectPositions(posIter, expected, tupleCount, result);
   }
   {
-    FieldPosition fp(NumberFormat::kIntegerField);
+    FieldPosition fp(UNUM_INTEGER_FIELD);
     UnicodeString result;
     decFmt->format(val, result, fp);
-    expectPosition(fp, NumberFormat::kIntegerField, 1, 2, result);
+    expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
   }
   {
-    FieldPosition fp(NumberFormat::kFractionField);
+    FieldPosition fp(UNUM_FRACTION_FIELD);
     UnicodeString result;
     decFmt->format(val, result, fp);
-    expectPosition(fp, NumberFormat::kFractionField, 3, 5, result);
+    expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
   }
   delete decFmt;
 
@@ -6226,17 +6797,17 @@ void NumberFormatTest::TestFormatAttributes() {
 
 const char* attrString(int32_t attrId) {
   switch (attrId) {
-    case NumberFormat::kIntegerField: return "integer";
-    case NumberFormat::kFractionField: return "fraction";
-    case NumberFormat::kDecimalSeparatorField: return "decimal separator";
-    case NumberFormat::kExponentSymbolField: return "exponent symbol";
-    case NumberFormat::kExponentSignField: return "exponent sign";
-    case NumberFormat::kExponentField: return "exponent";
-    case NumberFormat::kGroupingSeparatorField: return "grouping separator";
-    case NumberFormat::kCurrencyField: return "currency";
-    case NumberFormat::kPercentField: return "percent";
-    case NumberFormat::kPermillField: return "permille";
-    case NumberFormat::kSignField: return "sign";
+    case UNUM_INTEGER_FIELD: return "integer";
+    case UNUM_FRACTION_FIELD: return "fraction";
+    case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
+    case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
+    case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
+    case UNUM_EXPONENT_FIELD: return "exponent";
+    case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
+    case UNUM_CURRENCY_FIELD: return "currency";
+    case UNUM_PERCENT_FIELD: return "percent";
+    case UNUM_PERMILL_FIELD: return "permille";
+    case UNUM_SIGN_FIELD: return "sign";
     default: return "";
   }
 }
@@ -6314,8 +6885,7 @@ void NumberFormatTest::TestDecimal() {
 
     {
         UErrorCode status = U_ZERO_ERROR;
-        NumberFormat *fmtr = NumberFormat::createInstance(
-                Locale::getUS(), NumberFormat::kNumberStyle, status);
+        NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
         if (U_FAILURE(status) || fmtr == NULL) {
             dataerrln("Unable to create NumberFormat");
         } else {
@@ -6333,8 +6903,7 @@ void NumberFormatTest::TestDecimal() {
         // Check formatting a DigitList.  DigitList is internal, but this is
         // a critical interface that must work.
         UErrorCode status = U_ZERO_ERROR;
-        NumberFormat *fmtr = NumberFormat::createInstance(
-                Locale::getUS(), NumberFormat::kNumberStyle, status);
+        NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
         if (U_FAILURE(status) || fmtr == NULL) {
             dataerrln("Unable to create NumberFormat");
         } else {
@@ -6365,8 +6934,7 @@ void NumberFormatTest::TestDecimal() {
     {
         // Check a parse with a formatter with a multiplier.
         UErrorCode status = U_ZERO_ERROR;
-        NumberFormat *fmtr = NumberFormat::createInstance(
-                Locale::getUS(), NumberFormat::kPercentStyle, status);
+        NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
         if (U_FAILURE(status) || fmtr == NULL) {
             dataerrln("Unable to create NumberFormat");
         } else {
@@ -6380,11 +6948,15 @@ void NumberFormatTest::TestDecimal() {
         }
     }
     
+#if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
+    /*
+     * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
+     * See #9463
+     */
     {
         // Check that a parse returns a decimal number with full accuracy
         UErrorCode status = U_ZERO_ERROR;
-        NumberFormat *fmtr = NumberFormat::createInstance(
-                Locale::getUS(), NumberFormat::kNumberStyle, status);
+        NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
         if (U_FAILURE(status) || fmtr == NULL) {
             dataerrln("Unable to create NumberFormat");
         } else {
@@ -6398,6 +6970,7 @@ void NumberFormatTest::TestDecimal() {
             delete fmtr;
         }
     }
+#endif
 
 }
 
@@ -6440,31 +7013,10 @@ void NumberFormatTest::TestExponentParse() {
         return; 
     } 
     
-#if 0
-    symbols->setSymbol(DecimalFormatSymbols::kExponentialSymbol,"e"); 
-    // create format instance 
-    status = U_ZERO_ERROR; 
-    DecimalFormat fmt("#####", symbols, status); 
-       if(U_FAILURE(status)) { 
-        errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); 
-    } 
-    // parse the text 
-    fmt.parse("123E4", result, parsePos); 
-    if(result.getType() != Formattable::kDouble &&  
-       result.getDouble() != (double)123 && 
-       parsePos.getIndex() != 3 
-       ) 
-    { 
-        errln("ERROR: parse failed - expected 123.0, 3  - returned %d, %i", 
-               result.getDouble(), parsePos.getIndex()); 
-    } 
-#else
     // create format instance 
     status = U_ZERO_ERROR; 
     DecimalFormat fmt("#####", symbols, status); 
-       if(U_FAILURE(status)) { 
+    if(U_FAILURE(status)) { 
         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); 
     } 
     
@@ -6478,7 +7030,1729 @@ void NumberFormatTest::TestExponentParse() {
         errln("ERROR: parse failed - expected 5.06E-27, 8  - returned %d, %i", 
               result.getDouble(), parsePos.getIndex()); 
     } 
-#endif
 } 
 
+void NumberFormatTest::TestExplicitParents() {
+
+    /* Test that number formats are properly inherited from es_419 */
+    /* These could be subject to change if the CLDR data changes */
+    static const char* parentLocaleTests[][2]= {
+    /* locale ID */  /* expected */
+    {"es_CO", "1.250,75" },
+    {"es_ES", "1.250,75" },
+    {"es_GQ", "1.250,75" },
+    {"es_MX", "1,250.75" },
+    {"es_US", "1,250.75" },
+    {"es_VE", "1.250,75" },
+    };
+
+    UnicodeString s;
+
+    for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
+        UErrorCode status = U_ZERO_ERROR;
+        const char *localeID = parentLocaleTests[i][0];
+        UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
+        expected = expected.unescape();
+        char loc[256]={0};
+        uloc_canonicalize(localeID, loc, 256, &status);
+        NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
+        if(U_FAILURE(status)){
+            dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
+            continue;
+        }
+        s.remove();
+        fmt->format(1250.75, s);
+        if(s!=expected){
+            errln(UnicodeString("FAIL: Expected: ")+expected
+                    + UnicodeString(" Got: ") + s
+                    + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
+        }
+        if (U_FAILURE(status)){
+            errln((UnicodeString)"FAIL: Status " + (int32_t)status);
+        }
+        delete fmt;
+    }
+
+}
+
+/**
+ * Test available numbering systems API.
+ */
+void NumberFormatTest::TestAvailableNumberingSystems() {
+    UErrorCode status = U_ZERO_ERROR;
+    StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
+    CHECK_DATA(status, "NumberingSystem::getAvailableNames()")
+
+    int32_t nsCount = availableNumberingSystems->count(status);
+    if ( nsCount < 74 ) {
+        errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
+    }
+
+    /* A relatively simple test of the API.  We call getAvailableNames() and cycle through */
+    /* each name returned, attempting to create a numbering system based on that name and  */
+    /* verifying that the name returned from the resulting numbering system is the same    */
+    /* one that we initially thought.                                                      */
+
+    int32_t len;
+    for ( int32_t i = 0 ; i < nsCount ; i++ ) {
+        const char *nsname = availableNumberingSystems->next(&len,status);
+        NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
+        logln("OK for ns = %s",nsname);
+        if ( uprv_strcmp(nsname,ns->getName()) ) {
+            errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
+        }
+
+        delete ns;
+    }
+
+    delete availableNumberingSystems;
+}
+
+void
+NumberFormatTest::Test9087(void)
+{
+    U_STRING_DECL(pattern,"#",1);
+    U_STRING_INIT(pattern,"#",1);
+    
+    U_STRING_DECL(infstr,"INF",3);
+    U_STRING_INIT(infstr,"INF",3);
+
+    U_STRING_DECL(nanstr,"NAN",3);
+    U_STRING_INIT(nanstr,"NAN",3);
+    
+    UChar outputbuf[50] = {0};
+    UErrorCode status = U_ZERO_ERROR;
+    UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
+    if ( U_FAILURE(status) ) {
+        dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
+        return;
+    }
+
+    unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
+    unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
+    if ( U_FAILURE(status) ) {
+        errln("FAIL: error setting symbols");
+    }
+
+    double inf = uprv_getInfinity();
+
+    unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
+    unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
+
+    UFieldPosition position = { 0, 0, 0};
+    unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
+    
+    if ( u_strcmp(infstr, outputbuf)) {
+        errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
+    }
+
+    unum_close(fmt);
+}
+
+#include "dcfmtimp.h"
+
+void NumberFormatTest::TestFormatFastpaths() {
+#if UCONFIG_FORMAT_FASTPATHS_49
+    logln("Sizeof DecimalFormat = %d, Sizeof DecimalFormatInternal=%d, UNUM_DECIMALFORMAT_INTERNAL_SIZE=%d\n",
+        sizeof(DecimalFormat), sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
+    if(UNUM_DECIMALFORMAT_INTERNAL_SIZE < sizeof(DecimalFormatInternal)) {
+        errln("Error: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is only %d. Increase the #define?\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE);
+    } else if(UNUM_DECIMALFORMAT_INTERNAL_SIZE > (sizeof(DecimalFormatInternal)+16)) {
+        infoln("Note: sizeof(DecimalFormatInternal)=%d but UNUM_DECIMALFORMAT_INTERNAL_SIZE is %d. Decrease the #define? sizeof(DecimalFormat)=%d\n", sizeof(DecimalFormatInternal), UNUM_DECIMALFORMAT_INTERNAL_SIZE, sizeof(DecimalFormat));
+    }
+#else
+    infoln("NOTE: UCONFIG_FORMAT_FASTPATHS not set, test skipped.");
+#endif  
+
+    // get some additional case
+    {
+        UErrorCode status=U_ZERO_ERROR;
+        DecimalFormat df(UnicodeString("0000",""),status);
+        if (U_FAILURE(status)) {
+            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        } else {
+            int64_t long_number = 1;
+            UnicodeString expect = "0001";
+            UnicodeString result;
+            FieldPosition pos;
+            df.format(long_number, result, pos);
+            if(U_FAILURE(status)||expect!=result) {
+                errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),""));
+            } else {
+                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+            }
+        }
+    }
+    {
+        UErrorCode status=U_ZERO_ERROR;
+        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+        if (U_FAILURE(status)) {
+            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        } else {
+            int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
+            // uint8_t bits[8];
+            // memcpy(bits,&long_number,8);
+            // for(int i=0;i<8;i++) {
+            //   logln("bits: %02X", (unsigned int)bits[i]);
+            // }
+            UnicodeString expect = "-9223372036854775808";
+            UnicodeString result;
+            FieldPosition pos;
+            df.format(long_number, result, pos);
+            if(U_FAILURE(status)||expect!=result) {
+                errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+            } else {
+                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+            }
+        }
+    }
+    {
+        UErrorCode status=U_ZERO_ERROR;
+        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+        if (U_FAILURE(status)) {
+            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        } else {
+            int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
+            // uint8_t bits[8];
+            // memcpy(bits,&long_number,8);
+            // for(int i=0;i<8;i++) {
+            //   logln("bits: %02X", (unsigned int)bits[i]);
+            // }
+            UnicodeString expect = "9223372036854775807";
+            UnicodeString result;
+            FieldPosition pos;
+            df.format(long_number, result, pos);
+            if(U_FAILURE(status)||expect!=result) {
+                errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+            } else {
+                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+            }
+        }
+    }
+    {
+        UErrorCode status=U_ZERO_ERROR;
+        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+        if (U_FAILURE(status)) {
+            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        } else {
+            int64_t long_number = 0;
+            // uint8_t bits[8];
+            // memcpy(bits,&long_number,8);
+            // for(int i=0;i<8;i++) {
+            //   logln("bits: %02X", (unsigned int)bits[i]);
+            // }
+            UnicodeString expect = "0000000000000000000";
+            UnicodeString result;
+            FieldPosition pos;
+            df.format(long_number, result, pos);
+            if(U_FAILURE(status)||expect!=result) {
+                errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+            } else {
+                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+            }
+        }
+    }
+    {
+        UErrorCode status=U_ZERO_ERROR;
+        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+        if (U_FAILURE(status)) {
+            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        } else {
+            int64_t long_number = U_INT64_MIN + 1;
+            UnicodeString expect = "-9223372036854775807";
+            UnicodeString result;
+            FieldPosition pos;
+            df.format(long_number, result, pos);
+            if(U_FAILURE(status)||expect!=result) {
+                errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+            } else {
+                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+            }
+        }
+    }
+}
+
+
+void NumberFormatTest::TestFormattableSize(void) {
+  if(sizeof(FmtStackData) > UNUM_INTERNAL_STACKARRAY_SIZE) {
+    errln("Error: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+          sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+  } else if(sizeof(FmtStackData) < UNUM_INTERNAL_STACKARRAY_SIZE) {
+    logln("Warning: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+        sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+  } else {
+    logln("sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+        sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+  }
+}
+
+UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
+  UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
+
+  UFormattable *u = f.toUFormattable();
+  logln();
+  if (u == NULL) {
+    errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
+    return FALSE;
+  }
+  logln("%s:%d: comparing Formattable with UFormattable", file, line);
+  logln(fileLine + toString(f));
+
+  UErrorCode status = U_ZERO_ERROR;
+  UErrorCode valueStatus = U_ZERO_ERROR;
+  UFormattableType expectUType = UFMT_COUNT; // invalid
+
+  UBool triedExact = FALSE; // did we attempt an exact comparison?
+  UBool exactMatch = FALSE; // was the exact comparison true?
+
+  switch( f.getType() ) {
+  case Formattable::kDate:
+    expectUType = UFMT_DATE;
+    exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
+    triedExact = TRUE;
+    break;
+  case Formattable::kDouble:
+    expectUType = UFMT_DOUBLE;
+    exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
+    triedExact = TRUE;
+    break;
+  case Formattable::kLong:
+    expectUType = UFMT_LONG;
+    exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
+    triedExact = TRUE;
+    break;
+  case Formattable::kString:
+    expectUType = UFMT_STRING;
+    {
+      UnicodeString str;
+      f.getString(str);
+      int32_t len;
+      const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
+      if(U_SUCCESS(valueStatus)) {
+        UnicodeString str2(uch, len);
+        assertTrue("UChar* NULL-terminated", uch[len]==0);
+        exactMatch = (str == str2);
+      }
+      triedExact = TRUE;
+    }
+    break;
+  case Formattable::kArray:
+    expectUType = UFMT_ARRAY;
+    triedExact = TRUE;
+    {
+      int32_t count = ufmt_getArrayLength(u, &valueStatus);
+      int32_t count2;
+      const Formattable *array2 = f.getArray(count2);
+      exactMatch = assertEquals(fileLine + " array count", count, count2);
+
+      if(exactMatch) {
+        for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
+          UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
+          if(*Formattable::fromUFormattable(uu) != (array2[i])) {
+            errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
+                  (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
+            exactMatch = FALSE;
+          } else {
+            if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
+              exactMatch = FALSE;
+            }
+          }
+        }
+      }
+    }
+    break;
+  case Formattable::kInt64:
+    expectUType = UFMT_INT64;
+    exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
+    triedExact = TRUE;
+    break;
+  case Formattable::kObject:
+    expectUType = UFMT_OBJECT;
+    exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
+    triedExact = TRUE;
+    break;
+  }
+  UFormattableType uType = ufmt_getType(u, &status);
+
+  if(U_FAILURE(status)) {
+    errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
+    return FALSE;
+  }
+
+  if(uType != expectUType) {
+    errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
+  }
+
+  if(triedExact) {
+    if(U_FAILURE(valueStatus)) {
+      errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
+    } else if(!exactMatch) {
+     errln("%s:%d: failed exact match for the Formattable type", file, line);
+    } else {
+      logln("%s:%d: exact match OK", file, line);
+    }
+  } else {
+    logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
+  }
+
+  if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
+      && f.isNumeric()) {
+    UErrorCode convStatus = U_ZERO_ERROR;
+
+    if(uType != UFMT_INT64) { // may fail to compare
+      assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
+    }
+
+    if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
+      StringPiece fDecNum = f.getDecimalNumber(convStatus);
+#if 1
+      int32_t len;
+      const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
+#else
+      // copy version
+      char decNumChars[200];
+      int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
+#endif
+
+      if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
+        logln(fileLine + decNumChars);
+        assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
+        assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
+      }
+
+      UErrorCode int64ConversionF = U_ZERO_ERROR;
+      int64_t l = f.getInt64(int64ConversionF);
+      UErrorCode int64ConversionU = U_ZERO_ERROR;
+      int64_t r = ufmt_getInt64(u, &int64ConversionU);
+
+      if( (l==r) 
+          && ( uType != UFMT_INT64 ) // int64 better not overflow
+          && (U_INVALID_FORMAT_ERROR==int64ConversionU) 
+          && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
+        logln("%s:%d: OK: 64 bit overflow", file, line);
+      } else {
+        assertEquals(fileLine + " as int64 ==", l, r);
+        assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
+        assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
+      }
+    }
+  }
+  return exactMatch || !triedExact;
+}
+
+void NumberFormatTest::TestUFormattable(void) {
+  {
+    // test that a default formattable is equal to Formattable()
+    UErrorCode status = U_ZERO_ERROR;
+    LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
+    assertSuccess("calling umt_open", status);
+    Formattable defaultFormattable;
+    assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+               (defaultFormattable
+                == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+    assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+               (defaultFormattable
+                == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+    assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
+               (defaultFormattable
+                == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
+    assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
+               ((&defaultFormattable)
+                == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
+    assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
+               ((&defaultFormattable)
+                == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
+    testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
+  }
+  // test some random Formattables
+  {
+    Formattable f(ucal_getNow(), Formattable::kIsDate);
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    Formattable f((double)1.61803398874989484820); // golden ratio
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    Formattable f("Hello world."); // should be invariant?
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    UErrorCode status2 = U_ZERO_ERROR;
+    Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
+    assertSuccess("Constructing a StringPiece", status2);
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    UErrorCode status2 = U_ZERO_ERROR;
+    UObject *obj = new Locale();
+    Formattable f(obj);
+    assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
+    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
+  }
+  {
+    const Formattable array[] = {
+      Formattable(ucal_getNow(), Formattable::kIsDate),
+      Formattable((int32_t)4),
+      Formattable((double)1.234),
+    };
+
+    Formattable fa(array, 3);
+    testFormattableAsUFormattable(__FILE__, __LINE__, fa);
+  }
+}
+
+void NumberFormatTest::TestSignificantDigits(void) {
+  double input[] = {
+        0, 0,
+        0.1, -0.1,
+        123, -123,
+        12345, -12345,
+        123.45, -123.45,
+        123.44501, -123.44501,
+        0.001234, -0.001234,
+        0.00000000123, -0.00000000123,
+        0.0000000000000000000123, -0.0000000000000000000123,
+        1.2, -1.2,
+        0.0000000012344501, -0.0000000012344501,
+        123445.01, -123445.01,
+        12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
+    };
+    const char* expected[] = {
+        "0.00", "0.00",
+        "0.100", "-0.100",
+        "123", "-123",
+        "12345", "-12345",
+        "123.45", "-123.45",
+        "123.45", "-123.45",
+        "0.001234", "-0.001234",
+        "0.00000000123", "-0.00000000123",
+        "0.0000000000000000000123", "-0.0000000000000000000123",
+        "1.20", "-1.20",
+        "0.0000000012345", "-0.0000000012345",
+        "123450", "-123450",
+        "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
+    };
+
+    UErrorCode status = U_ZERO_ERROR;
+    Locale locale("en_US");
+    LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+            NumberFormat::createInstance(locale, status)));
+    CHECK_DATA(status,"NumberFormat::createInstance")
+
+    numberFormat->setSignificantDigitsUsed(TRUE);
+    numberFormat->setMinimumSignificantDigits(3);
+    numberFormat->setMaximumSignificantDigits(5);
+    numberFormat->setGroupingUsed(false);
+    
+    UnicodeString result;
+    UnicodeString expectedResult;
+    for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
+        numberFormat->format(input[i], result);
+        UnicodeString expectedResult(expected[i]);
+        if (result != expectedResult) {
+          errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
+        }
+        result.remove();
+    }
+}
+
+void NumberFormatTest::TestShowZero() {
+    UErrorCode status = U_ZERO_ERROR;
+    Locale locale("en_US");
+    LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+            NumberFormat::createInstance(locale, status)));
+    CHECK_DATA(status, "NumberFormat::createInstance")
+
+    numberFormat->setSignificantDigitsUsed(TRUE);
+    numberFormat->setMaximumSignificantDigits(3);
+    
+    UnicodeString result;
+    numberFormat->format(0.0, result);
+    if (result != "0") {
+        errln((UnicodeString)"Expected: 0, got " + result);
+    }
+}
+
+void NumberFormatTest::TestBug9936() {
+    UErrorCode status = U_ZERO_ERROR;
+    Locale locale("en_US");
+    LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+            NumberFormat::createInstance(locale, status)));
+    if (U_FAILURE(status)) {
+        dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
+        return;
+    }
+        
+    if (numberFormat->areSignificantDigitsUsed() == TRUE) {
+        errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
+    }
+    numberFormat->setSignificantDigitsUsed(TRUE);
+    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+    }
+
+    numberFormat->setSignificantDigitsUsed(FALSE);
+    if (numberFormat->areSignificantDigitsUsed() == TRUE) {
+        errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
+    }
+
+    numberFormat->setMinimumSignificantDigits(3);
+    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+    }
+
+    numberFormat->setSignificantDigitsUsed(FALSE);
+    numberFormat->setMaximumSignificantDigits(6);
+    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+    }
+}
+
+void NumberFormatTest::TestParseNegativeWithFaLocale() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
+    CHECK_DATA(status, "NumberFormat::createInstance")
+    test->setLenient(TRUE);
+    Formattable af;
+    ParsePosition ppos;
+    UnicodeString value("\\u200e-0,5");
+    value = value.unescape();
+    test->parse(value, af, ppos);
+    if (ppos.getIndex() == 0) {
+        errln("Expected -0,5 to parse for Farsi.");
+    }
+    delete test;
+}
+
+void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
+    CHECK_DATA(status, "NumberFormat::createInstance")
+    test->setLenient(TRUE);
+    Formattable af;
+    ParsePosition ppos;
+    UnicodeString value("\\u208B0.5");
+    value = value.unescape();
+    test->parse(value, af, ppos);
+    if (ppos.getIndex() == 0) {
+        errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
+    }
+    delete test;
+}
+
+void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols custom(Locale::getUS(), status);
+    CHECK(status, "DecimalFormatSymbols constructor");
+
+    custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
+    custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
+    custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
+
+    UnicodeString pat(" #,##0.00");
+    pat.insert(0, (UChar)0x00A4);
+
+    DecimalFormat fmt(pat, custom, status);
+    CHECK(status, "DecimalFormat constructor");
+
+    UnicodeString numstr("* 1^234:56");
+    expect2(fmt, (Formattable)((double)1234.56), numstr);
+}
+
+typedef struct {
+    const char *   locale;
+    UBool          lenient;
+    UnicodeString  numString;
+    double         value;
+} SignsAndMarksItem;
+
+
+void NumberFormatTest::TestParseSignsAndMarks() {
+    const SignsAndMarksItem items[] = {
+        // locale               lenient numString                                                       value
+        { "en",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
+        { "en",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
+        { "en",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
+        { "en",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
+        { "en",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
+        { "en",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "en",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "en",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
+
+        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
+        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
+        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
+        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
+        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
+        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
+        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
+        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
+
+        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
+        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
+        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
+        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
+        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
+        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
+        { "he",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
+        { "he",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
+        { "he",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
+        { "he",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
+        { "he",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
+        { "he",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "he",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "he",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
+
+        { "ar",                 FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
+        { "ar",                 TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
+        { "ar",                 FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
+        { "ar",                 TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
+        { "ar",                 TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
+        { "ar",                 FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
+        { "ar",                 TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
+        { "ar",                 TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },
+
+        { "ar_MA",              FALSE,  CharsToUnicodeString("12"),                                      12 },
+        { "ar_MA",              TRUE,   CharsToUnicodeString("12"),                                      12 },
+        { "ar_MA",              FALSE,  CharsToUnicodeString("-23"),                                    -23 },
+        { "ar_MA",              TRUE,   CharsToUnicodeString("-23"),                                    -23 },
+        { "ar_MA",              TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
+        { "ar_MA",              FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
+        { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },
+
+        { "fa",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "fa",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "fa",                 FALSE,  CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
+        { "fa",                 TRUE,   CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
+        { "fa",                 TRUE,   CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"),                 -67 },
+        { "fa",                 FALSE,  CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
+        { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
+        { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"),   -67 },
+
+        { "ps",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "ps",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
+        { "ps",                 FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
+        { "ps",                 FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
+        { "ps",                 FALSE,  CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
+        { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"),                -67 },
+        // terminator
+        { NULL,                 0,      UnicodeString(""),                                                0 },
+    };
+
+    const SignsAndMarksItem * itemPtr;
+    for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
+        UErrorCode status = U_ZERO_ERROR;
+        NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
+        if (U_SUCCESS(status)) {
+            numfmt->setLenient(itemPtr->lenient);
+            Formattable fmtobj;
+            ParsePosition ppos;
+            numfmt->parse(itemPtr->numString, fmtobj, ppos);
+            if (ppos.getIndex() == itemPtr->numString.length()) {
+                double parsedValue = fmtobj.getDouble(status);
+                if (U_FAILURE(status) || parsedValue != itemPtr->value) {
+                    errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
+                }
+            } else {
+                errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
+            }
+        } else {
+            dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
+        }
+        delete numfmt;
+    }
+}
+
+typedef struct {
+  DecimalFormat::ERoundingMode mode;
+  double value;
+  UnicodeString expected;
+} Test10419Data;
+
+
+// Tests that rounding works right when fractional digits is set to 0.
+void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
+    const Test10419Data items[] = {
+        { DecimalFormat::kRoundCeiling, 1.488,  "2"},
+        { DecimalFormat::kRoundDown, 1.588,  "1"},
+        { DecimalFormat::kRoundFloor, 1.888,  "1"},
+        { DecimalFormat::kRoundHalfDown, 1.5,  "1"},
+        { DecimalFormat::kRoundHalfEven, 2.5,  "2"},
+        { DecimalFormat::kRoundHalfUp, 2.5,  "3"},
+        { DecimalFormat::kRoundUp, 1.5,  "2"},
+    };
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
+    if (U_FAILURE(status)) {
+        dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+        return;
+    }
+    for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
+        decfmt->setRoundingMode(items[i].mode);
+        decfmt->setMaximumFractionDigits(0);
+        UnicodeString actual;
+        if (items[i].expected != decfmt->format(items[i].value, actual)) {
+            errln("Expected " + items[i].expected + ", got " + actual);
+        }
+    }
+}
+
+void NumberFormatTest::Test10468ApplyPattern() {
+    // Padding char of fmt is now 'a'
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat fmt("'I''ll'*a###.##", status);
+
+    if (U_FAILURE(status)) {
+        errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+        return;
+    }
+
+    if (fmt.getPadCharacterString() != UnicodeString("a")) {
+        errln("Padding character should be 'a'.");
+        return;
+    }
+
+    // Padding char of fmt ought to be '*' since that is the default and no
+    // explicit padding char is specified in the new pattern.
+    fmt.applyPattern("AA#,##0.00ZZ", status);
+
+    // Oops this still prints 'a' even though we changed the pattern. 
+    if (fmt.getPadCharacterString() != UnicodeString(" ")) {
+        errln("applyPattern did not clear padding character.");
+    }
+}
+
+void NumberFormatTest::TestRoundingScientific10542() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat format("0.00E0", status);
+    if (U_FAILURE(status)) {
+        errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+        return;
+    }
+        
+    DecimalFormat::ERoundingMode roundingModes[] = {
+            DecimalFormat::kRoundCeiling,
+            DecimalFormat::kRoundDown,
+            DecimalFormat::kRoundFloor,
+            DecimalFormat::kRoundHalfDown,
+            DecimalFormat::kRoundHalfEven,
+            DecimalFormat::kRoundHalfUp,
+            DecimalFormat::kRoundUp};
+    const char *descriptions[] = {
+            "Round Ceiling",
+            "Round Down",
+            "Round Floor",
+            "Round half down",
+            "Round half even",
+            "Round half up",
+            "Round up"};
+        
+    {
+        double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
+                "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+                "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+                "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
+                "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+                "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+                "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+    }
+    {
+        double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
+                "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
+                "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
+                "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
+                "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+                "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+                "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+    }
+/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
+    {
+        double values[] = {0.0, -0.0};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0",
+                "0.00E0", "-0.00E0"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+    }
+*/
+    {
+
+        double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "1.00E25", "1.01E25", "1.00E25",
+                "1.00E25", "1.00E25", "9.99E24",
+                "1.00E25", "1.00E25", "9.99E24",
+                "1.00E25", "1.00E25", "1.00E25",
+                "1.00E25", "1.00E25", "1.00E25",
+                "1.00E25", "1.00E25", "1.00E25",
+                "1.00E25", "1.01E25", "1.00E25"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+        }
+    {
+        double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "-1.00E25", "-9.99E24", "-1.00E25",
+                "-1.00E25", "-9.99E24", "-1.00E25",
+                "-1.00E25", "-1.00E25", "-1.01E25",
+                "-1.00E25", "-1.00E25", "-1.00E25",
+                "-1.00E25", "-1.00E25", "-1.00E25",
+                "-1.00E25", "-1.00E25", "-1.00E25",
+                "-1.00E25", "-1.00E25", "-1.01E25"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+        }
+    {
+        double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "1.00E-25", "1.01E-25", "1.00E-25",
+                "1.00E-25", "1.00E-25", "9.99E-26",
+                "1.00E-25", "1.00E-25", "9.99E-26",
+                "1.00E-25", "1.00E-25", "1.00E-25",
+                "1.00E-25", "1.00E-25", "1.00E-25",
+                "1.00E-25", "1.00E-25", "1.00E-25",
+                "1.00E-25", "1.01E-25", "1.00E-25"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+        }
+    {
+        double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
+        // The order of these expected values correspond to the order of roundingModes and the order of values.
+        const char *expected[] = {
+                "-1.00E-25", "-9.99E-26", "-1.00E-25",
+                "-1.00E-25", "-9.99E-26", "-1.00E-25",
+                "-1.00E-25", "-1.00E-25", "-1.01E-25",
+                "-1.00E-25", "-1.00E-25", "-1.00E-25",
+                "-1.00E-25", "-1.00E-25", "-1.00E-25",
+                "-1.00E-25", "-1.00E-25", "-1.00E-25",
+                "-1.00E-25", "-1.00E-25", "-1.01E-25"};
+        verifyRounding(
+                format,
+                values,
+                expected,
+                roundingModes,
+                descriptions,
+                UPRV_LENGTHOF(values),
+                UPRV_LENGTHOF(roundingModes));
+    }
+}
+
+void NumberFormatTest::TestZeroScientific10547() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat fmt("0.00E0", status);
+    if (!assertSuccess("Formt creation", status)) {
+        return;
+    }
+    UnicodeString out;
+    fmt.format(-0.0, out);
+    assertEquals("format", "-0.00E0", out);
+}
+
+void NumberFormatTest::verifyRounding(
+        DecimalFormat& format,
+        const double *values,
+        const char * const *expected,
+        const DecimalFormat::ERoundingMode *roundingModes,
+        const char * const *descriptions,
+        int32_t valueSize,
+        int32_t roundingModeSize) {
+    for (int32_t i = 0; i < roundingModeSize; ++i) {
+        format.setRoundingMode(roundingModes[i]);
+        for (int32_t j = 0; j < valueSize; j++) {
+            UnicodeString currentExpected(expected[i * valueSize + j]);
+            currentExpected = currentExpected.unescape();
+            UnicodeString actual;
+            format.format(values[j], actual);
+            if (currentExpected != actual) {
+                char buffer[256];
+                sprintf(
+                        buffer,
+                        "For %s value %f, expected ",
+                        descriptions[i],
+                        values[j]);
+                errln(UnicodeString(buffer) + currentExpected + ", got " + actual);
+            }
+        }
+    }
+}
+
+void NumberFormatTest::TestAccountingCurrency() {
+    UErrorCode status = U_ZERO_ERROR;
+    UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
+
+    expect(NumberFormat::createInstance("en_US", style, status),
+        (Formattable)1234.5, "$1,234.50", TRUE, status);
+    expect(NumberFormat::createInstance("en_US", style, status),
+        (Formattable)-1234.5, "($1,234.50)", TRUE, status);
+    expect(NumberFormat::createInstance("en_US", style, status),
+        (Formattable)0, "$0.00", TRUE, status);
+    expect(NumberFormat::createInstance("en_US", style, status),
+        (Formattable)-0.2, "($0.20)", TRUE, status);
+    expect(NumberFormat::createInstance("ja_JP", style, status),
+        (Formattable)10000, UnicodeString("\\u00A510,000").unescape(), TRUE, status);
+    expect(NumberFormat::createInstance("ja_JP", style, status),
+        (Formattable)-1000.5, UnicodeString("(\\u00A51,000)").unescape(), FALSE, status);
+    expect(NumberFormat::createInstance("de_DE", style, status),
+        (Formattable)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
+}
+
+// for #5186
+void NumberFormatTest::TestEquality() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols* symbols = new DecimalFormatSymbols(Locale("root"), status);
+    if (U_FAILURE(status)) {
+       dataerrln("Fail: can't create DecimalFormatSymbols for root");
+       return;
+    }
+    UnicodeString pattern("#,##0.###");
+    DecimalFormat* fmtBase = new DecimalFormat(pattern, symbols, status);
+    if (U_FAILURE(status)) {
+       dataerrln("Fail: can't create DecimalFormat using root symbols");
+       return;
+    }
+
+    DecimalFormat* fmtClone = (DecimalFormat*)fmtBase->clone();
+    fmtClone->setFormatWidth(fmtBase->getFormatWidth() + 32);
+    if (*fmtClone == *fmtBase) {
+        errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
+    }
+    delete fmtClone;
+
+    delete fmtBase;
+}
+
+void NumberFormatTest::TestCurrencyUsage() {
+    double agent = 123.567;
+
+    UErrorCode status;
+    DecimalFormat *fmt;
+
+    // compare the Currency and Currency Cash Digits
+    // Note that as of CLDR 26:
+    // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
+    // * CAD rounds to .05 in cash mode only
+    // 1st time for getter/setter, 2nd time for factory method
+    Locale enUS_PKR("en_US@currency=PKR");
+
+    for(int i=0; i<2; i++){
+        status = U_ZERO_ERROR;
+        if(i == 0){
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CURRENCY, status);
+            if (assertSuccess("en_US@currency=PKR/CURRENCY", status, TRUE) == FALSE) {
+                continue;
+            }
+
+            UnicodeString original;
+            fmt->format(agent,original);
+            assertEquals("Test Currency Usage 1", UnicodeString("PKR124"), original);
+
+            // test the getter here
+            UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+            assertEquals("Test usage getter - standard", curUsage, UCURR_USAGE_STANDARD);
+
+            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+        }else{
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CASH_CURRENCY, status);
+            if (assertSuccess("en_US@currency=PKR/CASH", status, TRUE) == FALSE) {
+                continue;
+            }
+        }
+
+        // must be usage = cash
+        UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+        assertEquals("Test usage getter - cash", curUsage, UCURR_USAGE_CASH);
+
+        UnicodeString cash_currency;
+        fmt->format(agent,cash_currency);
+        assertEquals("Test Currency Usage 2", UnicodeString("PKR124"), cash_currency);
+        delete fmt;
+    }
+
+    // compare the Currency and Currency Cash Rounding
+    // 1st time for getter/setter, 2nd time for factory method
+    Locale enUS_CAD("en_US@currency=CAD");
+    for(int i=0; i<2; i++){
+        status = U_ZERO_ERROR;
+        if(i == 0){
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+            if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+                continue;
+            }
+
+            UnicodeString original_rounding;
+            fmt->format(agent, original_rounding);
+            assertEquals("Test Currency Usage 3", UnicodeString("CA$123.57"), original_rounding);
+            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+        }else{
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status); 
+            if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
+                continue;
+            }
+        }
+
+        UnicodeString cash_rounding_currency;
+        fmt->format(agent, cash_rounding_currency);
+        assertEquals("Test Currency Usage 4", UnicodeString("CA$123.55"), cash_rounding_currency);
+        delete fmt;
+    }
+
+    // Test the currency change
+    // 1st time for getter/setter, 2nd time for factory method
+    const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
+    for(int i=0; i<2; i++){
+        status = U_ZERO_ERROR;
+        if(i == 0){
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+            if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+                continue;
+            }
+            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+        }else{
+            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
+            if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
+                continue;
+            }
+        }
+
+        UnicodeString cur_original;
+        fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
+        fmt->format(agent, cur_original);
+        assertEquals("Test Currency Usage 5", UnicodeString("CA$123.57"), cur_original);
+
+        fmt->setCurrency(CUR_PKR, status);
+        assertSuccess("Set currency to PKR", status);
+
+        UnicodeString PKR_changed;
+        fmt->format(agent, PKR_changed);
+        assertEquals("Test Currency Usage 6", UnicodeString("PKR124"), PKR_changed);
+        delete fmt;
+    }
+}
+
+void NumberFormatTest::TestNumberFormatTestTuple() {
+    NumberFormatTestTuple tuple;
+    UErrorCode status = U_ZERO_ERROR;
+
+    tuple.setField(
+            NumberFormatTestTuple::getFieldByName("locale"),
+            "en",
+            status);
+    tuple.setField(
+            NumberFormatTestTuple::getFieldByName("pattern"),
+            "#,##0.00",
+            status);
+    tuple.setField(
+            NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
+            "-10",
+            status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+
+    // only what we set should be set.
+    assertEquals("", "en", tuple.locale.getName());
+    assertEquals("", "#,##0.00", tuple.pattern);
+    assertEquals("", -10, tuple.minIntegerDigits);
+    assertTrue("", tuple.localeFlag);
+    assertTrue("", tuple.patternFlag);
+    assertTrue("", tuple.minIntegerDigitsFlag);
+    assertFalse("", tuple.formatFlag);
+
+    UnicodeString appendTo;
+    assertEquals(
+            "",
+            "{locale: en, pattern: #,##0.00, minIntegerDigits: -10}",
+            tuple.toString(appendTo));
+
+    tuple.clear();
+    appendTo.remove();
+    assertEquals(
+            "",
+            "{}",
+            tuple.toString(appendTo));
+    tuple.setField(
+            NumberFormatTestTuple::getFieldByName("aBadFieldName"),
+            "someValue",
+            status);
+    if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+        errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
+    }
+    status = U_ZERO_ERROR;
+    tuple.setField(
+            NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
+            "someBadValue",
+            status);
+    if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+        errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
+    }
+}
+
+void
+NumberFormatTest::TestDataDriven() {
+    NumberFormatTestDataDriven dd;
+    dd.setCaller(this);
+    dd.run("numberformattestspecification.txt", FALSE);
+}
+
+
+// Check the constant MAX_INT64_IN_DOUBLE.
+// The value should convert to a double with no loss of precision.
+// A failure may indicate a platform with a different double format, requiring
+// a revision to the constant.
+//
+// Note that this is actually hard to test, because the language standard gives
+//  compilers considerable flexibility to do unexpected things with rounding and
+//  with overflow in simple int to/from float conversions. Some compilers will completely optimize
+//  away a simple round-trip conversion from int64_t -> double -> int64_t.
+
+void NumberFormatTest::TestDoubleLimit11439() {
+    char  buf[50];
+    for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
+        sprintf(buf, "%lld", (long long)num);
+        double fNum = 0.0;
+        sscanf(buf, "%lf", &fNum);
+        int64_t rtNum = fNum;
+        if (num != rtNum) {
+            errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
+            return;
+        }
+    }
+    for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
+        sprintf(buf, "%lld", (long long)num);
+        double fNum = 0.0;
+        sscanf(buf, "%lf", &fNum);
+        int64_t rtNum = fNum;
+        if (num != rtNum) {
+            errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
+            return;
+        }
+    }
+}
+
+void NumberFormatTest::TestFastPathConsistent11524() {
+    UErrorCode status = U_ZERO_ERROR;
+    NumberFormat *fmt = NumberFormat::createInstance("en", status);
+    if (U_FAILURE(status) || fmt == NULL) {
+        dataerrln("Failed call to NumberFormat::createInstance() - %s", u_errorName(status));
+        return;
+    }
+    fmt->setMaximumIntegerDigits(INT32_MIN);
+    UnicodeString appendTo;
+    assertEquals("", "0", fmt->format(123, appendTo));
+    appendTo.remove();
+    assertEquals("", "0", fmt->format(12345, appendTo));
+    delete fmt;
+}
+
+void NumberFormatTest::TestGetAffixes() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols sym("en_US", status);
+    UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+    pattern = pattern.unescape();
+    DecimalFormat fmt(pattern, sym, status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        return;
+    }
+    UnicodeString affixStr;
+    assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+    assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+    assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+    assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+
+    // Test equality with affixes. set affix methods can't capture special
+    // characters which is why equality should fail.
+    {
+        DecimalFormat fmtCopy(fmt);
+        assertTrue("", fmt == fmtCopy);
+        UnicodeString someAffix;
+        fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
+        assertTrue("", fmt != fmtCopy);
+    }
+    {
+        DecimalFormat fmtCopy(fmt);
+        assertTrue("", fmt == fmtCopy);
+        UnicodeString someAffix;
+        fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
+        assertTrue("", fmt != fmtCopy);
+    }
+    {
+        DecimalFormat fmtCopy(fmt);
+        assertTrue("", fmt == fmtCopy);
+        UnicodeString someAffix;
+        fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
+        assertTrue("", fmt != fmtCopy);
+    }
+    {
+        DecimalFormat fmtCopy(fmt);
+        assertTrue("", fmt == fmtCopy);
+        UnicodeString someAffix;
+        fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
+        assertTrue("", fmt != fmtCopy);
+    }
+    fmt.setPositivePrefix("Don't");
+    fmt.setPositiveSuffix("do");
+    UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
+    someAffix = someAffix.unescape();
+    fmt.setNegativePrefix(someAffix);
+    fmt.setNegativeSuffix("%");
+    assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
+    assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
+    assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
+    assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::TestToPatternScientific11648() {
+    UErrorCode status = U_ZERO_ERROR;
+    Locale en("en");
+    DecimalFormatSymbols sym(en, status);
+    DecimalFormat fmt("0.00", sym, status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        return;
+    }
+    fmt.setScientificNotation(TRUE);
+    UnicodeString pattern;
+    assertEquals("", "0.00E0", fmt.toPattern(pattern));
+    DecimalFormat fmt2(pattern, sym, status);
+    assertSuccess("", status);
+}
+
+void NumberFormatTest::TestBenchmark() {
+/*
+    UErrorCode status = U_ZERO_ERROR;
+    Locale en("en");
+    DecimalFormatSymbols sym(en, status);
+    DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
+//    DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
+//    DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
+    FieldPosition fpos(0);
+    clock_t start = clock();
+    for (int32_t i = 0; i < 1000000; ++i) {
+        UnicodeString append;
+        fmt.format(3.0, append, fpos, status);
+//        fmt.format(4.6692016, append, fpos, status);
+//        fmt.format(1234567.8901, append, fpos, status);
+//        fmt.format(2.99792458E8, append, fpos, status);
+//        fmt.format(31, append);
+    }
+    errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+    assertSuccess("", status);
+
+    UErrorCode status = U_ZERO_ERROR;
+    MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
+    FieldPosition fpos(0);
+    Formattable one(1.0);
+    Formattable three(3.0);
+    clock_t start = clock();
+    for (int32_t i = 0; i < 500000; ++i) {
+        UnicodeString append;
+        fmt.format(&one, 1, append, fpos, status);
+        UnicodeString append2;
+        fmt.format(&three, 1, append2, fpos, status);
+    }
+    errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+    assertSuccess("", status);
+
+    UErrorCode status = U_ZERO_ERROR;
+    Locale en("en");
+    Measure measureC(23, MeasureUnit::createCelsius(status), status);
+    MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
+    FieldPosition fpos(0);
+    clock_t start = clock();
+    for (int32_t i = 0; i < 1000000; ++i) {
+        UnicodeString appendTo;
+        fmt.formatMeasures(
+                &measureC, 1, appendTo, fpos, status);
+    }
+    errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+    assertSuccess("", status);
+*/
+}
+
+void NumberFormatTest::TestFractionalDigitsForCurrency() {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+        return;
+    }
+    UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
+    fmt->setCurrency(JPY, status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+    assertEquals("", 0, fmt->getMaximumFractionDigits());
+}
+
+
+void NumberFormatTest::TestFormatCurrencyPlural() {
+    UErrorCode status = U_ZERO_ERROR;
+    Locale locale = Locale::createCanonical("en_US");
+    NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+        return;
+    }
+   UnicodeString formattedNum;
+   fmt->format(11234.567, formattedNum, NULL, status);
+   assertEquals("", "11,234.57 US dollars", formattedNum);
+   delete fmt;
+}
+
+void NumberFormatTest::TestCtorApplyPatternDifference() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols sym("en_US", status);
+    UnicodeString pattern("\\u00a40");
+    DecimalFormat fmt(pattern.unescape(), sym, status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+        return;
+    }
+    UnicodeString result;
+    assertEquals(
+            "ctor favors precision of currency",
+            "$5.00",
+            fmt.format(5, result));
+    result.remove();
+    fmt.applyPattern(pattern.unescape(), status);
+    assertEquals(
+            "applyPattern favors precision of pattern",
+            "$5",
+            fmt.format(5, result));
+}
+
+void NumberFormatTest::Test11868() {
+    double posAmt = 34.567;
+    double negAmt = -9876.543;
+
+    Locale selectedLocale("en_US");
+    UErrorCode status = U_ZERO_ERROR;
+
+    UnicodeString result;
+    FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
+    LocalPointer<NumberFormat> fmt(
+            NumberFormat::createInstance(
+                    selectedLocale, UNUM_CURRENCY_PLURAL, status));
+    if (!assertSuccess("Format creation", status)) {
+        return;
+    }
+    fmt->format(posAmt, result, fpCurr, status);
+    assertEquals("", "34.57 US dollars", result);
+    assertEquals("begin index", 6, fpCurr.getBeginIndex());
+    assertEquals("end index", 16, fpCurr.getEndIndex());
+
+    // Test field position iterator
+    {
+        NumberFormatTest_Attributes attributes[] = {
+                {UNUM_INTEGER_FIELD, 0, 2},
+                {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+                {UNUM_FRACTION_FIELD, 3, 5},
+                {UNUM_CURRENCY_FIELD, 6, 16},
+                {0, -1, 0}};
+        UnicodeString result;
+        FieldPositionIterator iter;
+        fmt->format(posAmt, result, &iter, status);
+        assertEquals("", "34.57 US dollars", result);
+        verifyFieldPositionIterator(attributes, iter);
+    }
+
+    result.remove();
+    fmt->format(negAmt, result, fpCurr, status);
+    assertEquals("", "-9,876.54 US dollars", result);
+    assertEquals("begin index", 10, fpCurr.getBeginIndex());
+    assertEquals("end index", 20, fpCurr.getEndIndex());
+
+    // Test field position iterator
+    {
+        NumberFormatTest_Attributes attributes[] = {
+                {UNUM_SIGN_FIELD, 0, 1},
+                {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
+                {UNUM_INTEGER_FIELD, 1, 6},
+                {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
+                {UNUM_FRACTION_FIELD, 7, 9},
+                {UNUM_CURRENCY_FIELD, 10, 20},
+                {0, -1, 0}};
+        UnicodeString result;
+        FieldPositionIterator iter;
+        fmt->format(negAmt, result, &iter, status);
+        assertEquals("", "-9,876.54 US dollars", result);
+        verifyFieldPositionIterator(attributes, iter);
+    }
+}
+
+void NumberFormatTest::Test10727_RoundingZero() {
+   DigitList d;
+   d.set(-0.0);
+   assertFalse("", d.isPositive());
+   d.round(3); 
+   assertFalse("", d.isPositive());
+}
+
+void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
+    {
+        const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+        UErrorCode status = U_ZERO_ERROR;
+        LocalPointer<NumberFormat> fmt(
+                NumberFormat::createCurrencyInstance("en", status));
+        if (!assertSuccess("", status)) {
+            return;
+        }
+        DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+        dfmt->setCurrency(USD);
+        UnicodeString result;
+    
+        // This line should be a no-op. I am setting the positive prefix
+        // to be the same thing it was before.
+        dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
+
+        UnicodeString appendTo;
+        assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
+        assertSuccess("", status);
+    }
+    {
+        const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+        UErrorCode status = U_ZERO_ERROR;
+        LocalPointer<NumberFormat> fmt(
+                NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
+        if (!assertSuccess("", status)) {
+            return;
+        }
+        DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+        UnicodeString result;
+        UnicodeString tripleIntlCurrency(" \\u00a4\\u00a4\\u00a4");
+        tripleIntlCurrency = tripleIntlCurrency.unescape();
+        assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result));
+        dfmt->setCurrency(USD);
+
+        // getPositiveSuffix() always returns the suffix for the
+        // "other" plural category
+        assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+        UnicodeString appendTo;
+        assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
+        assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+        dfmt->setPositiveSuffix("booya");
+        appendTo.remove();
+        assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
+        assertEquals("", "booya", dfmt->getPositiveSuffix(result));
+    }
+}
+
+void NumberFormatTest::Test11475_signRecognition() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols sym("en", status);
+    UnicodeString result;
+    {
+        DecimalFormat fmt("+0.00", sym, status);
+        if (!assertSuccess("", status)) {
+            return;
+        }
+        NumberFormatTest_Attributes attributes[] = {
+                {UNUM_SIGN_FIELD, 0, 1},
+                {UNUM_INTEGER_FIELD, 1, 2},
+                {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+                {UNUM_FRACTION_FIELD, 3, 5},
+                {0, -1, 0}};
+        UnicodeString result;
+        FieldPositionIterator iter;
+        fmt.format(2.3, result, &iter, status);
+        assertEquals("", "+2.30", result);
+        verifyFieldPositionIterator(attributes, iter);
+    }
+    {
+        DecimalFormat fmt("++0.00+;-(#)--", sym, status);
+        if (!assertSuccess("", status)) {
+            return;
+        }
+        {
+            NumberFormatTest_Attributes attributes[] = {
+                    {UNUM_SIGN_FIELD, 0, 2},
+                    {UNUM_INTEGER_FIELD, 2, 3},
+                    {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+                    {UNUM_FRACTION_FIELD, 4, 6},
+                    {UNUM_SIGN_FIELD, 6, 7},
+                    {0, -1, 0}};
+            UnicodeString result;
+            FieldPositionIterator iter;
+            fmt.format(2.3, result, &iter, status);
+            assertEquals("", "++2.30+", result);
+            verifyFieldPositionIterator(attributes, iter);
+        }
+        {
+            NumberFormatTest_Attributes attributes[] = {
+                    {UNUM_SIGN_FIELD, 0, 1},
+                    {UNUM_INTEGER_FIELD, 2, 3},
+                    {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+                    {UNUM_FRACTION_FIELD, 4, 6},
+                    {UNUM_SIGN_FIELD, 7, 9},
+                    {0, -1, 0}};
+            UnicodeString result;
+            FieldPositionIterator iter;
+            fmt.format(-2.3, result, &iter, status);
+            assertEquals("", "-(2.30)--", result);
+            verifyFieldPositionIterator(attributes, iter);
+        }
+    }
+}
+
+void NumberFormatTest::Test11640_getAffixes() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols symbols("en_US", status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+    UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+    pattern = pattern.unescape();
+    DecimalFormat fmt(pattern, symbols, status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+    UnicodeString affixStr;
+    assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+    assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+    assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+    assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
+    UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+    pattern = pattern.unescape();
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat fmt(pattern, status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+    static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+    fmt.setCurrency(USD);
+    UnicodeString appendTo;
+    
+    assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+
+    UnicodeString topattern;
+    fmt.toPattern(topattern);
+    DecimalFormat fmt2(topattern, status);
+    if (!assertSuccess("", status)) {
+        return;
+    }
+    fmt2.setCurrency(USD);
+    
+    appendTo.remove();
+    assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+
+void NumberFormatTest::verifyFieldPositionIterator(
+        NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
+    int32_t idx = 0;
+    FieldPosition fp;
+    while (iter.next(fp)) {
+        if (expected[idx].spos == -1) {
+            errln("Iterator should have ended. got %d", fp.getField());
+            return;
+        }
+        assertEquals("id", expected[idx].id, fp.getField());
+        assertEquals("start", expected[idx].spos, fp.getBeginIndex());
+        assertEquals("end", expected[idx].epos, fp.getEndIndex());
+        ++idx;
+    }
+    if (expected[idx].spos != -1) {
+        errln("Premature end of iterator. expected %d", expected[idx].id);
+    }
+}
+
+void NumberFormatTest::checkExceptionIssue11735() {
+    UErrorCode status;
+    Locale enLocale("en");
+    DecimalFormatSymbols symbols(enLocale, status);
+
+    if (U_FAILURE(status)) {
+      errln((UnicodeString)
+            "Fail: Construct DecimalFormatSymbols");
+    }
+
+    DecimalFormat fmt("0", symbols, status);
+    if (U_FAILURE(status)) {
+      errln((UnicodeString)
+            "Fail: Construct DecimalFormat formatter");
+    }
+
+    ParsePosition ppos(0);
+    fmt.parseCurrency("53.45", ppos);  // NPE thrown here in ICU4J.
+    assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */