Title: [109876] trunk
Revision
109876
Author
[email protected]
Date
2012-03-06 01:12:44 -0800 (Tue, 06 Mar 2012)

Log Message

Do not reformat strings in <input type=number> on platforms using LocalizedNumberICU.
https://bugs.webkit.org/show_bug.cgi?id=78326

Reviewed by Hajime Morita.

Source/WebCore:

We had bugs such as stripping leading zeros, dropping lower digits
of large numbers because we parse a user-input string to a double
value, and generate a string from the double value.

In order to avoid such reformatting, we converts number strings by
replacing standard digits to corresponding localized digits.

* WebCore.gypi: Added LocalizedNumberICU.h
* platform/text/LocalizedNumberICU.cpp:
(WebCore::ICULocale::ICULocale): Added.
(WebCore::ICULocale::create): A testing factory function.
(WebCore::ICULocale::createForCurrentLocale): A practical factory function.
(WebCore::ICULocale::setDecimalSymbol): Initialize a symbol table.
(WebCore::ICULocale::initializeDecimalFormat): Initialize ICU DecimalFormat.
(WebCore::ICULocale::convertToLocalizedNumber):
 Replace characters to corresponding localized characters.
(WebCore::matches): A helper function for convertFromLocalizedNumber.
(WebCore::endsWith): ditto.
(WebCore::ICULocale::determineStartPosition): ditto.
(WebCore::ICULocale::matchedDecimalSymbolIndex): ditto.
(WebCore::ICULocale::convertFromLocalizedNumber):
 Replace characters to corresponding standard characters.
(WebCore::currentLocale): Added.
(WebCore::convertToLocalizedNumber): Uses ICULocale::convertToLocalizedNumber.
(WebCore::convertFromLocalizedNumber): Uses ICULocale::convertFromLocalizedNumber.
* platform/text/LocalizedNumberICU.h: Added.
(ICULocale): Added. This is exposed to WebKit/chromium/tests/LocalizedNumberICUTest.cpp.

Source/WebKit/chromium:

Add a test for WebCore/platform/text/LocalizedNumberICU.

* WebKit.gypi: Added LocalizedNumberICUTest.cpp
* tests/LocalizedNumberICUTest.cpp: Added.

LayoutTests:

* platform/chromium/test_expectations.txt:
Need to do rebaseline for
fast/speech/input-appearance-numberandspeech.html because the
number rounding issue is fixed.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (109875 => 109876)


--- trunk/LayoutTests/ChangeLog	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/LayoutTests/ChangeLog	2012-03-06 09:12:44 UTC (rev 109876)
@@ -1,3 +1,15 @@
+2012-03-05  Kent Tamura  <[email protected]>
+
+        Do not reformat strings in <input type=number> on platforms using LocalizedNumberICU.
+        https://bugs.webkit.org/show_bug.cgi?id=78326
+
+        Reviewed by Hajime Morita.
+
+        * platform/chromium/test_expectations.txt:
+        Need to do rebaseline for
+        fast/speech/input-appearance-numberandspeech.html because the
+        number rounding issue is fixed.
+
 2012-03-06  Mike Lawther  <[email protected]>
 
         CSS3 calc: rewrite margin test to use getComputedStyle

Modified: trunk/LayoutTests/platform/chromium/test_expectations.txt (109875 => 109876)


--- trunk/LayoutTests/platform/chromium/test_expectations.txt	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/LayoutTests/platform/chromium/test_expectations.txt	2012-03-06 09:12:44 UTC (rev 109876)
@@ -3496,6 +3496,9 @@
 BUGWK69714 WIN LINUX : svg/clip-path/clip-path-tspan-and-stroke.svg = IMAGE+TEXT
 BUGWK77103 MAC : svg/repaint/image-href-change.svg = IMAGE
 
+// Need rebaseline
+BUGWK78326 : fast/speech/input-appearance-numberandspeech.html = FAIL
+
 // Need to implement file name logging.
 BUGWK76572 : http/tests/download = FAIL
 

Modified: trunk/Source/WebCore/ChangeLog (109875 => 109876)


