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
34 using namespace WebCore;
35
36 class DateTimeFormatTest : public ::testing::Test {
37 public:
38 typedef DateTimeFormat::FieldType FieldType;
39
40 struct Token {
41 String string;
42 int count;
43 FieldType fieldType;
44
TokenDateTimeFormatTest::Token45 Token(FieldType fieldType, int count = 1)
46 : count(count)
47 , fieldType(fieldType)
48 {
49 ASSERT(fieldType != DateTimeFormat::FieldTypeLiteral);
50 }
51
TokenDateTimeFormatTest::Token52 Token(const String& string)
53 : string(string)
54 , count(0)
55 , fieldType(DateTimeFormat::FieldTypeLiteral)
56 {
57 }
58
operator ==DateTimeFormatTest::Token59 bool operator==(const Token& other) const
60 {
61 return fieldType == other.fieldType && count == other.count && string == other.string;
62 }
63
toStringDateTimeFormatTest::Token64 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:
Tokens()84 Tokens() { }
85
Tokens(const Vector<Token> tokens)86 explicit Tokens(const Vector<Token> tokens)
87 : m_tokens(tokens)
88 {
89 }
90
Tokens(const String & string)91 explicit Tokens(const String& string)
92 {
93 m_tokens.append(Token(string));
94 }
95
Tokens(Token token1)96 explicit Tokens(Token token1)
97 {
98 m_tokens.append(token1);
99 }
100
Tokens(Token token1,Token token2)101 Tokens(Token token1, Token token2)
102 {
103 m_tokens.append(token1);
104 m_tokens.append(token2);
105 }
106
Tokens(Token token1,Token token2,Token token3)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
Tokens(Token token1,Token token2,Token token3,Token token4)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
Tokens(Token token1,Token token2,Token token3,Token token4,Token token5)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
Tokens(Token token1,Token token2,Token token3,Token token4,Token token5,Token token6)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
operator ==(const Tokens & other) const141 bool operator==(const Tokens& other) const
142 {
143 return m_tokens == other.m_tokens;
144 }
145
toString() const146 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
163 protected:
parse(const String & formatString)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
single(const char ch)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
183 private:
184 class TokenHandler : public DateTimeFormat::TokenHandler {
185 public:
~TokenHandler()186 virtual ~TokenHandler() { }
187
fieldType(int index) const188 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
tokens() const193 Tokens tokens() const { return Tokens(m_tokens); }
194
195 private:
visitField(FieldType fieldType,int count)196 virtual void visitField(FieldType fieldType, int count) OVERRIDE
197 {
198 m_tokens.append(Token(fieldType, count));
199 }
200
visitLiteral(const String & string)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
operator <<(std::ostream & os,const DateTimeFormatTest::Tokens & tokens)210 std::ostream& operator<<(std::ostream& os, const DateTimeFormatTest::Tokens& tokens)
211 {
212 return os << tokens.toString().ascii().data();
213 }
214
TEST_F(DateTimeFormatTest,CommonPattern)215 TEST_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
TEST_F(DateTimeFormatTest,MissingClosingQuote)248 TEST_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
TEST_F(DateTimeFormatTest,Quote)255 TEST_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
TEST_F(DateTimeFormatTest,SingleLowerCaseCharacter)269 TEST_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
TEST_F(DateTimeFormatTest,SingleLowerCaseInvalid)288 TEST_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
TEST_F(DateTimeFormatTest,SingleUpperCaseCharacter)303 TEST_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
TEST_F(DateTimeFormatTest,SingleUpperCaseInvalid)321 TEST_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