]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/numfmtst.cpp
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
index 5a5998808a6897245d48bdc8ef4f4dcfe3601d67..1ac9e1bee095db3ee37b662a7652f967be106295 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * Copyright (c) 1997-2008, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 /* Modification History:
 #include "unicode/decimfmt.h"
 #include "unicode/ucurr.h"
 #include "unicode/ustring.h"
+#include "unicode/measfmt.h"
+#include "unicode/curramt.h"
+#include "digitlst.h"
+#include "textfile.h"
+#include "tokiter.h"
+#include "charstr.h"
+#include "putilimp.h"
+#include "winnmtst.h"
 #include <float.h>
 #include <string.h>
-#include "digitlst.h"
+#include <stdlib.h>
+#include "cstring.h"
 
 static const UChar EUR[] = {69,85,82,0}; // "EUR"
  
@@ -54,12 +63,34 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
 
         CASE(14,TestCurrencyObject);
         CASE(15,TestCurrencyPatterns);
-        CASE(16,TestDigitList);
-        CASE(17,TestWhiteSpaceParsing);
-        CASE(18,TestComplexCurrency);
-        CASE(19,TestRegCurrency);
-        CASE(20,TestSymbolsWithBadLocale);
-        CASE(21,TestAdoptDecimalFormatSymbols);
+        //CASE(16,TestDigitList);
+        CASE(16,TestWhiteSpaceParsing);
+        CASE(17,TestComplexCurrency);
+        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,TestLenientParse);
+               CASE(38,TestSpaceParsing);
 
         default: name = ""; break;
     }
@@ -94,11 +125,54 @@ NumberFormatTest::TestAPI(void)
       status = U_ZERO_ERROR;
     }
 
+    result.remove();
+    int64_t ll = 12;
+    test->format(ll, result);
+    if (result != "12.00"){
+        errln("format int64_t error");
+    }
+
     delete test;  
   }
+}
 
+class StubNumberForamt :public NumberFormat{
+public:
+    StubNumberForamt(){};
+    virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
+        return appendTo;
+    }
+    virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
+        return appendTo.append((UChar)0x0033);
+    }
+    virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const {
+        return NumberFormat::format(number, appendTo, pos);
+    }
+    virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
+        return appendTo;
+    }
+    virtual void parse(const UnicodeString& ,
+                    Formattable& ,
+                    ParsePosition& ) const {}
+    virtual void parse( const UnicodeString& ,
+                        Formattable& ,
+                        UErrorCode& ) const {}
+    virtual UClassID getDynamicClassID(void) const {
+        static char classID = 0;
+        return (UClassID)&classID; 
+    }
+    virtual Format* clone() const {return NULL;}
+};
 
-
+void 
+NumberFormatTest::TestCoverage(void){
+    StubNumberForamt stub;
+    UnicodeString agent("agent");
+    FieldPosition pos;
+    int64_t num = 4;
+    if (stub.format(num, agent, pos) != UnicodeString("agent3")){
+        errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
+    };
 }
 
 // Test various patterns
@@ -133,20 +207,21 @@ NumberFormatTest::TestPatterns(void)
     }
 }
 
+/*
+icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug  
+icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug  
+icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug 
+*/
+/*
 void 
 NumberFormatTest::TestDigitList(void)
 {
   // API coverage for DigitList
-  /*
-    icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug  
-    icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug  
-    icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug 
-  */
   DigitList list1;
   list1.append('1');
   list1.fDecimalAt = 1;
   DigitList list2;
-  list2.set(1);
+  list2.set((int32_t)1);
   if (list1 != list2) {
     errln("digitlist append, operator!= or set failed ");
   }
@@ -154,6 +229,7 @@ NumberFormatTest::TestDigitList(void)
     errln("digitlist append, operator== or set failed ");
   }
 }
+*/
 
 // -------------------------------------
 
@@ -313,8 +389,10 @@ NumberFormatTest::TestExponential(void)
             ParsePosition pos(0);
             Formattable af;
             fmt.parse(s, af, pos);