--- trunk/Source/WebCore/ChangeLog	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/Source/WebCore/ChangeLog	2012-03-06 09:12:44 UTC (rev 109876)
@@ -1,3 +1,38 @@
+2012-03-05  Kent Tamura  <[email protected]>
+
+        Do not reformat strings in <input type=number> on platforms using LocalizedNumberICU.
+        https://bugs.webkit.org/show_bug.cgi?id=78326
+
+        Reviewed by Hajime Morita.
+
+        We had bugs such as stripping leading zeros, dropping lower digits
+        of large numbers because we parse a user-input string to a double
+        value, and generate a string from the double value.
+
+        In order to avoid such reformatting, we converts number strings by
+        replacing standard digits to corresponding localized digits.
+
+        * WebCore.gypi: Added LocalizedNumberICU.h
+        * platform/text/LocalizedNumberICU.cpp:
+        (WebCore::ICULocale::ICULocale): Added.
+        (WebCore::ICULocale::create): A testing factory function.
+        (WebCore::ICULocale::createForCurrentLocale): A practical factory function.
+        (WebCore::ICULocale::setDecimalSymbol): Initialize a symbol table.
+        (WebCore::ICULocale::initializeDecimalFormat): Initialize ICU DecimalFormat.
+        (WebCore::ICULocale::convertToLocalizedNumber):
+         Replace characters to corresponding localized characters.
+        (WebCore::matches): A helper function for convertFromLocalizedNumber.
+        (WebCore::endsWith): ditto.
+        (WebCore::ICULocale::determineStartPosition): ditto.
+        (WebCore::ICULocale::matchedDecimalSymbolIndex): ditto.
+        (WebCore::ICULocale::convertFromLocalizedNumber):
+         Replace characters to corresponding standard characters.
+        (WebCore::currentLocale): Added.
+        (WebCore::convertToLocalizedNumber): Uses ICULocale::convertToLocalizedNumber.
+        (WebCore::convertFromLocalizedNumber): Uses ICULocale::convertFromLocalizedNumber.
+        * platform/text/LocalizedNumberICU.h: Added.
+        (ICULocale): Added. This is exposed to WebKit/chromium/tests/LocalizedNumberICUTest.cpp.
+
 2012-03-06  Adam Barth  <[email protected]>
 
         Attempt to fix the GTK minimal build

Modified: trunk/Source/WebCore/WebCore.gypi (109875 => 109876)


--- trunk/Source/WebCore/WebCore.gypi	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/Source/WebCore/WebCore.gypi	2012-03-06 09:12:44 UTC (rev 109876)
@@ -4213,6 +4213,7 @@
             'platform/text/LocalizedDateNone.cpp',
             'platform/text/LocalizedNumber.h',
             'platform/text/LocalizedNumberICU.cpp',
+            'platform/text/LocalizedNumberICU.h',
             'platform/text/LocalizedNumberNone.cpp',
             'platform/text/ParserUtilities.h',
             'platform/text/QuotedPrintable.h',

Modified: trunk/Source/WebCore/platform/text/LocalizedNumberICU.cpp (109875 => 109876)


--- trunk/Source/WebCore/platform/text/LocalizedNumberICU.cpp	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/Source/WebCore/platform/text/LocalizedNumberICU.cpp	2012-03-06 09:12:44 UTC (rev 109876)
@@ -29,107 +29,240 @@
  */
 
 #include "config.h"
+#include "LocalizedNumberICU.h"
+
 #include "LocalizedNumber.h"
-
-#include <limits>
+#include <unicode/decimfmt.h>
 #include <unicode/numfmt.h>
-#include <unicode/parsepos.h>
-#include <wtf/MainThread.h>
-#include <wtf/MathExtras.h>
 #include <wtf/PassOwnPtr.h>
-#include <wtf/dtoa.h>
+#include <wtf/text/StringBuilder.h>
 
 using namespace icu;
