blob: df419418d63b5d2c9b277546a197dc16724d259f [file] [log] [blame]
/*
* 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:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "platform/text/DateTimeFormat.h"
#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
#include "wtf/text/CString.h"
#include "wtf/text/StringBuilder.h"
#include <gtest/gtest.h>
using namespace blink;
class DateTimeFormatTest : public ::testing::Test {
public:
typedef DateTimeFormat::FieldType FieldType;
struct Token {
String string;
int count;
FieldType fieldType;
Token(FieldType fieldType, int count = 1)
: count(count)
, fieldType(fieldType)
{
ASSERT(fieldType != DateTimeFormat::FieldTypeLiteral);
}
Token(const String& string)
: string(string)
, count(0)
, fieldType(DateTimeFormat::FieldTypeLiteral)
{
}
bool operator==(const Token& other) const
{
return fieldType == other.fieldType && count == other.count && string == other.string;
}
String toString() const
{
switch (fieldType) {
case DateTimeFormat::FieldTypeInvalid:
return "*invalid*";
case DateTimeFormat::FieldTypeLiteral: {
StringBuilder builder;
builder.append('"');
builder.append(string);
builder.append('"');
return builder.toString();
}
default:
return String::format("Token(%d, %d)", fieldType, count);
}
}
};
class Tokens {
public:
Tokens() { }
explicit Tokens(const Vector<Token> tokens)
: m_tokens(tokens)
{
}
explicit Tokens(const String& string)
{
m_tokens.append(Token(string));
}
explicit Tokens(Token token1)
{
m_tokens.append(token1);
}
Tokens(Token token1, Token token2)
{
m_tokens.append(token1);
m_tokens.append(token2);
}
Tokens(Token token1, Token token2, Token token3)
{
m_tokens.append(token1);
m_tokens.append(token2);
m_tokens.append(token3);
}
Tokens(Token token1, Token token2, Token token3, Token token4)
{
m_tokens.append(token1);
m_tokens.append(token2);
m_tokens.append(token3);
m_tokens.append(token4);
}
Tokens(Token token1, Token token2, Token token3, Token token4, Token token5)
{
m_tokens.append(token1);
m_tokens.append(token2);
m_tokens.append(token3);
m_tokens.append(token4);
m_tokens.append(token5);
}
Tokens(Token token1, Token token2, Token token3, Token token4, Token token5, Token token6)
{
m_tokens.append(token1);
m_tokens.append(token2);
m_tokens.append(token3);
m_tokens.append(token4);
m_tokens.append(token5);
m_tokens.append(token6);
}
bool operator==(const Tokens& other) const
{
return m_tokens == other.m_tokens;
}
String toString() const
{
StringBuilder builder;
builder.append("Tokens(");
for (unsigned index = 0; index < m_tokens.size(); ++index) {
if (index)
builder.append(",");
builder.append(m_tokens[index].toString());
}
builder.append(")");
return builder.toString();
}
private:
Vector<Token> m_tokens;
};
protected:
Tokens parse(const String& formatString)
{
TokenHandler handler;
if (!DateTimeFormat::parse(formatString, handler))
return Tokens(Token("*failed*"));
return handler.tokens();
}
FieldType single(const char ch)
{
char formatString[2];
formatString[0] = ch;
formatString[1] = 0;
TokenHandler handler;
if (!DateTimeFormat::parse(formatString, handler))
return DateTimeFormat::FieldTypeInvalid;
return handler.fieldType(0);
}
private:
class TokenHandler : public DateTimeFormat::TokenHandler {
public:
virtual ~TokenHandler() { }
FieldType fieldType(int index) const
{
return index >=0 && index < static_cast<int>(m_tokens.size()) ? m_tokens[index].fieldType : DateTimeFormat::FieldTypeInvalid;
}
Tokens tokens() const { return Tokens(m_tokens); }
private:
virtual void visitField(FieldType fieldType, int count) OVERRIDE
{
m_tokens.append(Token(fieldType, count));
}
virtual void visitLiteral(const String& string) OVERRIDE
{
m_tokens.append(Token(string));
}
Vector<Token> m_tokens;
};
};
std::ostream& operator<<(std::ostream& os, const DateTimeFormatTest::Tokens& tokens)
{
return os << tokens.toString().ascii().data();
}
TEST_F(DateTimeFormatTest, CommonPattern)
{
EXPECT_EQ(Tokens(), parse(""));
EXPECT_EQ(
Tokens(
Token(DateTimeFormat::FieldTypeYear, 4), Token("-"),
Token(DateTimeFormat::FieldTypeMonth, 2), Token("-"),
Token(DateTimeFormat::FieldTypeDayOfMonth, 2)),
parse("yyyy-MM-dd"));
EXPECT_EQ(
Tokens(
Token(DateTimeFormat::FieldTypeHour24, 2), Token(":"),
Token(DateTimeFormat::FieldTypeMinute, 2), Token(":"),
Token(DateTimeFormat::FieldTypeSecond, 2)),
parse("kk:mm:ss"));
EXPECT_EQ(
Tokens(
Token(DateTimeFormat::FieldTypeHour12), Token(":"),
Token(DateTimeFormat::FieldTypeMinute), Token(" "),
Token(DateTimeFormat::FieldTypePeriod)),
parse("h:m a"));
EXPECT_EQ(
Tokens(
Token(DateTimeFormat::FieldTypeYear), Token("Nen "),
Token(DateTimeFormat::FieldTypeMonth), Token("Getsu "),
Token(DateTimeFormat::FieldTypeDayOfMonth), Token("Nichi")),
parse("y'Nen' M'Getsu' d'Nichi'"));
}
TEST_F(DateTimeFormatTest, MissingClosingQuote)
{
EXPECT_EQ(Tokens("*failed*"), parse("'foo"));
EXPECT_EQ(Tokens("*failed*"), parse("fo'o"));
EXPECT_EQ(Tokens("*failed*"), parse("foo'"));
}
TEST_F(DateTimeFormatTest, Quote)
{
EXPECT_EQ(Tokens("FooBar"), parse("'FooBar'"));
EXPECT_EQ(Tokens("'"), parse("''"));
EXPECT_EQ(Tokens("'-'"), parse("''-''"));
EXPECT_EQ(Tokens("Foo'Bar"), parse("'Foo''Bar'"));
EXPECT_EQ(
Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'s")),
parse("G'''s'"));
EXPECT_EQ(
Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'"), Token(DateTimeFormat::FieldTypeSecond)),
parse("G''s"));
}
TEST_F(DateTimeFormatTest, SingleLowerCaseCharacter)
{
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('b'));
EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, single('c'));
EXPECT_EQ(DateTimeFormat::FieldTypeDayOfMonth, single('d'));
EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeek, single('e'));
EXPECT_EQ(DateTimeFormat::FieldTypeModifiedJulianDay, single('g'));
EXPECT_EQ(DateTimeFormat::FieldTypeHour12, single('h'));
EXPECT_EQ(DateTimeFormat::FieldTypeHour24, single('k'));
EXPECT_EQ(DateTimeFormat::FieldTypeMinute, single('m'));
EXPECT_EQ(DateTimeFormat::FieldTypeQuaterStandAlone, single('q'));
EXPECT_EQ(DateTimeFormat::FieldTypeSecond, single('s'));
EXPECT_EQ(DateTimeFormat::FieldTypeExtendedYear, single('u'));
EXPECT_EQ(DateTimeFormat::FieldTypeNonLocationZone, single('v'));
EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfMonth, single('W'));
EXPECT_EQ(DateTimeFormat::FieldTypeYear, single('y'));
EXPECT_EQ(DateTimeFormat::FieldTypeZone, single('z'));
}
TEST_F(DateTimeFormatTest, SingleLowerCaseInvalid)
{
EXPECT_EQ(DateTimeFormat::FieldTypePeriod, single('a'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('f'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('i'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('j'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('l'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('n'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('o'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('p'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('r'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('t'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('x'));
}
TEST_F(DateTimeFormatTest, SingleUpperCaseCharacter)
{
EXPECT_EQ(DateTimeFormat::FieldTypeMillisecondsInDay, single('A'));
EXPECT_EQ(DateTimeFormat::FieldTypeDayOfYear, single('D'));
EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeek, single('E'));
EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeekInMonth, single('F'));
EXPECT_EQ(DateTimeFormat::FieldTypeEra, single('G'));
EXPECT_EQ(DateTimeFormat::FieldTypeHour23, single('H'));
EXPECT_EQ(DateTimeFormat::FieldTypeHour11, single('K'));
EXPECT_EQ(DateTimeFormat::FieldTypeMonthStandAlone, single('L'));
EXPECT_EQ(DateTimeFormat::FieldTypeMonth, single('M'));
EXPECT_EQ(DateTimeFormat::FieldTypeQuater, single('Q'));
EXPECT_EQ(DateTimeFormat::FieldTypeFractionalSecond, single('S'));
EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfYear, single('w'));
EXPECT_EQ(DateTimeFormat::FieldTypeYearOfWeekOfYear, single('Y'));
EXPECT_EQ(DateTimeFormat::FieldTypeRFC822Zone, single('Z'));
}
TEST_F(DateTimeFormatTest, SingleUpperCaseInvalid)
{
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('B'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('C'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('I'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('J'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('N'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('O'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('P'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('R'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('T'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('U'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('V'));
EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('X'));
}
#endif