1/* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "platform/text/DateTimeFormat.h" 28 29#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 30#include "wtf/text/CString.h" 31#include "wtf/text/StringBuilder.h" 32#include <gtest/gtest.h> 33 34using namespace WebCore; 35 36class DateTimeFormatTest : public ::testing::Test { 37public: 38 typedef DateTimeFormat::FieldType FieldType; 39 40 struct Token { 41 String string; 42 int count; 43 FieldType fieldType; 44 45 Token(FieldType fieldType, int count = 1) 46 : count(count) 47 , fieldType(fieldType) 48 { 49 ASSERT(fieldType != DateTimeFormat::FieldTypeLiteral); 50 } 51 52 Token(const String& string) 53 : string(string) 54 , count(0) 55 , fieldType(DateTimeFormat::FieldTypeLiteral) 56 { 57 } 58 59 bool operator==(const Token& other) const 60 { 61 return fieldType == other.fieldType && count == other.count && string == other.string; 62 } 63 64 String toString() const 65 { 66 switch (fieldType) { 67 case DateTimeFormat::FieldTypeInvalid: 68 return "*invalid*"; 69 case DateTimeFormat::FieldTypeLiteral: { 70 StringBuilder builder; 71 builder.append('"'); 72 builder.append(string); 73 builder.append('"'); 74 return builder.toString(); 75 } 76 default: 77 return String::format("Token(%d, %d)", fieldType, count); 78 } 79 } 80 }; 81 82 class Tokens { 83 public: 84 Tokens() { } 85 86 explicit Tokens(const Vector<Token> tokens) 87 : m_tokens(tokens) 88 { 89 } 90 91 explicit Tokens(const String& string) 92 { 93 m_tokens.append(Token(string)); 94 } 95 96 explicit Tokens(Token token1) 97 { 98 m_tokens.append(token1); 99 } 100 101 Tokens(Token token1, Token token2) 102 { 103 m_tokens.append(token1); 104 m_tokens.append(token2); 105 } 106 107 Tokens(Token token1, Token token2, Token token3) 108 { 109 m_tokens.append(token1); 110 m_tokens.append(token2); 111 m_tokens.append(token3); 112 } 113 114 Tokens(Token token1, Token token2, Token token3, Token token4) 115 { 116 m_tokens.append(token1); 117 m_tokens.append(token2); 118 m_tokens.append(token3); 119 m_tokens.append(token4); 120 } 121 122 Tokens(Token token1, Token token2, Token token3, Token token4, Token token5) 123 { 124 m_tokens.append(token1); 125 m_tokens.append(token2); 126 m_tokens.append(token3); 127 m_tokens.append(token4); 128 m_tokens.append(token5); 129 } 130 131 Tokens(Token token1, Token token2, Token token3, Token token4, Token token5, Token token6) 132 { 133 m_tokens.append(token1); 134 m_tokens.append(token2); 135 m_tokens.append(token3); 136 m_tokens.append(token4); 137 m_tokens.append(token5); 138 m_tokens.append(token6); 139 } 140 141 bool operator==(const Tokens& other) const 142 { 143 return m_tokens == other.m_tokens; 144 } 145 146 String toString() const 147 { 148 StringBuilder builder; 149 builder.append("Tokens("); 150 for (unsigned index = 0; index < m_tokens.size(); ++index) { 151 if (index) 152 builder.append(","); 153 builder.append(m_tokens[index].toString()); 154 } 155 builder.append(")"); 156 return builder.toString(); 157 } 158 159 private: 160 Vector<Token> m_tokens; 161 }; 162 163protected: 164 Tokens parse(const String& formatString) 165 { 166 TokenHandler handler; 167 if (!DateTimeFormat::parse(formatString, handler)) 168 return Tokens(Token("*failed*")); 169 return handler.tokens(); 170 } 171 172 FieldType single(const char ch) 173 { 174 char formatString[2]; 175 formatString[0] = ch; 176 formatString[1] = 0; 177 TokenHandler handler; 178 if (!DateTimeFormat::parse(formatString, handler)) 179 return DateTimeFormat::FieldTypeInvalid; 180 return handler.fieldType(0); 181 } 182 183private: 184 class TokenHandler : public DateTimeFormat::TokenHandler { 185 public: 186 virtual ~TokenHandler() { } 187 188 FieldType fieldType(int index) const 189 { 190 return index >=0 && index < static_cast<int>(m_tokens.size()) ? m_tokens[index].fieldType : DateTimeFormat::FieldTypeInvalid; 191 } 192 193 Tokens tokens() const { return Tokens(m_tokens); } 194 195 private: 196 virtual void visitField(FieldType fieldType, int count) OVERRIDE 197 { 198 m_tokens.append(Token(fieldType, count)); 199 } 200 201 virtual void visitLiteral(const String& string) OVERRIDE 202 { 203 m_tokens.append(Token(string)); 204 } 205 206 Vector<Token> m_tokens; 207 }; 208}; 209 210std::ostream& operator<<(std::ostream& os, const DateTimeFormatTest::Tokens& tokens) 211{ 212 return os << tokens.toString().ascii().data(); 213} 214 215TEST_F(DateTimeFormatTest, CommonPattern) 216{ 217 EXPECT_EQ(Tokens(), parse("")); 218 219 EXPECT_EQ( 220 Tokens( 221 Token(DateTimeFormat::FieldTypeYear, 4), Token("-"), 222 Token(DateTimeFormat::FieldTypeMonth, 2), Token("-"), 223 Token(DateTimeFormat::FieldTypeDayOfMonth, 2)), 224 parse("yyyy-MM-dd")); 225 226 EXPECT_EQ( 227 Tokens( 228 Token(DateTimeFormat::FieldTypeHour24, 2), Token(":"), 229 Token(DateTimeFormat::FieldTypeMinute, 2), Token(":"), 230 Token(DateTimeFormat::FieldTypeSecond, 2)), 231 parse("kk:mm:ss")); 232 233 EXPECT_EQ( 234 Tokens( 235 Token(DateTimeFormat::FieldTypeHour12), Token(":"), 236 Token(DateTimeFormat::FieldTypeMinute), Token(" "), 237 Token(DateTimeFormat::FieldTypePeriod)), 238 parse("h:m a")); 239 240 EXPECT_EQ( 241 Tokens( 242 Token(DateTimeFormat::FieldTypeYear), Token("Nen "), 243 Token(DateTimeFormat::FieldTypeMonth), Token("Getsu "), 244 Token(DateTimeFormat::FieldTypeDayOfMonth), Token("Nichi")), 245 parse("y'Nen' M'Getsu' d'Nichi'")); 246} 247 248TEST_F(DateTimeFormatTest, MissingClosingQuote) 249{ 250 EXPECT_EQ(Tokens("*failed*"), parse("'foo")); 251 EXPECT_EQ(Tokens("*failed*"), parse("fo'o")); 252 EXPECT_EQ(Tokens("*failed*"), parse("foo'")); 253} 254 255TEST_F(DateTimeFormatTest, Quote) 256{ 257 EXPECT_EQ(Tokens("FooBar"), parse("'FooBar'")); 258 EXPECT_EQ(Tokens("'"), parse("''")); 259 EXPECT_EQ(Tokens("'-'"), parse("''-''")); 260 EXPECT_EQ(Tokens("Foo'Bar"), parse("'Foo''Bar'")); 261 EXPECT_EQ( 262 Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'s")), 263 parse("G'''s'")); 264 EXPECT_EQ( 265 Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'"), Token(DateTimeFormat::FieldTypeSecond)), 266 parse("G''s")); 267} 268 269TEST_F(DateTimeFormatTest, SingleLowerCaseCharacter) 270{ 271 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('b')); 272 EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, single('c')); 273 EXPECT_EQ(DateTimeFormat::FieldTypeDayOfMonth, single('d')); 274 EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeek, single('e')); 275 EXPECT_EQ(DateTimeFormat::FieldTypeModifiedJulianDay, single('g')); 276 EXPECT_EQ(DateTimeFormat::FieldTypeHour12, single('h')); 277 EXPECT_EQ(DateTimeFormat::FieldTypeHour24, single('k')); 278 EXPECT_EQ(DateTimeFormat::FieldTypeMinute, single('m')); 279 EXPECT_EQ(DateTimeFormat::FieldTypeQuaterStandAlone, single('q')); 280 EXPECT_EQ(DateTimeFormat::FieldTypeSecond, single('s')); 281 EXPECT_EQ(DateTimeFormat::FieldTypeExtendedYear, single('u')); 282 EXPECT_EQ(DateTimeFormat::FieldTypeNonLocationZone, single('v')); 283 EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfMonth, single('W')); 284 EXPECT_EQ(DateTimeFormat::FieldTypeYear, single('y')); 285 EXPECT_EQ(DateTimeFormat::FieldTypeZone, single('z')); 286} 287 288TEST_F(DateTimeFormatTest, SingleLowerCaseInvalid) 289{ 290 EXPECT_EQ(DateTimeFormat::FieldTypePeriod, single('a')); 291 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('f')); 292 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('i')); 293 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('j')); 294 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('l')); 295 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('n')); 296 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('o')); 297 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('p')); 298 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('r')); 299 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('t')); 300 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('x')); 301} 302 303TEST_F(DateTimeFormatTest, SingleUpperCaseCharacter) 304{ 305 EXPECT_EQ(DateTimeFormat::FieldTypeMillisecondsInDay, single('A')); 306 EXPECT_EQ(DateTimeFormat::FieldTypeDayOfYear, single('D')); 307 EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeek, single('E')); 308 EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeekInMonth, single('F')); 309 EXPECT_EQ(DateTimeFormat::FieldTypeEra, single('G')); 310 EXPECT_EQ(DateTimeFormat::FieldTypeHour23, single('H')); 311 EXPECT_EQ(DateTimeFormat::FieldTypeHour11, single('K')); 312 EXPECT_EQ(DateTimeFormat::FieldTypeMonthStandAlone, single('L')); 313 EXPECT_EQ(DateTimeFormat::FieldTypeMonth, single('M')); 314 EXPECT_EQ(DateTimeFormat::FieldTypeQuater, single('Q')); 315 EXPECT_EQ(DateTimeFormat::FieldTypeFractionalSecond, single('S')); 316 EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfYear, single('w')); 317 EXPECT_EQ(DateTimeFormat::FieldTypeYearOfWeekOfYear, single('Y')); 318 EXPECT_EQ(DateTimeFormat::FieldTypeRFC822Zone, single('Z')); 319} 320 321TEST_F(DateTimeFormatTest, SingleUpperCaseInvalid) 322{ 323 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('B')); 324 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('C')); 325 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('I')); 326 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('J')); 327 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('N')); 328 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('O')); 329 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('P')); 330 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('R')); 331 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('T')); 332 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('U')); 333 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('V')); 334 EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('X')); 335} 336 337#endif 338