-using namespace std;
 
 namespace WebCore {
 
-static PassOwnPtr<NumberFormat> createFormatterForCurrentLocale()
+ICULocale::ICULocale(const Locale& locale)
+    : m_locale(locale)
+    , m_didCreateDecimalFormat(false)
 {
+}
+
+PassOwnPtr<ICULocale> ICULocale::create(const char* localeString)
+{
+    return adoptPtr(new ICULocale(Locale::createCanonical(localeString)));
+}
+
+PassOwnPtr<ICULocale> ICULocale::createForCurrentLocale()
+{
+    return adoptPtr(new ICULocale(Locale::getDefault()));
+}
+
+void ICULocale::setDecimalSymbol(unsigned index, DecimalFormatSymbols::ENumberFormatSymbol symbol)
+{
+    UnicodeString ustring = m_decimalFormat->getDecimalFormatSymbols()->getSymbol(symbol);
+    m_decimalSymbols[index] = String(ustring.getBuffer(), ustring.length());
+}
+
+void ICULocale::initializeDecimalFormat()
+{
+    if (m_didCreateDecimalFormat)
+        return;
+    m_didCreateDecimalFormat = true;
     UErrorCode status = U_ZERO_ERROR;
-    OwnPtr<NumberFormat> formatter = adoptPtr(NumberFormat::createInstance(status));
-    return U_SUCCESS(status) ? formatter.release() : nullptr;
+    NumberFormat* format = NumberFormat::createInstance(m_locale, NumberFormat::kNumberStyle, status);
+    if (!U_SUCCESS(status))
+        return;
+    m_decimalFormat = adoptPtr(static_cast<DecimalFormat*>(format));
+
+    setDecimalSymbol(0, DecimalFormatSymbols::kZeroDigitSymbol);
+    setDecimalSymbol(1, DecimalFormatSymbols::kOneDigitSymbol);
+    setDecimalSymbol(2, DecimalFormatSymbols::kTwoDigitSymbol);
+    setDecimalSymbol(3, DecimalFormatSymbols::kThreeDigitSymbol);
+    setDecimalSymbol(4, DecimalFormatSymbols::kFourDigitSymbol);
+    setDecimalSymbol(5, DecimalFormatSymbols::kFiveDigitSymbol);
+    setDecimalSymbol(6, DecimalFormatSymbols::kSixDigitSymbol);
+    setDecimalSymbol(7, DecimalFormatSymbols::kSevenDigitSymbol);
+    setDecimalSymbol(8, DecimalFormatSymbols::kEightDigitSymbol);
+    setDecimalSymbol(9, DecimalFormatSymbols::kNineDigitSymbol);
+    setDecimalSymbol(DecimalSeparatorIndex, DecimalFormatSymbols::kDecimalSeparatorSymbol);
+    setDecimalSymbol(GroupSeparatorIndex, DecimalFormatSymbols::kGroupingSeparatorSymbol);
 }
 
-static PassOwnPtr<NumberFormat> createFormatterForCurrentLocaleToDisplay()
+String ICULocale::convertToLocalizedNumber(const String& input)
 {
-    OwnPtr<NumberFormat> formatter(createFormatterForCurrentLocale());
-    if (!formatter)
-        return nullptr;
+    initializeDecimalFormat();
+    if (!m_decimalFormat || input.isEmpty())
+        return input;
 
-    formatter->setGroupingUsed(FALSE);
-    return formatter.release();
+    unsigned i = 0;
+    bool isNegative = false;
+    UnicodeString ustring;
+
+    if (input[0] == '-') {
+        ++i;
+        isNegative = true;
+        m_decimalFormat->getNegativePrefix(ustring);
+    } else
+        m_decimalFormat->getPositivePrefix(ustring);
+    StringBuilder builder;
+    builder.reserveCapacity(input.length());
+    builder.append(ustring.getBuffer(), ustring.length());
+
+    for (; i < input.length(); ++i) {
+        switch (input[i]) {
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            builder.append(m_decimalSymbols[input[i] - '0']);
+            break;
+        case '.':
+            builder.append(m_decimalSymbols[DecimalSeparatorIndex]);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    if (isNegative)
+        m_decimalFormat->getNegativeSuffix(ustring);
+    else
+        m_decimalFormat->getPositiveSuffix(ustring);
+    builder.append(ustring.getBuffer(), ustring.length());
+
+    return builder.toString();
 }
 
-// This might return 0.
-static NumberFormat* numberFormatterForParsing()
+template <class StringType> static bool matches(const String& text, unsigned position, const StringType& part)
 {
-    ASSERT(isMainThread());
-    static NumberFormat* formatter = createFormatterForCurrentLocale().leakPtr();
-    return formatter;
+    if (part.isEmpty())
+        return true;
+    if (position + part.length() > text.length())
+        return false;
+    for (unsigned i = 0; i < static_cast<unsigned>(part.length()); ++i) {
+        if (text[position + i] != part[i])
+            return false;
+    }
+    return true;
 }
 
-// This might return 0.
-static NumberFormat* numberFormatterForDisplay()
+static bool endsWith(const String& text, const UnicodeString& suffix)
 {
-    ASSERT(isMainThread());
-    static NumberFormat* formatter = createFormatterForCurrentLocaleToDisplay().leakPtr();
-    return formatter;
+    if (suffix.length() <= 0)
+        return true;
+    unsigned suffixLength = static_cast<unsigned>(suffix.length());
+    if (suffixLength > text.length())
+        return false;
+    unsigned start = text.length() - suffixLength;
+    for (unsigned i = 0; i < suffixLength; ++i) {
+        if (text[start + i] != suffix[i])
+            return false;
+    }
+    return true;
 }
 
-static double parseLocalizedNumber(const String& numberString)
+bool ICULocale::detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex)
 {
-    if (numberString.isEmpty())
-        return numeric_limits<double>::quiet_NaN();
-    NumberFormat* formatter = numberFormatterForParsing();
-    if (!formatter)
-        return numeric_limits<double>::quiet_NaN();
-    UnicodeString numberUnicodeString(numberString.characters(), numberString.length());
-    Formattable result;
-    ParsePosition position(0);
-    formatter->parse(numberUnicodeString, result, position);
-    if (position.getIndex() != numberUnicodeString.length())
-        return numeric_limits<double>::quiet_NaN();
-    UErrorCode status = U_ZERO_ERROR;
-    double numericResult = result.getDouble(status);
-    return U_SUCCESS(status) ? numericResult : numeric_limits<double>::quiet_NaN();
+    startIndex = 0;
+    endIndex = input.length();
+    UnicodeString prefix;
+    m_decimalFormat->getNegativePrefix(prefix);
+    UnicodeString suffix;
+    m_decimalFormat->getNegativeSuffix(suffix);
+    if (prefix.isEmpty() && suffix.isEmpty()) {
+        m_decimalFormat->getPositivePrefix(prefix);
+        m_decimalFormat->getPositiveSuffix(suffix);
+        ASSERT(!(prefix.isEmpty() && suffix.isEmpty()));
+        if (matches(input, 0, prefix) && endsWith(input, suffix)) {
+            isNegative = false;
+            startIndex = prefix.length();
+            endIndex -= suffix.length();
+        } else
+            isNegative = true;
+    } else {
+        if (matches(input, 0, prefix) && endsWith(input, suffix)) {
+            isNegative = true;
+            startIndex = prefix.length();
+            endIndex -= suffix.length();
+        } else {
+            isNegative = false;
+            m_decimalFormat->getPositivePrefix(prefix);
+            m_decimalFormat->getPositiveSuffix(suffix);
+            if (matches(input, 0, prefix) && endsWith(input, suffix)) {
+                startIndex = prefix.length();
+                endIndex -= suffix.length();
+            } else
+                return false;
+        }
+    }
+    return true;
 }
 
-static String formatLocalizedNumber(double number, unsigned fractionDigits)
+unsigned ICULocale::matchedDecimalSymbolIndex(const String& input, unsigned& position)
 {
-    NumberFormat* formatter = numberFormatterForDisplay();
-    if (!formatter)
-        return String();
-    UnicodeString result;
-    formatter->setMaximumFractionDigits(clampToInteger(fractionDigits));
-    formatter->format(number, result);
-    return String(result.getBuffer(), result.length());
+    for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolIndex) {
+        if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m_decimalSymbols[symbolIndex])) {
+            position += m_decimalSymbols[symbolIndex].length();
+            return symbolIndex;
+        }
+    }
+    return DecimalSymbolsSize;
 }
 