-            if (af.getType() == Formattable::kLong) {
-                int32_t a = af.getLong();
+            if (af.getType() == Formattable::kLong ||
+                af.getType() == Formattable::kInt64) {
+                UErrorCode status = U_ZERO_ERROR;
+                int32_t a = af.getLong(status);
                 if (pos.getIndex() == s.length())
                 {
                     logln((UnicodeString)"  -parse-> " + a);
@@ -334,6 +412,138 @@ NumberFormatTest::TestExponential(void)
     }
 }
 
+void
+NumberFormatTest::TestScientific2() {
+    // jb 2552
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
+    if (U_SUCCESS(status)) {
+        double num = 12.34;
+        expect(*fmt, num, "$12.34");
+        fmt->setScientificNotation(TRUE);
+        expect(*fmt, num, "$1.23E1");
+        fmt->setScientificNotation(FALSE);
+        expect(*fmt, num, "$12.34");
+    }
+    delete fmt;
+}
+
+void 
+NumberFormatTest::TestScientificGrouping() {
+    // jb 2552
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat fmt("##0.00E0",status);
+    if (U_SUCCESS(status)) {
+        expect(fmt, .01234, "12.3E-3");
+        expect(fmt, .1234, "123E-3");
+        expect(fmt, 1.234, "1.23E0");
+        expect(fmt, 12.34, "12.3E0");
+        expect(fmt, 123.4, "123E0");
+        expect(fmt, 1234., "1.23E3");
+    }
+}
+
+/*static void setFromString(DigitList& dl, const char* str) {
+    char c;
+    UBool decimalSet = FALSE;
+    dl.clear();
+    while ((c = *str++)) {
+        if (c == '-') {
+            dl.fIsPositive = FALSE;
+        } else if (c == '+') {
+            dl.fIsPositive = TRUE;
+        } else if (c == '.') {
+            dl.fDecimalAt = dl.fCount;
+            decimalSet = TRUE;
+        } else {
+            dl.append(c);
+        }
+    }
+    if (!decimalSet) {
+        dl.fDecimalAt = dl.fCount;
+    }
+}*/
+
+void
+NumberFormatTest::TestInt64() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat fmt("#.#E0",status);
+    fmt.setMaximumFractionDigits(20);
+    if (U_SUCCESS(status)) {
+        expect(fmt, (Formattable)(int64_t)0, "0E0");
+        expect(fmt, (Formattable)(int64_t)-1, "-1E0");
+        expect(fmt, (Formattable)(int64_t)1, "1E0");
+        expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
+        expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
+        expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
+        expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
+    }
+
+    // also test digitlist
+/*    int64_t int64max = U_INT64_MAX;
+    int64_t int64min = U_INT64_MIN;
+    const char* int64maxstr = "9223372036854775807";
+    const char* int64minstr = "-9223372036854775808";
+    UnicodeString fail("fail: ");
+
+    // test max int64 value
+    DigitList dl;
+    setFromString(dl, int64maxstr);
+    {
+        if (!dl.fitsIntoInt64(FALSE)) {
+            errln(fail + int64maxstr + " didn't fit");
+        }
+        int64_t int64Value = dl.getInt64();
+        if (int64Value != int64max) {
+            errln(fail + int64maxstr);
+        }
+        dl.set(int64Value);
+        int64Value = dl.getInt64();
+        if (int64Value != int64max) {
+            errln(fail + int64maxstr);
+        }
+    }
+    // test negative of max int64 value (1 shy of min int64 value)
+    dl.fIsPositive = FALSE;
+    {
+        if (!dl.fitsIntoInt64(FALSE)) {
+            errln(fail + "-" + int64maxstr + " didn't fit");
+        }
+        int64_t int64Value = dl.getInt64();
+        if (int64Value != -int64max) {
+            errln(fail + "-" + int64maxstr);
+        }
+        dl.set(int64Value);
+        int64Value = dl.getInt64();
+        if (int64Value != -int64max) {
+            errln(fail + "-" + int64maxstr);
+        }
+    }
+    // test min int64 value
+    setFromString(dl, int64minstr);
+    {
+        if (!dl.fitsIntoInt64(FALSE)) {
+            errln(fail + "-" + int64minstr + " didn't fit");
+        }
+        int64_t int64Value = dl.getInt64();
+        if (int64Value != int64min) {
+            errln(fail + int64minstr);
+        }
+        dl.set(int64Value);
+        int64Value = dl.getInt64();
+        if (int64Value != int64min) {
+            errln(fail + int64minstr);
+        }
+    }
+    // test negative of min int 64 value (1 more than max int64 value)
+    dl.fIsPositive = TRUE; // won't fit
+    {
+        if (dl.fitsIntoInt64(FALSE)) {
+            errln(fail + "-(" + int64minstr + ") didn't fit");
+        }
+    }*/
+}
+
 // -------------------------------------
 
 // Test the handling of quotes
@@ -438,7 +648,19 @@ NumberFormatTest::escape(UnicodeString& s)
 
  
 // -------------------------------------
+static const char* testCases[][2]= {
+     /* locale ID */  /* expected */
+    {"ca_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+    {"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" }, 
+    {"gl_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+    {"it_IT_PREEURO", "\\u20A4\\u00A01.150" },
+    {"pt_PT_PREEURO", "1,150$50\\u00A0Esc."},
+    {"en_US@currency=JPY", "\\u00A51,150"}
+};
 /**
  * Test localized currency patterns.
  */
@@ -447,27 +669,60 @@ NumberFormatTest::TestCurrency(void)
 {
     UErrorCode status = U_ZERO_ERROR;
     NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error calling NumberFormat::createCurrencyInstance()");
+        return;
+    }
+
     UnicodeString s; currencyFmt->format(1.50, s);
     logln((UnicodeString)"Un pauvre ici a..........." + s);
-    if (!(s=="1,50 $"))
-        errln((UnicodeString)"FAIL: Expected 1,50 $");
+    if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
+        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$");
     delete currencyFmt;
     s.truncate(0);
-    currencyFmt = NumberFormat::createCurrencyInstance(Locale("de_DE_PREEURO"),status);
+    char loc[256]={0};
+    int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
+    currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
     currencyFmt->format(1.50, s);
     logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
-    if (!(s=="1,50 DM"))
-        errln((UnicodeString)"FAIL: Expected 1,50 DM");
+    if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
+        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM");
     delete currencyFmt;
     s.truncate(0);
-    currencyFmt = NumberFormat::createCurrencyInstance(Locale("fr_FR_PREEURO"), status);
+    len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
+    currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
     currencyFmt->format(1.50, s);
     logln((UnicodeString)"Un pauvre en France a....." + s);
-    if (!(s=="1,50 F"))
-        errln((UnicodeString)"FAIL: Expected 1,50 F");
+    if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
+        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
     delete currencyFmt;
     if (U_FAILURE(status))
         errln((UnicodeString)"FAIL: Status " + (int32_t)status);
+    
+    for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
+        status = U_ZERO_ERROR;
+        const char *localeID = testCases[i][0];
+        UnicodeString expected(testCases[i][1], -1, US_INV);
+        expected = expected.unescape();
+        s.truncate(0);
+        char loc[256]={0};
+        uloc_canonicalize(localeID, loc, 256, &status);
+        currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
+        if(U_FAILURE(status)){
+            errln("Could not create currency formatter for locale %s",localeID);
+            continue;
+        }
+        currencyFmt->format(1150.50, 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 currencyFmt;
+    }
 }
  
 // -------------------------------------
@@ -497,7 +752,7 @@ void NumberFormatTest::TestCurrencyObject() {
                    1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
 
     expectCurrency(*fmt, Locale("fr", "CH", ""),
-                   1234.56, "SwF1,234.55"); // 0.05 rounding
+                   1234.56, "Fr.1,234.55"); // 0.05 rounding
 
     expectCurrency(*fmt, Locale::getUS(),
                    1234.56, "$1,234.56");
@@ -514,13 +769,13 @@ void NumberFormatTest::TestCurrencyObject() {
     expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
 
     expectCurrency(*fmt, Locale::getJapan(),
-                   1234.56, CharsToUnicodeString("1 235 \\u00A5")); // Yen
+                   1234.56, CharsToUnicodeString("1 235 \\u00A5JP")); // Yen
 
     expectCurrency(*fmt, Locale("fr", "CH", ""),
                    1234.56, "1 234,55 sFr."); // 0.05 rounding
 
     expectCurrency(*fmt, Locale::getUS(),
-                   1234.56, "1 234,56 $");
+                   1234.56, "1 234,56 $US");
 
     expectCurrency(*fmt, Locale::getFrance(),
                    1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
@@ -540,7 +795,9 @@ 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");
@@ -554,6 +811,238 @@ NumberFormatTest::TestParse(void)
  
 // -------------------------------------
 
+static const char *lenientAffixTestCases[] = {
+       "(1)",
+       "( 1)",
+       "(1 )",
+       "( 1 )"
+};
+
+static const char *lenientMinusTestCases[] = {
+    "-5",
+    "\\u22125",
+    "\\u20105"
+};
+
+static const char *lenientCurrencyTestCases[] = {
+       "$1,000",
+       "$ 1,000",
+       "$1000",
+       "$ 1000",
+       "$1 000.00",
+       "$ 1 000.00",
+       "$ 1\\u00A0000.00",
+       "1000.00"
+};
+
+static const char *lenientNegativeCurrencyTestCases[] = {
+       "($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\\u00A0%",
+       "25"
+};
+
+static const char *lenientNegativePercentTestCases[] = {
+       "-25%",
+       " -25%",
+       " - 25%",
+       "- 25 %",
+       " - 25 %",
+       "-25 %",
+       "-25\\u00A0%",
+       "-25",
+       "- 25"
+};
+
+static const char *strictFailureTestCases[] = {
+       " 1000",
+#if 0
+       "10,00",
+       "1,000,.0"
+#endif
+};
+
+#define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
+
+/**
+ * Test lenient parsing.
+ */
+void
+NumberFormatTest::TestLenientParse(void)
+{
+    UErrorCode status = U_ZERO_ERROR;
+    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 (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, 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;
+        }
+    }
+    
+    delete mFormat;
+    
+    mFormat = NumberFormat::createInstance(en_US, 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;
+        }
+    }
+    
+    delete mFormat;
+    
+    NumberFormat *cFormat = NumberFormat::createCurrencyInstance(en_US, status);
+       
+    cFormat->setParseStrict(FALSE);
+    for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
+       UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
+               
+        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;
+        }
+       }
+       
+    for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
+       UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
+               ParsePosition pos(0);
+               
+        cFormat->parse(testCase, n, /*status*/pos);
+        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+               
+        if (/*U_FAILURE(status)*/pos.getErrorIndex() >= 0 ||n.getType() != Formattable::kLong ||
+               n.getLong() != -1000) {
+               errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\" parse position = " +
+                                  pos.getIndex() + ", " + pos.getErrorIndex());
+               status = U_ZERO_ERROR;
+        }
+       }
+       
+    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]);
+               
+       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;
+        }
+       }
+       
+    for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
+       UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
+               
+       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;
+        }
+       }
+       
+       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;
+               }
+       }
+       
+       delete nFormat;
+}
+
+// -------------------------------------
+
 /**
  * Test proper rounding by the format method.
  */
