Index: base/i18n/message_formatter_unittest.cc |
diff --git a/base/i18n/message_formatter_unittest.cc b/base/i18n/message_formatter_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..85e2e171cb11560718338b93414fadc5a91f9620 |
--- /dev/null |
+++ b/base/i18n/message_formatter_unittest.cc |
@@ -0,0 +1,180 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/i18n/message_formatter.h" |
+ |
+#include "base/i18n/rtl.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/strings/string_piece.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/time/time.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/icu/source/common/unicode/unistr.h" |
+#include "third_party/icu/source/i18n/unicode/datefmt.h" |
+#include "third_party/icu/source/i18n/unicode/msgfmt.h" |
+ |
+typedef testing::Test MessageFormatterTest; |
+ |
+namespace base { |
+namespace i18n { |
+ |
+class MessageFormatterTest : public testing::Test { |
+ protected: |
+ MessageFormatterTest() { |
+ original_locale_ = GetConfiguredLocale(); |
+ SetICUDefaultLocale("en-US"); |
+ } |
+ ~MessageFormatterTest() override { |
+ SetICUDefaultLocale(original_locale_); |
+ } |
+ |
+ private: |
+ std::string original_locale_; |
+}; |
+ |
+namespace { |
+ |
+void AppendFormattedDateTime(const scoped_ptr<icu::DateFormat>& df, |
+ const Time& now, std::string* result) { |
+ icu::UnicodeString formatted; |
+ df->format(static_cast<UDate>(now.ToJsTime()), formatted). |
+ toUTF8String(*result); |
+} |
+ |
+} // namespace |
+ |
+TEST_F(MessageFormatterTest, PluralNamedArgs) { |
+ const string16 pattern = ASCIIToUTF16( |
+ "{num_people, plural, " |
+ "=0 {I met nobody in {place}.}" |
+ "=1 {I met a person in {place}.}" |
+ "other {I met # people in {place}.}}"); |
+ |
+ std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 0, "place", "Paris")); |
+ EXPECT_EQ("I met nobody in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 1, "place", "Paris")); |
+ EXPECT_EQ("I met a person in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 5, "place", "Paris")); |
+ EXPECT_EQ("I met 5 people in Paris.", result); |
+} |
+ |
+TEST_F(MessageFormatterTest, PluralNamedArgsWithOffset) { |
+ const string16 pattern = ASCIIToUTF16( |
+ "{num_people, plural, offset:1 " |
+ "=0 {I met nobody in {place}.}" |
+ "=1 {I met {person} in {place}.}" |
+ "=2 {I met {person} and one other person in {place}.}" |
+ "=13 {I met {person} and a dozen other people in {place}.}" |
+ "other {I met {person} and # other people in {place}.}}"); |
+ |
+ std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 0, "place", "Paris")); |
+ EXPECT_EQ("I met nobody in Paris.", result); |
+ // {person} is ignored if {num_people} is 0. |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 0, "place", "Paris", "person", "Peter")); |
+ EXPECT_EQ("I met nobody in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 1, "place", "Paris", "person", "Peter")); |
+ EXPECT_EQ("I met Peter in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 2, "place", "Paris", "person", "Peter")); |
+ EXPECT_EQ("I met Peter and one other person in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 13, "place", "Paris", "person", "Peter")); |
+ EXPECT_EQ("I met Peter and a dozen other people in Paris.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( |
+ pattern, "num_people", 50, "place", "Paris", "person", "Peter")); |
+ EXPECT_EQ("I met Peter and 49 other people in Paris.", result); |
+} |
+ |
+TEST_F(MessageFormatterTest, PluralNumberedArgs) { |
+ const string16 pattern = ASCIIToUTF16( |
+ "{1, plural, " |
+ "=1 {The cert for {0} expired yesterday.}" |
+ "=7 {The cert for {0} expired a week ago.}" |
+ "other {The cert for {0} expired # days ago.}}"); |
+ |
+ std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "example.com", 1)); |
+ EXPECT_EQ("The cert for example.com expired yesterday.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "example.com", 7)); |
+ EXPECT_EQ("The cert for example.com expired a week ago.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "example.com", 15)); |
+ EXPECT_EQ("The cert for example.com expired 15 days ago.", result); |
+} |
+ |
+TEST_F(MessageFormatterTest, PluralNumberedArgsWithDate) { |
+ const string16 pattern = ASCIIToUTF16( |
+ "{1, plural, " |
+ "=1 {The cert for {0} expired yesterday. Today is {2,date,full}}" |
+ "other {The cert for {0} expired # days ago. Today is {2,date,full}}}"); |
+ |
+ base::Time now = base::Time::Now(); |
+ using icu::DateFormat; |
+ scoped_ptr<DateFormat> df(DateFormat::createDateInstance(DateFormat::FULL)); |
+ std::string second_sentence = " Today is "; |
+ AppendFormattedDateTime(df, now, &second_sentence); |
+ |
+ std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "example.com", 1, now)); |
+ EXPECT_EQ("The cert for example.com expired yesterday." + second_sentence, |
+ result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "example.com", 15, now)); |
+ EXPECT_EQ("The cert for example.com expired 15 days ago." + second_sentence, |
+ result); |
+} |
+ |
+TEST_F(MessageFormatterTest, DateTimeAndNumber) { |
+ // Note that using 'mph' for all locales is not a good i18n practice. |
+ const string16 pattern = ASCIIToUTF16( |
+ "At {0,time, short} on {0,date, medium}, " |
+ "there was {1} at building {2,number,integer}. " |
+ "The speed of the wind was {3,number,###.#} mph."); |
+ |
+ using icu::DateFormat; |
+ scoped_ptr<DateFormat> tf(DateFormat::createTimeInstance(DateFormat::SHORT)); |
+ scoped_ptr<DateFormat> df(DateFormat::createDateInstance(DateFormat::MEDIUM)); |
+ |
+ base::Time now = base::Time::Now(); |
+ std::string expected = "At "; |
+ AppendFormattedDateTime(tf, now, &expected); |
+ expected.append(" on "); |
+ AppendFormattedDateTime(df, now, &expected); |
+ expected.append(", there was an explosion at building 3. " |
+ "The speed of the wind was 37.4 mph."); |
+ |
+ EXPECT_EQ(expected, UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, now, "an explosion", 3, 37.413))); |
+} |
+ |
+TEST_F(MessageFormatterTest, SelectorSingleOrMultiple) { |
+ const string16 pattern = ASCIIToUTF16( |
+ "{0, select," |
+ "single {Select a file to upload.}" |
+ "multiple {Select files to upload.}" |
+ "other {UNUSED}}"); |
+ |
+ std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "single")); |
+ EXPECT_EQ("Select a file to upload.", result); |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "multiple")); |
+ EXPECT_EQ("Select files to upload.", result); |
+ |
+ // fallback if a parameter is not selectors specified in the message pattern. |
+ result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( |
+ pattern, "foobar")); |
+ EXPECT_EQ("UNUSED", result); |
+} |
+ |
+} // namespace i18n |
+} // namespace base |