-String convertToLocalizedNumber(const String& canonicalNumberString, unsigned fractionDigits)
+String ICULocale::convertFromLocalizedNumber(const String& localized)
 {
-    // FIXME: We should not do parse-then-format. It makes some
-    // problems such as removing leading zeros, changing trailing
-    // digits to zeros.
-    // FIXME: We should not use the fractionDigits argument.
+    initializeDecimalFormat();
+    String input = localized.stripWhiteSpace();
+    if (!m_decimalFormat || input.isEmpty())
+        return input;
 
-    double doubleValue = canonicalNumberString.toDouble();
-    // The input string must be valid.
-    return formatLocalizedNumber(doubleValue, fractionDigits);
+    bool isNegative;
+    unsigned startIndex;
+    unsigned endIndex;
+    if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) {
+        // Input is broken. Returning an invalid number string.
+        return "*";
+    }
 
+    StringBuilder builder;
+    builder.reserveCapacity(input.length());
+    if (isNegative)
+        builder.append("-");
+    for (unsigned i = startIndex; i < endIndex;) {
+        unsigned symbolIndex = matchedDecimalSymbolIndex(input, i);
+        if (symbolIndex >= DecimalSymbolsSize)
+            return "*";
+        if (symbolIndex == DecimalSeparatorIndex)
+            builder.append('.');
+        else if (symbolIndex == GroupSeparatorIndex) {
+            // Ignore group separators.
+
+        } else
+            builder.append(static_cast<UChar>('0' + symbolIndex));
+    }
+    return builder.toString();
 }
 