@@ -562,6 +1051,11 @@ NumberFormatTest::TestRounding487(void)
 {
     UErrorCode status = U_ZERO_ERROR;
     NumberFormat *nf = NumberFormat::createInstance(status);
+    if (U_FAILURE(status)) {
+        dataerrln("Error calling NumberFormat::createInstance()");
+        return;
+    }
+
     roundingTest(*nf, 0.00159999, 4, "0.0016");
     roundingTest(*nf, 0.00995, 4, "0.01");
 
@@ -650,21 +1144,22 @@ void NumberFormatTest::TestWhiteSpaceParsing(void) {
 
 /**
  * Test currencies whose display name is a ChoiceFormat.
+ * Less useful now that INR is no longer a choice format! See cldrbug 1961 !
  */
 void NumberFormatTest::TestComplexCurrency() {
     UErrorCode ec = U_ZERO_ERROR;
-    Locale loc("en", "IN", "");
+    Locale loc("kn", "IN", "");
     NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
     if (U_SUCCESS(ec)) {
-        expect2(*fmt, 1.0, "Re. 1.00");
+        expect2(*fmt, 1.0, CharsToUnicodeString("Rs.\\u00A01.00"));
         // Use .00392625 because that's 2^-8.  Any value less than 0.005 is fine.
-        expect(*fmt, 1.00390625, "Re. 1.00"); // tricky
-        expect2(*fmt, 12345678.0, "Rs. 1,23,45,678.00");
-        expect2(*fmt, 0.5, "Rs. 0.50");
-        expect2(*fmt, -1.0, "-Re. 1.00");
-        expect2(*fmt, -10.0, "-Rs. 10.00");
+        expect(*fmt, 1.00390625, CharsToUnicodeString("Rs.\\u00A01.00")); // tricky
+        expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
+        expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
+        expect2(*fmt, -1.0, CharsToUnicodeString("-Rs.\\u00A01.00"));
+        expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
     } else {
-        errln("FAIL: getCurrencyInstance(en_IN)");
+        errln("FAIL: getCurrencyInstance(kn_IN)");
     }
     delete fmt;
 }
@@ -889,13 +1384,13 @@ void NumberFormatTest::TestPad(void) {
            int32_t(0), "^^^^0", status);
     expect2(new DecimalFormat("*^##.##", US, status),
            -1.3, "^-1.3", status);
-    expect2(new DecimalFormat("##0.0####E0*_ g-m/s^2", US, status),
+    expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
            int32_t(0), "0.0E0______ g-m/s^2", status);
-    expect(new DecimalFormat("##0.0####E0*_ g-m/s^2", US, status),
+    expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
            1.0/3, "333.333E-3_ g-m/s^2", status);
-    expect2(new DecimalFormat("##0.0####*_ g-m/s^2", US, status),
+    expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
            int32_t(0), "0.0______ g-m/s^2", status);
-    expect(new DecimalFormat("##0.0####*_ g-m/s^2", US, status),
+    expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
            1.0/3, "0.33333__ g-m/s^2", status);
 
     // Test padding before a sign
@@ -1081,16 +1576,16 @@ void NumberFormatTest::TestSurrogateSupport(void) {
     expect2(new DecimalFormat("##.##", custom, status),
            -1.3, " minus 1decimal3", status);
     status = U_ZERO_ERROR;
-    expect2(new DecimalFormat("##0.0####E0 g'-'m/s^2", custom, status),
+    expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
            int32_t(0), "0decimal0exponent0 g-m/s^2", status);
     status = U_ZERO_ERROR;
-    expect(new DecimalFormat("##0.0####E0 g'-'m/s^2", custom, status),
+    expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
            1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
     status = U_ZERO_ERROR;
-    expect2(new DecimalFormat("##0.0#### g'-'m/s^2", custom, status),
+    expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
            int32_t(0), "0decimal0 g-m/s^2", status);
     status = U_ZERO_ERROR;
-    expect(new DecimalFormat("##0.0#### g'-'m/s^2", custom, status),
+    expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
            1.0/3, "0decimal33333 g-m/s^2", status);
 
     UnicodeString zero((UChar32)0x10000);
@@ -1104,7 +1599,7 @@ void NumberFormatTest::TestSurrogateSupport(void) {
     custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
     custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
     custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
-    patternStr = "0.00 \\u00A4' in your bank account'";
+    patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
     patternStr = patternStr.unescape();
     expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
     status = U_ZERO_ERROR;
@@ -1127,7 +1622,7 @@ void NumberFormatTest::TestCurrencyPatterns(void) {
         UErrorCode ec = U_ZERO_ERROR;
         NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
         if (U_FAILURE(ec)) {
-            errln("FAIL: Can't create NumberFormat");
+            errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
         } else {
             // Make sure currency formats do not have a variable number
             // of fraction digits
@@ -1163,56 +1658,194 @@ void NumberFormatTest::TestCurrencyPatterns(void) {
 }
 
 void NumberFormatTest::TestRegCurrency(void) {
-  UErrorCode status = U_ZERO_ERROR;
-  const UChar* USD = ucurr_forLocale("en_US", &status);
-  const UChar* YEN = ucurr_forLocale("ja_JP", &status);
-  if(U_FAILURE(status)) {
-    errln("Unable to get currency for locale, error %s", u_errorName(status));
-    return;
-  }
+#if !UCONFIG_NO_SERVICE
+    UErrorCode status = U_ZERO_ERROR;
+    UChar USD[4];
+    ucurr_forLocale("en_US", USD, 4, &status);
+    UChar YEN[4];
+    ucurr_forLocale("ja_JP", YEN, 4, &status);
+    UChar TMP[4];
+    static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
+    if(U_FAILURE(status)) {
+        errln("Unable to get currency for locale, error %s", u_errorName(status));
+        return;
+    }
+    
+    UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
+    UCurrRegistryKey enUSEUROkey = ucurr_register(QQQ, "en_US_EURO", &status);
+    
+    ucurr_forLocale("en_US", TMP, 4, &status);
+    if (u_strcmp(YEN, TMP) != 0) {
+        errln("FAIL: didn't return YEN registered for en_US");
+    }
 
-  UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
-  UCurrRegistryKey enUSEUROkey = ucurr_register(EUR, "en_US_EURO", &status);
+    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
+    if (u_strcmp(QQQ, TMP) != 0) {
+        errln("FAIL: didn't return QQQ for en_US_EURO");
+    }
+    
+    int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
+    if (fallbackLen) {
+        errln("FAIL: tried to fallback en_XX_BAR");
+    }
+    status = U_ZERO_ERROR; // reset
+    
+    if (!ucurr_unregister(enkey, &status)) {
+        errln("FAIL: couldn't unregister enkey");
+    }
 
-  if (u_strcmp(YEN, ucurr_forLocale("en_US", &status)) != 0) {
-    errln("FAIL: didn't return YEN registered for en_US");
-  }
+    ucurr_forLocale("en_US", TMP, 4, &status);        
+    if (u_strcmp(USD, TMP) != 0) {
+        errln("FAIL: didn't return USD for en_US after unregister of en_US");
+    }
+    status = U_ZERO_ERROR; // reset
+    
+    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
+    if (u_strcmp(QQQ, TMP) != 0) {
+        errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
+    }
+    
+    ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
+    if (u_strcmp(USD, TMP) != 0) {
+        errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
+    }
+    status = U_ZERO_ERROR; // reset
+    
+    if (!ucurr_unregister(enUSEUROkey, &status)) {
+        errln("FAIL: couldn't unregister enUSEUROkey");
+    }
+    
+    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
+    if (u_strcmp(EUR, TMP) != 0) {
+        errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
+    }
+    status = U_ZERO_ERROR; // reset
+#endif
+}
 
-  if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
-    errln("FAIL: didn't return EUR for en_US_EURO");
-  }
+void NumberFormatTest::TestCurrencyNames(void) {
+    // Do a basic check of getName()
+    // USD { "US$", "US Dollar"            } // 04/04/1792-
+    UErrorCode ec = U_ZERO_ERROR;
+    static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
+    static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
+    static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
+    static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
+    UBool isChoiceFormat;
+    int32_t len;
+    // Warning: HARD-CODED LOCALE DATA in this test.  If it fails, CHECK
+    // THE LOCALE DATA before diving into the code.
+    assertEquals("USD.getName(SYMBOL_NAME)",
+                 UnicodeString("$"),
+                 UnicodeString(ucurr_getName(USD, "en",
+                                             UCURR_SYMBOL_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("USD.getName(LONG_NAME)",
+                 UnicodeString("US Dollar"),
+                 UnicodeString(ucurr_getName(USD, "en",
+                                             UCURR_LONG_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("CAD.getName(SYMBOL_NAME)",
+                 UnicodeString("CA$"),
+                 UnicodeString(ucurr_getName(CAD, "en",
+                                             UCURR_SYMBOL_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("CAD.getName(SYMBOL_NAME)",
+                 UnicodeString("$"),
+                 UnicodeString(ucurr_getName(CAD, "en_CA",
+                                             UCURR_SYMBOL_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("USD.getName(SYMBOL_NAME)",
+                 UnicodeString("US$"),
+                 UnicodeString(ucurr_getName(USD, "en_AU",
+                                             UCURR_SYMBOL_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("CAD.getName(SYMBOL_NAME)",
+                 UnicodeString("CA$"),
+                 UnicodeString(ucurr_getName(CAD, "en_AU",
+                                             UCURR_SYMBOL_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertEquals("USX.getName(LONG_NAME)",
+                 UnicodeString("USX"),
+                 UnicodeString(ucurr_getName(USX, "en_US",
+                                             UCURR_LONG_NAME,
+                                             &isChoiceFormat, &len, &ec)));
+    assertSuccess("ucurr_getName", ec);
+    
+    ec = U_ZERO_ERROR;
+
+    // Test that a default or fallback warning is being returned. JB 4239.
+    ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
+                            &len, &ec);
+    assertTrue("ucurr_getName (fallback)",
+                    U_USING_FALLBACK_WARNING == ec, TRUE);
+
+    ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
+                            &len, &ec);
+    assertTrue("ucurr_getName (fallback)",
+                    U_USING_FALLBACK_WARNING == ec, TRUE);
+
+    ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
+                            &len, &ec);
+    assertTrue("ucurr_getName (default)",
+                    U_USING_DEFAULT_WARNING == ec, TRUE);
+    
+    ucurr_getName(CAD, "vi", UCURR_LONG_NAME, &isChoiceFormat,
+                            &len, &ec);
+    assertTrue("ucurr_getName (default)",
+                    U_USING_DEFAULT_WARNING == ec, TRUE);
+    
+    // Test that a default warning is being returned when falling back to root. JB 4536.
+    ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
+                            &len, &ec);
+    assertTrue("ucurr_getName (default to root)",
+                    U_USING_DEFAULT_WARNING == ec, TRUE);
+    
+    // TODO add more tests later
+}
 
-  if (ucurr_forLocale("en_XX_BAR", &status) != NULL) {
-    errln("FAIL: tried to fallback en_XX_BAR");
-  }
-  status = U_ZERO_ERROR; // reset
-  
-  if (!ucurr_unregister(enkey, &status)) {
-    errln("FAIL: couldn't unregister enkey");
-  }
+void NumberFormatTest::TestCurrencyUnit(void){
+    UErrorCode ec = U_ZERO_ERROR;
+    static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
+    CurrencyUnit cu(USD, ec);
+    assertSuccess("CurrencyUnit", ec);
 
-  if (u_strcmp(USD, ucurr_forLocale("en_US", &status)) != 0) {
-    errln("FAIL: didn't return USD for en_US after unregister of en_US");
-  }
-  status = U_ZERO_ERROR; // reset
+    const UChar * r = cu.getISOCurrency(); // who is the buffer owner ?
+    assertEquals("getISOCurrency()", USD, r);
 
-  if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
-    errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US");
-  }
+    CurrencyUnit cu2(cu);
+    if (!(cu2 == cu)){
+        errln("CurrencyUnit copy constructed object should be same");
+    }
 
-  if (u_strcmp(USD, ucurr_forLocale("en_US_BLAH", &status)) != 0) {
-    errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
-  }
-  status = U_ZERO_ERROR; // reset
+    CurrencyUnit * cu3 = (CurrencyUnit *)cu.clone();
+    if (!(*cu3 == cu)){
+        errln("CurrencyUnit cloned object should be same");
+    }
+    delete cu3;
+}
 
-  if (!ucurr_unregister(enUSEUROkey, &status)) {
-    errln("FAIL: couldn't unregister enUSEUROkey");
-  }
+void NumberFormatTest::TestCurrencyAmount(void){
+    UErrorCode ec = U_ZERO_ERROR;
+    static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
+    CurrencyAmount ca(9, USD, ec);
+    assertSuccess("CurrencyAmount", ec);
 
-  if (ucurr_forLocale("en_US_EURO", &status) != NULL) {
-    errln("FAIL: didn't return NULL for en_US_EURO after unregister of en_US_EURO");
-  }
-  status = U_ZERO_ERROR; // reset
+    CurrencyAmount ca2(ca);
+    if (!(ca2 == ca)){
+        errln("CurrencyAmount copy constructed object should be same");
+    }
+
+    ca2=ca;
+    if (!(ca2 == ca)){
+        errln("CurrencyAmount assigned object should be same");
+    }
+    
+    CurrencyAmount *ca3 = (CurrencyAmount *)ca.clone();
+    if (!(*ca3 == ca)){
+        errln("CurrencyAmount cloned object should be same");
+    }
+    delete ca3;
 }
 
 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
@@ -1233,10 +1866,15 @@ void NumberFormatTest::TestSymbolsWithBadLocale(void) {
     if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
         errln("DecimalFormatSymbols does not have the right locale.");
     }
-    DecimalFormatSymbols::ENumberFormatSymbol symbolEnum;
-    int *symbolEnumPtr = (int*)(&symbolEnum);
-    for (symbolEnum = DecimalFormatSymbols::kDecimalSeparatorSymbol; symbolEnum < DecimalFormatSymbols::kFormatSymbolCount; (*symbolEnumPtr)++) {
-        if (mySymbols.getSymbol(symbolEnum).length() == 0 && symbolEnum != DecimalFormatSymbols::kGroupingSeparatorSymbol) {
+    int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
+    for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
+        logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ")
+            + prettify(mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum)));
+
+        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);
         }
     }
@@ -1320,22 +1958,331 @@ void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
     }
 }
 
+void NumberFormatTest::TestPerMill() {
+    UErrorCode ec = U_ZERO_ERROR;
+    UnicodeString str;
+    DecimalFormat fmt(ctou("###.###\\u2030"), ec);
+    if (!assertSuccess("DecimalFormat ct", ec)) return;
+    assertEquals("0.4857 x ###.###\\u2030",
+                 ctou("485.7\\u2030"), fmt.format(0.4857, str));
+    
+    DecimalFormatSymbols sym(Locale::getUS(), ec);
+    sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
+    DecimalFormat fmt2("", sym, ec);
+    fmt2.applyLocalizedPattern("###.###m", ec);
+    if (!assertSuccess("setup", ec)) return;
+    str.truncate(0);
+    assertEquals("0.4857 x ###.###m",
+                 "485.7m", fmt2.format(0.4857, str));
+}
+
+/**
+ * Generic test for patterns that should be legal/illegal.
+ */
+void NumberFormatTest::TestIllegalPatterns() {
+    // Test cases:
+    // Prefix with "-:" for illegal patterns
+    // Prefix with "+:" for legal patterns
+    const char* DATA[] = {
+        // Unquoted special characters in the suffix are illegal
+        "-:000.000|###",
+        "+:000.000'|###'",
+        0
+    };
+    for (int32_t i=0; DATA[i]; ++i) {
+        const char* pat=DATA[i];
+        UBool valid = (*pat) == '+';
+        pat += 2;
+        UErrorCode ec = U_ZERO_ERROR;
+        DecimalFormat fmt(pat, ec); // locale doesn't matter here
+        if (U_SUCCESS(ec) == valid) {
+            logln("Ok: pattern \"%s\": %s",
+                  pat, u_errorName(ec));
+        } else {
+            errln("FAIL: pattern \"%s\" should have %s; got %s",
+                  pat, (valid?"succeeded":"failed"),
+                  u_errorName(ec));
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+
+static const char* KEYWORDS[] = {
+    /*0*/ "ref=", // <reference pattern to parse numbers>
+    /*1*/ "loc=", // <locale for formats>
+    /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
+    /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
+    /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
+    /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
+    /*6*/ "perr:", // <pattern or '-'> <invalid string>
+    /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
+    /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
+    0
+};
+
+/**
+ * Return an integer representing the next token from this
+ * iterator.  The integer will be an index into the given list, or
+ * -1 if there are no more tokens, or -2 if the token is not on
+ * the list.
+ */
+static int32_t keywordIndex(const UnicodeString& tok) {
+    for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
+        if (tok==KEYWORDS[i]) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+/**
+ * Parse a CurrencyAmount using the given NumberFormat, with
+ * the 'delim' character separating the number and the currency.
+ */
+static void parseCurrencyAmount(const UnicodeString& str,
+                                const NumberFormat& fmt,
+                                UChar delim,
+                                Formattable& result,
+                                UErrorCode& ec) {
+    UnicodeString num, cur;
+    int32_t i = str.indexOf(delim);
+    str.extractBetween(0, i, num);
+    str.extractBetween(i+1, INT32_MAX, cur);
+    Formattable n;
+    fmt.parse(num, n, ec);
+    result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
+}
+
+void NumberFormatTest::TestCases() {
+    UErrorCode ec = U_ZERO_ERROR;
+    TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
+    if (U_FAILURE(ec)) {
+        dataerrln("[DATA] Couldn't open NumberFormatTestCases.txt");
+        return;
+    }
+    TokenIterator tokens(&reader);
+
+    Locale loc("en", "US", "");
+    DecimalFormat *ref = 0, *fmt = 0;
+    MeasureFormat *mfmt = 0;
+    UnicodeString pat, tok, mloc, str, out, where, currAmt;
+    Formattable n;
+
+    for (;;) {
+        ec = U_ZERO_ERROR;
+        if (!tokens.next(tok, ec)) {
+            break;
+        }
+        where = UnicodeString("(") + tokens.getLineNumber() + ") ";
+        int32_t cmd = keywordIndex(tok);
+        switch (cmd) {
+        case 0:
+            // ref= <reference pattern>
+            if (!tokens.next(tok, ec)) goto error;
+            delete ref;
+            ref = new DecimalFormat(tok,
+                      new DecimalFormatSymbols(Locale::getUS(), ec), ec);
+            if (U_FAILURE(ec)) {
+                dataerrln("Error constructing DecimalFormat");
+                goto error;
+            }
+            break;
+        case 1:
+            // loc= <locale>
+            if (!tokens.next(tok, ec)) goto error;
+            loc = Locale::createFromName(CharString(tok));
+            break;
+        case 2: // f:
+        case 3: // fp:
+        case 4: // rt:
+        case 5: // p:
+            if (!tokens.next(tok, ec)) goto error;
+            if (tok != "-") {
+                pat = tok;
+                delete fmt;
+                fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
+                if (U_FAILURE(ec)) {
+                    errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
+                    ec = U_ZERO_ERROR;
+                    if (!tokens.next(tok, ec)) goto error;
+                    if (!tokens.next(tok, ec)) goto error;
+                    if (cmd == 3) {
+                        if (!tokens.next(tok, ec)) goto error;
+                    }
+                    continue;
+                }
+            }
+            if (cmd == 2 || cmd == 3 || cmd == 4) {
+                // f: <pattern or '-'> <number> <exp. string>
+                // fp: <pattern or '-'> <number> <exp. string> <exp. number>
+                // rt: <pattern or '-'> <number> <string>
+                UnicodeString num;
+                if (!tokens.next(num, ec)) goto error;
+                if (!tokens.next(str, ec)) goto error;
+                ref->parse(num, n, ec);
+                assertSuccess("parse", ec);
+                assertEquals(where + "\"" + pat + "\".format(" + num + ")",
+                             str, fmt->format(n, out.remove(), ec));
+                assertSuccess("format", ec);
+                if (cmd == 3) { // fp:
+                    if (!tokens.next(num, ec)) goto error;
+                    ref->parse(num, n, ec);
+                    assertSuccess("parse", ec);
+                }
+                if (cmd != 2) { // != f:
+                    Formattable m;
+                    fmt->parse(str, m, ec);
+                    assertSuccess("parse", ec);
+                    assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
+                                 n, m);
+                } 
+            }
+            // p: <pattern or '-'> <string to parse> <exp. number>
+            else {
+                UnicodeString expstr;
+                if (!tokens.next(str, ec)) goto error;
+                if (!tokens.next(expstr, ec)) goto error;
+                Formattable exp, n;
+                ref->parse(expstr, exp, ec);
+                assertSuccess("parse", ec);
+                fmt->parse(str, n, ec);
+                assertSuccess("parse", ec);
+                assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
+                             exp, n);
+            }
+            break;
+        case 8: // fpc:
+            if (!tokens.next(tok, ec)) goto error;
+            if (tok != "-") {
+                mloc = tok;
+                delete mfmt;
+                mfmt = MeasureFormat::createCurrencyFormat(
+                           Locale::createFromName(CharString(mloc)), ec);
+                if (U_FAILURE(ec)) {
+                    errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
+                    ec = U_ZERO_ERROR;
+                    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;
+            if (!tokens.next(str, ec)) goto error;
+            parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
+            if (assertSuccess("parseCurrencyAmount", ec)) {
+                assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
+                             str, mfmt->format(n, out.remove(), ec));
+                assertSuccess("format", ec);
+            }
+            if (!tokens.next(currAmt, ec)) goto error;
+            parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
+            if (assertSuccess("parseCurrencyAmount", ec)) {
+                Formattable m;
+                mfmt->parseObject(str, m, ec);
+                if (assertSuccess("parseCurrency", ec)) {
+                    assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
+                                 n, m);
+                }
+            }
+            break;
+        case 6:
+            // perr: <pattern or '-'> <invalid string>
+            errln("FAIL: Under construction");
+            goto done;
+        case 7: {
+            // pat: <pattern> <exp. toPattern, or '-' or 'err'>
+            UnicodeString testpat;
+            UnicodeString exppat;
+            if (!tokens.next(testpat, ec)) goto error;
+            if (!tokens.next(exppat, ec)) goto error;
+            UBool err = exppat == "err";
+            UBool existingPat = FALSE;
+            if (testpat == "-") {
+                if (err) {
+                    errln("FAIL: " + where + "Invalid command \"pat: - err\"");
+                    continue;
+                }
+                existingPat = TRUE;
+                testpat = pat;
+            }
+            if (exppat == "-") exppat = testpat;
+            DecimalFormat* f = 0;
+            UErrorCode ec2 = U_ZERO_ERROR;
+            if (existingPat) {
+                f = fmt;
+            } else {
+                f = new DecimalFormat(testpat, ec2);
+            }
+            if (U_SUCCESS(ec2)) {
+                if (err) {
+                    errln("FAIL: " + where + "Invalid pattern \"" + testpat +
+                          "\" was accepted");
+                } else {
+                    UnicodeString pat2;
+                    assertEquals(where + "\"" + testpat + "\".toPattern()",
+                                 exppat, f->toPattern(pat2));
+                }
+            } else {
+                if (err) {
+                    logln("Ok: " + where + "Invalid pattern \"" + testpat +
+                          "\" failed: " + u_errorName(ec2));
+                } else {
+                    errln("FAIL: " + where + "Valid pattern \"" + testpat +
+                          "\" failed: " + u_errorName(ec2));
+                }
+            }
+            if (!existingPat) delete f;
+            } break;
+        case -1:
+            errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
+            goto done;
+        }
+    }
+    goto done;
+
+ error:
+    if (U_SUCCESS(ec)) {
+        errln("FAIL: Unexpected EOF");
+    } else {
+        errln("FAIL: " + where + "Unexpected " + u_errorName(ec));
+    }
+
+ done:
+    delete mfmt;
+    delete fmt;
+    delete ref;
+}
+
+
 //----------------------------------------------------------------------
 // Support methods
 //----------------------------------------------------------------------
 
 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
+    if (a.getType() == b.getType()) {
+        return a == b;
+    }
+
     if (a.getType() == Formattable::kLong) {
-        if (b.getType() == Formattable::kLong) {
+        if (b.getType() == Formattable::kInt64) {
             return a.getLong() == b.getLong();
         } else if (b.getType() == Formattable::kDouble) {
-            return (double) a.getLong() == b.getDouble();
+            return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long 
         }
     } else if (a.getType() == Formattable::kDouble) {
         if (b.getType() == Formattable::kLong) {
             return a.getDouble() == (double) b.getLong();
+        } else if (b.getType() == Formattable::kInt64) {
+            return a.getDouble() == (double)b.getInt64();
+        }
+    } else if (a.getType() == Formattable::kInt64) {
+        if (b.getType() == Formattable::kLong) {
+                return a.getInt64() == (int64_t)b.getLong();
         } else if (b.getType() == Formattable::kDouble) {
-            return a.getDouble() == b.getDouble();
+            return a.getInt64() == (int64_t)b.getDouble();
         }
     }
     return FALSE;
@@ -1433,14 +2380,14 @@ void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
     UErrorCode ec = U_ZERO_ERROR;
     DecimalFormat& fmt = * (DecimalFormat*) &nf;
     const UChar DEFAULT_CURR[] = {45/*-*/,0};
-    const UChar* curr = DEFAULT_CURR;
+    UChar curr[4];
+    u_strcpy(curr, DEFAULT_CURR);
     if (*locale.getLanguage() != 0) {
-        curr = ucurr_forLocale(locale.getName(), &ec);
-        if (U_FAILURE(ec)) {
-            errln("FAIL: UCurrency::forLocale");
-            return;
-        }
-        fmt.setCurrency(curr);
+        ucurr_forLocale(locale.getName(), curr, 4, &ec);
+        assertSuccess("ucurr_forLocale", ec);
+        fmt.setCurrency(curr, ec);
+        assertSuccess("DecimalFormat::setCurrency", ec);
+        fmt.setCurrency(curr); //Deprecated variant, for coverage only
     }
     UnicodeString s;
     fmt.format(value, s);
@@ -1503,14 +2450,315 @@ void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
         apadStr = pad;
     }
     if (apos == pos && awidth == width && apadStr == pad) {
-        logln(UnicodeString("Ok   \"") + pat + "\" pos=" + apos +
-              ((pos == ILLEGAL) ? UnicodeString() :
-               (UnicodeString(" width=") + awidth + " pad=" + apadStr)));
+        UnicodeString infoStr;
+        if (pos == ILLEGAL) {
+            infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
+        }
+        logln(UnicodeString("Ok   \"") + pat + "\" pos=" + apos + infoStr);
     } else {
         errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
               " width=" + awidth + " pad=" + apadStr +
               ", expected " + pos + " " + width + " " + pad);
     }
 }
+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 s;
+    NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
+    if(U_FAILURE(status)){
+        errln("Could not create currency formatter for locale %s", localeID);
+        return;
+    }
+    currencyFmt->format(1150.50, s);
+    if(s!=expected){
+        errln(UnicodeString("FAIL: Expected: ")+expected 
+                + UnicodeString(" Got: ") + s 
+                + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
+    }
+    if (U_FAILURE(status)){
+        errln("FAIL: Status %s", u_errorName(status));
+    }
+    delete currencyFmt;
+}
+
+void NumberFormatTest::TestHost()
+{
+#ifdef U_WINDOWS
+    Win32NumberTest::testLocales(this);
+#endif
+}
+
+void NumberFormatTest::TestHostClone()
+{
+    /*
+    Verify that a cloned formatter gives the same results
+    and is useable after the original has been deleted.
+    */
+    // This is mainly important on Windows.
+    UErrorCode status = U_ZERO_ERROR;
+    Locale loc("en_US@compat=host");
+    UDate now = Calendar::getNow();
+    NumberFormat *full = NumberFormat::createInstance(loc, status);
+    if (full == NULL || U_FAILURE(status)) {
+        errln("FAIL: Can't create Relative date instance");
+        return;
+    }
+    UnicodeString result1;
+    full->format(now, result1, status);
+    Format *fullClone = full->clone();
+    delete full;
+    full = NULL;
+
+    UnicodeString result2;
+    fullClone->format(now, result2, status);
+    if (U_FAILURE(status)) {
+        errln("FAIL: format failure.");
+    }
+    if (result1 != result2) {
+        errln("FAIL: Clone returned different result from non-clone.");
+    }
+    delete fullClone;
+}
+
+void NumberFormatTest::TestCurrencyFormat()
+{
+    // This test is here to increase code coverage.
+    UErrorCode status = U_ZERO_ERROR;
+    MeasureFormat *cloneObj;
+    UnicodeString str;
+    Formattable toFormat, result;
+    static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
+
+    Locale  saveDefaultLocale = Locale::getDefault();
+    Locale::setDefault( Locale::getUK(), status );
+    if (U_FAILURE(status)) {
+        errln("couldn't set default Locale!");
+        return;
+    }
+
+    MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
+    Locale::setDefault( saveDefaultLocale, status );
+    if (U_FAILURE(status)){
+        errln("FAIL: Status %s", u_errorName(status));
+        return;
+    }
+    cloneObj = (MeasureFormat *)measureObj->clone();
+    if (cloneObj == NULL) {
+        errln("Clone doesn't work");
+        return;
+    }
+    toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
+    measureObj->format(toFormat, str, status);
+    measureObj->parseObject(str, result, status);
+    if (U_FAILURE(status)){
+        errln("FAIL: Status %s", u_errorName(status));
+    }
+    if (result != toFormat) {
+        errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
+    }
+    status = U_ZERO_ERROR;
+    str.truncate(0);
+    cloneObj->format(toFormat, str, status);
+    cloneObj->parseObject(str, result, status);
+    if (U_FAILURE(status)){
+        errln("FAIL: Status %s", u_errorName(status));
+    }
+    if (result != toFormat) {
+        errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
+    }
+    if (*measureObj != *cloneObj) {
+        errln("Cloned object is not equal to the original object");
+    }
+    delete measureObj;
+    delete cloneObj;
+
+    status = U_USELESS_COLLATOR_ERROR;
+    if (MeasureFormat::createCurrencyFormat(status) != NULL) {
+        errln("createCurrencyFormat should have returned NULL.");
+    }
+}
+
+/* Port of ICU4J rounding test. */
+void NumberFormatTest::TestRounding() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
+
+    if (U_FAILURE(status)) {
+        errln("Unable to create decimal formatter.");
+        return;
+    }
+
+    int roundingIncrements[]={1, 2, 5, 20, 50, 100};
+    int testValues[]={0, 300};
+
+    for (int j=0; j<2; j++) {
+        for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
+            df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
+            for (int increment=0; increment<6; increment++) {
+                double base=testValues[j];
+                double rInc=roundingIncrements[increment];
+                checkRounding(df, base, 20, rInc);
+                rInc=1.000000000/rInc;
+                checkRounding(df, base, 20, rInc);
+            }
+        }
+    }
+    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) {
+    UErrorCode status=U_ZERO_ERROR;
+    UnicodeString formattedDecimal;
+    double parsed;
+    Formattable result;
+    df->format(iValue, formattedDecimal, status);
+
+    if (U_FAILURE(status)) {
+        errln("Error formatting number.");
+    }
+
+    df->parse(formattedDecimal, result, status);
+
+    if (U_FAILURE(status)) {
+        errln("Error parsing number.");
+    }
+
+    parsed=result.getDouble();
+
+    if (lastParsed>parsed) {
+        errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
+    }
+
+    return lastParsed;
+}
+
+void NumberFormatTest::TestNonpositiveMultiplier() {
+    UErrorCode status = U_ZERO_ERROR;
+    DecimalFormatSymbols US(Locale::getUS(), status);
+    CHECK(status, "DecimalFormatSymbols constructor");
+    DecimalFormat df(UnicodeString("0"), US, status);
+    CHECK(status, "DecimalFormat(0)");
+    
+    // test zero multiplier
+
+    int32_t mult = df.getMultiplier();
+    df.setMultiplier(0);
+    if (df.getMultiplier() != mult) {
+        errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
+    }
+    
+    // test negative multiplier
+    
+    df.setMultiplier(-1);
+    if (df.getMultiplier() != -1) {
+        errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
+        return;
+    }
+    
+    expect(df, "1122.123", -1122.123);
+    expect(df, "-1122.123", 1122.123);
+    expect(df, "1.2", -1.2);
+    expect(df, "-1.2", 1.2);
+
+    // TODO: change all the following int64_t tests once BigInteger is ported
+    // (right now the big numbers get turned into doubles and lose tons of accuracy)
+    static const char* posOutOfRange = "9223372036854780000";
+    static const char* negOutOfRange = "-9223372036854780000";
+
+    expect(df, U_INT64_MIN, posOutOfRange);
+    expect(df, U_INT64_MIN+1, "9223372036854775807");
+    expect(df, (int64_t)-123, "123");
+    expect(df, (int64_t)123, "-123");
+    expect(df, U_INT64_MAX-1, "-9223372036854775806");
+    expect(df, U_INT64_MAX, "-9223372036854775807");
+
+    df.setMultiplier(-2);
+    expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
+    expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
+    expect(df, -(U_INT64_MIN/2)+1, negOutOfRange);
+
+    df.setMultiplier(-7);
+    expect(df, -(U_INT64_MAX/7)-1, posOutOfRange);
+    expect(df, -(U_INT64_MAX/7), "9223372036854775807");
+    expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
+
+    // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
+    // (right now the big numbers get turned into doubles and lose tons of accuracy)
+    //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
+    //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
+    //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
+    //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
+
+    // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
+    //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
+    //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
+    //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
+    //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
+}
+
+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 $", "3", "-1"},
+    };
+       
+    UErrorCode status = U_ZERO_ERROR;
+       Locale locale("en_US");
+    NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
+    if (U_FAILURE(status)) {
+        delete foo;
+        return;
+    }
+       
+    foo->setParseStrict(FALSE);
+    for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+        ParsePosition parsePosition(0);
+        UnicodeString stringToBeParsed = ctou(DATA[i][0]);
+        int parsedPosition = atoi(DATA[i][1]);
+        int errorIndex = atoi(DATA[i][2]);
+        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() + ")");
+        }
+        if (parsePosition.getErrorIndex() == -1 &&
+            result.getType() == Formattable::kLong &&
+            result.getLong() != 124) {
+            errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
+        }
+    }
+    delete foo;
+}
 
 #endif /* #if !UCONFIG_NO_FORMATTING */