-String convertFromLocalizedNumber(const String& localizedNumberString)
+static ICULocale* currentLocale()
 {
-    // FIXME: We should not do parse-then-format. It makes some
-    // problems such as removing leading zeros, changing trailing
-    // digits to zeros.
+    static ICULocale* currentICULocale = ICULocale::createForCurrentLocale().leakPtr();
+    return currentICULocale;
+}
 
-    double doubleValue = parseLocalizedNumber(localizedNumberString);
-    if (!isfinite(doubleValue))
-        return localizedNumberString;
-    NumberToStringBuffer buffer;
-    return String(numberToString(doubleValue, buffer));
+String convertToLocalizedNumber(const String& canonicalNumberString, unsigned fractionDigits)
+{
+    return currentLocale()->convertToLocalizedNumber(canonicalNumberString);
 }
 
+String convertFromLocalizedNumber(const String& localizedNumberString)
+{
+    return currentLocale()->convertFromLocalizedNumber(localizedNumberString);
+}
+
 } // namespace WebCore

Added: trunk/Source/WebCore/platform/text/LocalizedNumberICU.h (0 => 109876)


--- trunk/Source/WebCore/platform/text/LocalizedNumberICU.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/text/LocalizedNumberICU.h	2012-03-06 09:12:44 UTC (rev 109876)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LocalizedNumberICU_h
+#define LocalizedNumberICU_h
+
+#include <unicode/decimfmt.h>
+#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// We should use this class only for LocalizedNumberICU.cpp and LocalizedNumberICUTest.cpp.
+class ICULocale {
+public:
+    static PassOwnPtr<ICULocale> create(const char* localeString);
+    static PassOwnPtr<ICULocale> createForCurrentLocale();
+    String convertToLocalizedNumber(const String&);
+    String convertFromLocalizedNumber(const String&);
+
+private:
+    explicit ICULocale(const icu::Locale&);
+    void setDecimalSymbol(unsigned index, icu::DecimalFormatSymbols::ENumberFormatSymbol);
+    void initializeDecimalFormat();
+
+    bool detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex);
+    unsigned matchedDecimalSymbolIndex(const String& input, unsigned& position);
+
+    icu::Locale m_locale;
+    OwnPtr<icu::DecimalFormat> m_decimalFormat;
+    enum {
+        // 0-9 for digits.
+        DecimalSeparatorIndex = 10,
+        GroupSeparatorIndex = 11,
+        DecimalSymbolsSize
+    };
+    String m_decimalSymbols[DecimalSymbolsSize];
+    bool m_didCreateDecimalFormat;
+};
+
+}
+#endif
Property changes on: trunk/Source/WebCore/platform/text/LocalizedNumberICU.h
___________________________________________________________________

Added: svn:eol-style

Modified: trunk/Source/WebKit/chromium/ChangeLog (109875 => 109876)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-03-06 09:12:44 UTC (rev 109876)
@@ -1,3 +1,15 @@
+2012-03-05  Kent Tamura  <[email protected]>
+
+        Do not reformat strings in <input type=number> on platforms using LocalizedNumberICU.
+        https://bugs.webkit.org/show_bug.cgi?id=78326
+
+        Reviewed by Hajime Morita.
+
+        Add a test for WebCore/platform/text/LocalizedNumberICU.
+
+        * WebKit.gypi: Added LocalizedNumberICUTest.cpp
+        * tests/LocalizedNumberICUTest.cpp: Added.
+
 2012-03-05  Kenneth Russell  <[email protected]>
 
         [chromium] Notify CCLayerImpl tree of context loss and restoration

Modified: trunk/Source/WebKit/chromium/WebKit.gypi (109875 => 109876)


--- trunk/Source/WebKit/chromium/WebKit.gypi	2012-03-06 09:07:47 UTC (rev 109875)
+++ trunk/Source/WebKit/chromium/WebKit.gypi	2012-03-06 09:12:44 UTC (rev 109876)
@@ -106,6 +106,7 @@
             'tests/LayerChromiumTest.cpp',
             'tests/LayerTextureUpdaterTest.cpp',
             'tests/LevelDBTest.cpp',
+            'tests/LocalizedNumberICUTest.cpp',
             'tests/PaintAggregatorTest.cpp',
             'tests/PODArenaTest.cpp',
             'tests/PODIntervalTreeTest.cpp',

Added: trunk/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp (0 => 109876)


--- trunk/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp	                        (rev 0)
+++ trunk/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp	2012-03-06 09:12:44 UTC (rev 109876)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocalizedNumberICU.h"
+
+#include <gtest/gtest.h>
+#include <wtf/PassOwnPtr.h>
+
+using namespace WebCore;
+
+void testNumberIsReversible(const char* localeString, const char* original, const char* shouldHave = 0)
+{
+    OwnPtr<ICULocale> locale = ICULocale::create(localeString);
+    String localized = locale->convertToLocalizedNumber(original);
+    if (shouldHave)
+        EXPECT_TRUE(localized.contains(shouldHave));
+    String converted = locale->convertFromLocalizedNumber(localized);
+    EXPECT_EQ(original, converted);
+}
+
+void testNumbers(const char* localeString)
+{
+    testNumberIsReversible(localeString, "123456789012345678901234567890");
+    testNumberIsReversible(localeString, "-123.456");
+    testNumberIsReversible(localeString, ".456");
+    testNumberIsReversible(localeString, "-0.456");
+}
+
+TEST(LocalizedNumberICUTest, Reversible)
+{
+    testNumberIsReversible("en_US", "123456789012345678901234567890");
+    testNumberIsReversible("en_US", "-123.456", ".");
+    testNumberIsReversible("en_US", ".456", ".");
+    testNumberIsReversible("en_US", "-0.456", ".");
+
+    testNumberIsReversible("fr", "123456789012345678901234567890");
+    testNumberIsReversible("fr", "-123.456", ",");
+    testNumberIsReversible("fr", ".456", ",");
+    testNumberIsReversible("fr", "-0.456", ",");
+
+    // Persian locale has a negative prefix and a negative suffix.
+    testNumbers("fa");
+
+    // Test some of major locales.
+    testNumbers("ar");
+    testNumbers("de_DE");
+    testNumbers("es_ES");
+    testNumbers("ja_JP");
+    testNumbers("ko_KR");
+    testNumbers("zh_CN");
+    testNumbers("zh_HK");
+    testNumbers("zh_TW");
+}
Property changes on: trunk/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp
___________________________________________________________________

Added: svn:eol-style

_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to