blob: 78377a841f9b60f623f0bf01271bee8bd2013097 [file] [log] [blame] [edit]
// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/css_parser/scanner.h"
#include <locale.h>
#include "cobalt/css_parser/grammar.h"
#include "cobalt/css_parser/string_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace css_parser {
// When we support any of the at rule which already has a DISABLED test listed
// below, this DISABLED test should be enabled.
const char* kNumericLocales[] = {
"", // default locale
"C", // dot radix separator
"de_DE", // comma radix separator
};
class ScannerTest : public ::testing::Test,
public ::testing::WithParamInterface<const char*> {
public:
virtual void SetUp() {
// Don't mess with the locale for non-parameterized tests.
if (!testing::UnitTest::GetInstance()->current_test_info()->value_param()) {
old_locale_.clear();
return;
}
// Save the old locale.
char* old_locale_cstr = setlocale(LC_NUMERIC, nullptr);
EXPECT_TRUE(old_locale_cstr != nullptr) << "Cant' save original locale";
old_locale_ = old_locale_cstr;
// Keep the default locale when the param is empty, and for other param
// values we'll skip the test if we can't change the locale to it.
locale_okay_ =
(GetParam()[0] == 0 || setlocale(LC_NUMERIC, GetParam()) != nullptr);
}
virtual void TearDown() {
if (!old_locale_.empty()) setlocale(LC_NUMERIC, old_locale_.c_str());
}
// TODO: Use GTEST_SKIP in |SetUp| when we have a newer version of gtest.
bool SkipLocale() {
if (!locale_okay_) {
std::cout << "[ SKIPPED ] Can't set locale to " << GetParam()
<< std::endl;
}
return !locale_okay_;
}
protected:
std::string old_locale_;
bool locale_okay_;
StringPool string_pool_;
TokenValue token_value_;
YYLTYPE token_location_;
};
INSTANTIATE_TEST_CASE_P(LocaleNumeric, ScannerTest,
::testing::ValuesIn(kNumericLocales));
namespace {
// Array of property tokens corresponding to each cssom::PropertyKey.
const int property_tokens[] = {
kAlignContentToken,
kAlignItemsToken,
kAlignSelfToken,
kAnimationDelayToken,
kAnimationDirectionToken,
kAnimationDurationToken,
kAnimationFillModeToken,
kAnimationIterationCountToken,
kAnimationNameToken,
kAnimationTimingFunctionToken,
kBackgroundColorToken,
kBackgroundImageToken,
kBackgroundPositionToken,
kBackgroundRepeatToken,
kBackgroundSizeToken,
kBorderBottomColorToken,
kBorderBottomLeftRadiusToken,
kBorderBottomRightRadiusToken,
kBorderBottomStyleToken,
kBorderBottomWidthToken,
kBorderLeftColorToken,
kBorderLeftStyleToken,
kBorderLeftWidthToken,
kBorderRightColorToken,
kBorderRightStyleToken,
kBorderRightWidthToken,
kBorderTopColorToken,
kBorderTopLeftRadiusToken,
kBorderTopRightRadiusToken,
kBorderTopStyleToken,
kBorderTopWidthToken,
kBottomToken,
kBoxShadowToken,
kColorToken,
kContentToken,
kDisplayToken,
kFilterToken,
kFlexBasisToken,
kFlexDirectionToken,
kFlexGrowToken,
kFlexShrinkToken,
kFlexWrapToken,
kFontFamilyToken,
kFontSizeToken,
kFontStyleToken,
kFontWeightToken,
kHeightToken,
kIntersectionObserverRootMarginToken,
kJustifyContentToken,
kLeftToken,
kLineHeightToken,
kMarginBottomToken,
kMarginLeftToken,
kMarginRightToken,
kMarginTopToken,
kMaxHeightToken,
kMaxWidthToken,
kMinHeightToken,
kMinWidthToken,
kOpacityToken,
kOrderToken,
kOutlineColorToken,
kOutlineStyleToken,
kOutlineWidthToken,
kOverflowToken,
kOverflowWrapToken,
kPaddingBottomToken,
kPaddingLeftToken,
kPaddingRightToken,
kPaddingTopToken,
kPointerEventsToken,
kPositionToken,
kRightToken,
kTextAlignToken,
kTextDecorationColorToken,
kTextDecorationLineToken,
kTextIndentToken,
kTextOverflowToken,
kTextShadowToken,
kTextTransformToken,
kTopToken,
kTransformOriginToken,
kTransformToken,
kTransitionDelayToken,
kTransitionDurationToken,
kTransitionPropertyToken,
kTransitionTimingFunctionToken,
kVerticalAlignToken,
kVisibilityToken,
kWhiteSpacePropertyToken,
kWidthToken,
kZIndexToken,
kAllToken,
kSrcToken,
kUnicodeRangePropertyToken,
kWordWrapToken,
kAnimationToken,
kBackgroundToken,
kBorderBottomToken,
kBorderColorToken,
kBorderLeftToken,
kBorderToken,
kBorderRadiusToken,
kBorderRightToken,
kBorderStyleToken,
kBorderTopToken,
kBorderWidthToken,
kFlexToken,
kFlexFlowToken,
kFontToken,
kMarginToken,
kOutlineToken,
kPaddingToken,
kTextDecorationToken,
kTransitionToken,
};
} // namespace
TEST_F(ScannerTest, ScansPropertyName) {
static_assert(
SB_ARRAY_SIZE(property_tokens) == 1 + cssom::kMaxEveryPropertyKey,
"property_tokens[] should have a value for each cssom::PropertyKey");
// Test that all property names are scanned into tokens correctly.
ASSERT_EQ(SB_ARRAY_SIZE(property_tokens), 1 + cssom::kMaxEveryPropertyKey);
for (int i = 0; i < 1 + cssom::kMaxEveryPropertyKey; i++) {
cssom::PropertyKey property_key = static_cast<cssom::PropertyKey>(i);
Scanner scanner(cssom::GetPropertyName(property_key), &string_pool_);
ASSERT_EQ(property_tokens[i],
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken,
yylex(&token_value_, &token_location_, &scanner));
}
}
namespace {
// Array of keyword tokens corresponding to each cssom::KeywordValue.
const int keyword_tokens[] = {
kAbsoluteToken,
kAlternateToken,
kAlternateReverseToken,
kAutoToken,
kBackwardsToken,
kBaselineToken,
kBlockToken,
kBothToken,
kBottomToken,
kBreakWordToken,
kCenterToken,
kClipToken,
kCollapseToken,
kColumnToken,
kColumnReverseToken,
kContainToken,
kContentToken,
kCoverToken,
kIdentifierToken, // kCurrentColor
kCursiveToken,
kEllipsisToken,
kEndToken,
kEquirectangularToken,
kFantasyToken,
kFixedToken,
kFlexToken,
kFlexEndToken,
kFlexStartToken,
kForwardsToken,
kHiddenToken,
kInfiniteToken,
kInheritToken,
kInitialToken,
kInlineToken,
kInlineBlockToken,
kInlineFlexToken,
kLeftToken,
kLineThroughToken,
kMiddleToken,
kMonoscopicToken,
kMonospaceToken,
kNoneToken,
kNoRepeatToken,
kNormalToken,
kNowrapToken,
kPreToken,
kPreLineToken,
kPreWrapToken,
kRelativeToken,
kRepeatToken,
kReverseToken,
kRightToken,
kRowToken,
kRowReverseToken,
kSansSerifToken,
kScrollToken,
kSerifToken,
kSolidToken,
kSpaceAroundToken,
kSpaceBetweenToken,
kStartToken,
kStaticToken,
kStereoscopicLeftRightToken,
kStereoscopicTopBottomToken,
kStretchToken,
kTopToken,
kUppercaseToken,
kVisibleToken,
kWrapToken,
kWrapReverseToken,
};
} // namespace
TEST_F(ScannerTest, ScansKeywordValue) {
static_assert(SB_ARRAY_SIZE(keyword_tokens) ==
1 + cssom::KeywordValue::kMaxKeywordValue,
"keyword_tokens[] should have a value for each "
"cssom::KeywordValue::Value");
// Test that all keyword values are scanned into tokens correctly.
ASSERT_EQ(SB_ARRAY_SIZE(keyword_tokens),
1 + cssom::KeywordValue::kMaxKeywordValue);
for (int i = 0; i < 1 + cssom::KeywordValue::kMaxKeywordValue; i++) {
cssom::KeywordValue::Value keyword_value =
static_cast<cssom::KeywordValue::Value>(i);
std::string keyword_name = cssom::KeywordValue::GetName(keyword_value);
Scanner scanner(keyword_name.c_str(), &string_pool_);
ASSERT_EQ(keyword_tokens[i],
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken,
yylex(&token_value_, &token_location_, &scanner));
}
}
TEST_F(ScannerTest, ScansSingleCodePointUnicodeRange) {
Scanner scanner("u+1f4a9 U+1F4A9", &string_pool_);
ASSERT_EQ(kUnicodeRangeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(0x1f4a9, token_value_.integer_pair.first);
ASSERT_EQ(0x1f4a9, token_value_.integer_pair.second);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kUnicodeRangeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(0x1f4a9, token_value_.integer_pair.first);
ASSERT_EQ(0x1f4a9, token_value_.integer_pair.second);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansLowerToUpperBoundUnicodeRange) {
Scanner scanner("u+32-ff", &string_pool_);
ASSERT_EQ(kUnicodeRangeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(0x32, token_value_.integer_pair.first);
ASSERT_EQ(0xff, token_value_.integer_pair.second);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansWildcardUnicodeRange) {
Scanner scanner("u+04??", &string_pool_);
ASSERT_EQ(kUnicodeRangeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(0x400, token_value_.integer_pair.first);
ASSERT_EQ(0x4ff, token_value_.integer_pair.second);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdentifierThatStartsWithU) {
// Ensure all words below are not mistakenly recognized as kUnicodeRangeToken.
Scanner scanner("u U umami Ukraine", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("u", token_value_.string);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("U", token_value_.string);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("umami", token_value_.string);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("Ukraine", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansSixDigitUnicodeRange) {
Scanner scanner("u+11111111", &string_pool_);
ASSERT_EQ(kUnicodeRangeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(0x111111, token_value_.integer_pair.first);
ASSERT_EQ(0x111111, token_value_.integer_pair.second);
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(11, token_value_.integer);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUnquotedUri) {
Scanner scanner("url(https://www.youtube.com/tv#/)", &string_pool_);
ASSERT_EQ(kUriToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("https://www.youtube.com/tv#/", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUriWithoutEndBrace) {
Scanner scanner("url(https://www.youtube.com/tv#/", &string_pool_);
ASSERT_EQ(kUriToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("https://www.youtube.com/tv#/", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansQuotedUri) {
Scanner scanner("url('https://www.youtube.com/tv#/')", &string_pool_);
ASSERT_EQ(kUriToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("https://www.youtube.com/tv#/", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidUri) {
Scanner scanner("url(no pasaran)", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("url", token_value_.string);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("no", token_value_.string);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("pasaran", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidFunction) {
Scanner scanner("sample-function()", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("sample-function", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidFunctionWithNumber) {
Scanner scanner("sample-matrix4d()", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("sample-matrix4d", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansFunctionLikeMediaAnd) {
Scanner scanner("@media tv and(monochrome)", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kTVMediaTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kMediaAndToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('(', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNonNegativeIntegerMediaFeatureTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(static_cast<int>(cssom::kMonochromeMediaFeature),
token_value_.integer);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNPlusOne) {
Scanner scanner("nth-child(n+1)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n+1", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNPlusOneWithoutClosingAtTheEnd) {
Scanner scanner("nth-child(n+1", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n+1", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNMinusOne) {
Scanner scanner("nth-child(n-1)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n-1", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdentifierN) {
Scanner scanner("nth-child(n)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNDashIdentifier) {
Scanner scanner("nth-child(n-)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n-", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdentifier) {
Scanner scanner("sample-identifier", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("sample-identifier", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdentifierWithNumber) {
Scanner scanner("matrix3d5s7wss-47", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("matrix3d5s7wss-47", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDot) {
Scanner scanner(".", &string_pool_);
ASSERT_EQ('.', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNthThatStartsWithNumber) {
Scanner scanner("nth-child(4n+2)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("4n+2", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidDimension) {
Scanner scanner("12monkeys", &string_pool_);
ASSERT_EQ(kInvalidDimensionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("12monkeys", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansPercentage) {
if (SkipLocale()) return;
Scanner scanner("2.71828%", &string_pool_);
ASSERT_EQ(kPercentageToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(2.71828f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInteger) {
Scanner scanner("911", &string_pool_);
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(911, token_value_.integer);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansReal) {
if (SkipLocale()) return;
Scanner scanner("2.71828", &string_pool_);
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(2.71828f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansNegativeReal) {
if (SkipLocale()) return;
Scanner scanner("-3.14159", &string_pool_);
ASSERT_EQ('-', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(3.14159f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansVeryBigIntegerAsReal) {
Scanner scanner("2147483647 2147483648", &string_pool_);
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(2147483647, token_value_.integer);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(2147483648, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidNumber) {
// As per IEEE 754 the maximum value of |float| has 39 decimal digits.
// We use 40 decimal digits to cause overflow into positive infinity.
Scanner scanner("1000000000000000000000000000000000000000", &string_pool_);
ASSERT_EQ(kInvalidNumberToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("1000000000000000000000000000000000000000", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansScientificNotationNumberWithNegativeExponent) {
Scanner scanner("1e-14", &string_pool_);
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(0.00000000000001f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansScientificNotationNumberWithPositiveExponent) {
if (SkipLocale()) return;
Scanner scanner("2.5e+6", &string_pool_);
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(2500000, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansScientificNotationNumberWithUnsignedExponent) {
Scanner scanner("3e5", &string_pool_);
ASSERT_EQ(kRealToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(300000, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansScientificNotationNumberWithScientificExponent) {
// This should be parsed as the number "30000" and invalid dimension "e5",
// not 3*10^400000 nor 30000*10^5.
Scanner scanner("3e4e5", &string_pool_);
ASSERT_EQ(kInvalidDimensionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("3e4e5", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansHexadecimalNumber) {
// We don't support scanning of hexadecimal numbers. This test is just to
// confirm that we recover without crashing.
Scanner scanner("0x0", &string_pool_);
// "x0" is an invalid dimension.
ASSERT_EQ(kInvalidDimensionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("0x0", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUnknownDashFunction) {
Scanner scanner("-cobalt-magic()", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-cobalt-magic", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUnknownDashFunctionWithNumber) {
Scanner scanner("-cobalt-ma5555gic()", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-cobalt-ma5555gic", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUnknownDashFunctionWithoutClosingAtEnd) {
Scanner scanner("-cobalt-magic(", &string_pool_);
ASSERT_EQ(kInvalidFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-cobalt-magic", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
namespace {
// Array of known dash functions and their associated tokens.
struct {
const char* text;
int token;
} known_dash_functions[] = {
{ "-cobalt-mtm", kCobaltMtmFunctionToken },
{ "-cobalt-ui-nav-focus-transform", kCobaltUiNavFocusTransformFunctionToken },
{ "-cobalt-ui-nav-spotlight-transform",
kCobaltUiNavSpotlightTransformFunctionToken },
};
} // namespace
TEST_F(ScannerTest, ScansKnownDashFunction) {
for (size_t i = 0; i < SB_ARRAY_SIZE(known_dash_functions); ++i) {
std::string text(known_dash_functions[i].text);
text += "()";
Scanner scanner(text.c_str(), &string_pool_);
ASSERT_EQ(known_dash_functions[i].token,
yylex(&token_value_, &token_location_, &scanner)) << text;
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner)) << text;
ASSERT_EQ(kEndOfFileToken,
yylex(&token_value_, &token_location_, &scanner)) << text;
}
}
TEST_F(ScannerTest, ScansKnownDashFunctionWithoutClosingAtEnd) {
for (size_t i = 0; i < SB_ARRAY_SIZE(known_dash_functions); ++i) {
std::string text(known_dash_functions[i].text);
text += "(";
Scanner scanner(text.c_str(), &string_pool_);
ASSERT_EQ(known_dash_functions[i].token,
yylex(&token_value_, &token_location_, &scanner)) << text;
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner)) << text;
ASSERT_EQ(kEndOfFileToken,
yylex(&token_value_, &token_location_, &scanner)) << text;
}
}
TEST_F(ScannerTest, ScansMinusNPlusConstant) {
Scanner scanner("nth-child(-n+2)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-n+2", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDashNIdentifier) {
Scanner scanner("nth-child(-n)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-n", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMinusNMinusConstant) {
Scanner scanner("nth-child(-n-2)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-n-2", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDashNDashIdentifier) {
Scanner scanner("nth-child(-n-)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-n-", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansEndSgmlCommentDelimiter) {
Scanner scanner("-->", &string_pool_);
ASSERT_EQ(kSgmlCommentDelimiterToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansConstantTimesNPlusConstant) {
Scanner scanner("nth-child(-4n+2)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("-4n+2", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMinus) {
Scanner scanner("-", &string_pool_);
ASSERT_EQ('-', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansOtherCharacters) {
Scanner scanner("%&=[]", &string_pool_);
ASSERT_EQ('%', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('&', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('=', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('[', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(']', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansEmptyInput) {
Scanner scanner("", &string_pool_);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansWhitespace) {
Scanner scanner("h1\r\n\t img", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("h1", token_value_.string);
ASSERT_EQ(1, token_location_.first_line);
ASSERT_EQ(1, token_location_.first_column);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("img", token_value_.string);
ASSERT_EQ(2, token_location_.first_line);
ASSERT_EQ(3, token_location_.first_column);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansEndMediaQuery) {
Scanner scanner("@media;{", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(';', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('{', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('}', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansSingleQuotedString) {
Scanner scanner("'Quantum Paper rocks'", &string_pool_);
ASSERT_EQ(kStringToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("Quantum Paper rocks", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDoubleQuotedString) {
Scanner scanner("\"Quantum Paper rocks\"", &string_pool_);
ASSERT_EQ(kStringToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("Quantum Paper rocks", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansQuote) {
Scanner scanner("'hello\n", &string_pool_);
ASSERT_EQ('\'', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("hello", token_value_.string);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansQuoteAtEndOfFile) {
Scanner scanner("'hello", &string_pool_);
ASSERT_EQ(kStringToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("hello", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansImportant) {
Scanner scanner("! important", &string_pool_);
ASSERT_EQ(kImportantToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansExclamationMark) {
Scanner scanner("!", &string_pool_);
ASSERT_EQ('!', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansObviousHex) {
Scanner scanner("#1f1f1f", &string_pool_);
ASSERT_EQ(kHexToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("1f1f1f", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdentifierLikeHex) {
// Ensure that hex value is not mistakenly recognized as kIdSelectorToken.
Scanner scanner("#f1f1f1", &string_pool_);
ASSERT_EQ(kHexToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("f1f1f1", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIdSelector) {
Scanner scanner("#webgl-canvas", &string_pool_);
ASSERT_EQ(kIdSelectorToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("webgl-canvas", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansHashmark) {
Scanner scanner("#", &string_pool_);
ASSERT_EQ('#', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansComment) {
Scanner scanner("/* Cobalt\n+ Quantum Paper\n= <3 */", &string_pool_);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(3, token_location_.first_line);
ASSERT_EQ(8, token_location_.first_column);
}
TEST_F(ScannerTest, ScansUnterminatedComment) {
Scanner scanner("/* Everything that has a beginning has an end...",
// ...except for above comment.
&string_pool_);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansSlash) {
Scanner scanner("/", &string_pool_);
ASSERT_EQ('/', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansEndsWith) {
Scanner scanner("$=", &string_pool_);
ASSERT_EQ(kEndsWithToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDollar) {
Scanner scanner("$", &string_pool_);
ASSERT_EQ('$', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansContains) {
Scanner scanner("*=", &string_pool_);
ASSERT_EQ(kContainsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansAsterisk) {
Scanner scanner("*", &string_pool_);
ASSERT_EQ('*', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansPlusNth) {
Scanner scanner("nth-child(+4n+2)", &string_pool_);
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("4n+2", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansPlus) {
Scanner scanner("+4n+2", &string_pool_);
ASSERT_EQ('+', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kInvalidDimensionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("4n", token_value_.string);
ASSERT_EQ('+', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(2, token_value_.integer);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansStartSgmlCommentDelimiter) {
Scanner scanner("<!--", &string_pool_);
ASSERT_EQ(kSgmlCommentDelimiterToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansLess) {
Scanner scanner("<", &string_pool_);
ASSERT_EQ('<', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidAtRuleBlock) {
Scanner scanner("@cobalt-magic { foo[()]; bar[{ }] }", &string_pool_);
ASSERT_EQ(kInvalidAtBlockToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("@cobalt-magic", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidAtRuleBlockWithoutClosingBraceAtEndOfFile) {
Scanner scanner("@cobalt-magic { foo[(", &string_pool_);
ASSERT_EQ(kInvalidAtBlockToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("@cobalt-magic", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansInvalidAtRuleBlockEndsWithSemicolon) {
Scanner scanner("@cobalt-magic;", &string_pool_);
ASSERT_EQ(kInvalidAtBlockToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("@cobalt-magic", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansAt) {
Scanner scanner("@", &string_pool_);
ASSERT_EQ('@', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansAtWithEscapedIdentifier) {
Scanner scanner("@\\e9 motion", &string_pool_);
ASSERT_EQ(kInvalidAtBlockToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("@émotion", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansEscapedIdentifier) {
Scanner scanner("\\e9 motion", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("émotion", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansBackSlash) {
Scanner scanner("\\", &string_pool_);
ASSERT_EQ('\\', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansBeginsWith) {
Scanner scanner("^=", &string_pool_);
ASSERT_EQ(kBeginsWithToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansXor) {
Scanner scanner("^", &string_pool_);
ASSERT_EQ('^', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansDashMatch) {
Scanner scanner("|=", &string_pool_);
ASSERT_EQ(kDashMatchToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansVerticalBar) {
Scanner scanner("|", &string_pool_);
ASSERT_EQ('|', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansIncludes) {
Scanner scanner("~=", &string_pool_);
ASSERT_EQ(kIncludesToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansTilde) {
Scanner scanner("~", &string_pool_);
ASSERT_EQ('~', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansUtf8Identifier) {
// In Russian "огурец" means "cucumber". Why cucumber? It's a long story.
Scanner scanner("огурец", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("огурец", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansSupportsOr) {
Scanner scanner("@supports or", &string_pool_);
ASSERT_EQ(kSupportsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kSupportsOrToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansSupportsAnd) {
Scanner scanner("@supports and", &string_pool_);
ASSERT_EQ(kSupportsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kSupportsAndToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansSupportsNot) {
Scanner scanner("@supports not", &string_pool_);
ASSERT_EQ(kSupportsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kSupportsNotToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNotFunction) {
Scanner scanner("not()", &string_pool_);
ASSERT_EQ(kNotFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansCalcFunction) {
Scanner scanner("calc()", &string_pool_);
ASSERT_EQ(kCalcFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansCueFunction) {
Scanner scanner("cue()", &string_pool_);
ASSERT_EQ(kCueFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansFormatFunction) {
Scanner scanner("format()", &string_pool_);
ASSERT_EQ(kFormatFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansLocalFunction) {
Scanner scanner("local()", &string_pool_);
ASSERT_EQ(kLocalFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansScaleFunction) {
Scanner scanner("scale()", &string_pool_);
ASSERT_EQ(kScaleFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
// Test if we add a closing ')' for the function at end of file.
TEST_F(ScannerTest, ScansScaleFunctionWithoutEndBraceAtEndOfFile) {
Scanner scanner("scale(", &string_pool_);
ASSERT_EQ(kScaleFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMapToMeshFunction) {
Scanner scanner("map-to-mesh()", &string_pool_);
ASSERT_EQ(kMapToMeshFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMatrix3dFunction) {
Scanner scanner("matrix3d()", &string_pool_);
ASSERT_EQ(kMatrix3dFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNthOfTypeFunction) {
Scanner scanner("nth-of-type()", &string_pool_);
ASSERT_EQ(kNthOfTypeFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNthLastChildFunction) {
Scanner scanner("nth-last-child()", &string_pool_);
ASSERT_EQ(kNthLastChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansNthLastOfTypeFunction) {
Scanner scanner("nth-last-of-type()", &string_pool_);
ASSERT_EQ(kNthLastOfTypeFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMediaScreenAnd) {
Scanner scanner("@media screen and", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kScreenMediaTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kMediaAndToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMediaNotDeviceAspectRatio) {
Scanner scanner("@media not (device-aspect-ratio: 2560/1440)", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kMediaNotToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('(', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kRatioMediaFeatureTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(static_cast<int>(cssom::kDeviceAspectRatioMediaFeature),
token_value_.integer);
ASSERT_EQ(':', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(2560, token_value_.integer);
ASSERT_EQ('/', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(1440, token_value_.integer);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMediaOrientationBogus) {
Scanner scanner("@media (orientation: bogus)", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('(', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kOrientationMediaFeatureTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(static_cast<int>(cssom::kOrientationMediaFeature),
token_value_.integer);
ASSERT_EQ(':', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansMediaOnlyTv) {
Scanner scanner("@media only tv", &string_pool_);
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kMediaOnlyToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kTVMediaTypeToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansCentimeters) {
if (SkipLocale()) return;
Scanner scanner("8.24cm", &string_pool_);
ASSERT_EQ(kCentimetersToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansZeroGlyphWidthsAkaCh) {
if (SkipLocale()) return;
Scanner scanner("8.24ch", &string_pool_);
ASSERT_EQ(kZeroGlyphWidthsAkaChToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansDegrees) {
if (SkipLocale()) return;
Scanner scanner("8.24deg", &string_pool_);
ASSERT_EQ(kDegreesToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansDotsPerPixel) {
if (SkipLocale()) return;
Scanner scanner("8.24dppx", &string_pool_);
ASSERT_EQ(kDotsPerPixelToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansDotsPerCentimeter) {
if (SkipLocale()) return;
Scanner scanner("8.24dpcm", &string_pool_);
ASSERT_EQ(kDotsPerCentimeterToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansDotsPerInch) {
if (SkipLocale()) return;
Scanner scanner("8.24dpi", &string_pool_);
ASSERT_EQ(kDotsPerInchToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansFontSizesAkaEm) {
if (SkipLocale()) return;
Scanner scanner("8.24em", &string_pool_);
ASSERT_EQ(kFontSizesAkaEmToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansXHeightsAkaEx) {
if (SkipLocale()) return;
Scanner scanner("8.24ex", &string_pool_);
ASSERT_EQ(kXHeightsAkaExToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansFractions) {
if (SkipLocale()) return;
Scanner scanner("8.24fr", &string_pool_);
ASSERT_EQ(kFractionsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansGradians) {
if (SkipLocale()) return;
Scanner scanner("8.24grad", &string_pool_);
ASSERT_EQ(kGradiansToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansHertz) {
if (SkipLocale()) return;
Scanner scanner("8.24hz", &string_pool_);
ASSERT_EQ(kHertzToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansInches) {
if (SkipLocale()) return;
Scanner scanner("8.24in", &string_pool_);
ASSERT_EQ(kInchesToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansKilohertz) {
if (SkipLocale()) return;
Scanner scanner("8.24khz", &string_pool_);
ASSERT_EQ(kKilohertzToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansMillimeters) {
if (SkipLocale()) return;
Scanner scanner("8.24mm", &string_pool_);
ASSERT_EQ(kMillimetersToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansMilliseconds) {
if (SkipLocale()) return;
Scanner scanner("8.24ms", &string_pool_);
ASSERT_EQ(kMillisecondsToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansPixels) {
if (SkipLocale()) return;
Scanner scanner("8.24px", &string_pool_);
ASSERT_EQ(kPixelsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansPoints) {
if (SkipLocale()) return;
Scanner scanner("8.24pt", &string_pool_);
ASSERT_EQ(kPointsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansPicas) {
if (SkipLocale()) return;
Scanner scanner("8.24pc", &string_pool_);
ASSERT_EQ(kPicasToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansRadians) {
if (SkipLocale()) return;
Scanner scanner("8.24rad", &string_pool_);
ASSERT_EQ(kRadiansToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansRootElementFontSizesAkaRem) {
if (SkipLocale()) return;
Scanner scanner("8.24rem", &string_pool_);
ASSERT_EQ(kRootElementFontSizesAkaRemToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansSeconds) {
if (SkipLocale()) return;
Scanner scanner("8.24s", &string_pool_);
ASSERT_EQ(kSecondsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansTurns) {
if (SkipLocale()) return;
Scanner scanner("8.24turn", &string_pool_);
ASSERT_EQ(kTurnsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansViewportWidthPercentsAkaVw) {
if (SkipLocale()) return;
Scanner scanner("8.24vw", &string_pool_);
ASSERT_EQ(kViewportWidthPercentsAkaVwToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansViewportHeightPercentsAkaVh) {
if (SkipLocale()) return;
Scanner scanner("8.24vh", &string_pool_);
ASSERT_EQ(kViewportHeightPercentsAkaVhToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScansViewportSmallerSizePercentsAkaVmin) {
if (SkipLocale()) return;
Scanner scanner("8.24vmin", &string_pool_);
ASSERT_EQ(kViewportSmallerSizePercentsAkaVminToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_P(ScannerTest, ScanskViewportLargerSizePercentsAkaVmax) {
if (SkipLocale()) return;
Scanner scanner("8.24vmax", &string_pool_);
ASSERT_EQ(kViewportLargerSizePercentsAkaVmaxToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_FLOAT_EQ(8.24f, token_value_.real);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansBottomLeft) {
Scanner scanner("@bottom-left", &string_pool_);
ASSERT_EQ(kBottomLeftToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansBottomRight) {
Scanner scanner("@bottom-right", &string_pool_);
ASSERT_EQ(kBottomRightToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansBottomCenter) {
Scanner scanner("@bottom-center", &string_pool_);
ASSERT_EQ(kBottomCenterToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansBottomLeftCorner) {
Scanner scanner("@bottom-left-corner", &string_pool_);
ASSERT_EQ(kBottomLeftCornerToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansBottomRightCorner) {
Scanner scanner("@bottom-right-corner", &string_pool_);
ASSERT_EQ(kBottomRightCornerToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansCharset) {
Scanner scanner("@charset", &string_pool_);
ASSERT_EQ(kCharsetToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansFontFace) {
Scanner scanner("@font-face", &string_pool_);
ASSERT_EQ(kFontFaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansImport) {
Scanner scanner("@import", &string_pool_);
ASSERT_EQ(kImportToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansLeftTop) {
Scanner scanner("@left-top", &string_pool_);
ASSERT_EQ(kLeftTopToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansLeftMiddle) {
Scanner scanner("@left-middle", &string_pool_);
ASSERT_EQ(kLeftMiddleToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansLeftBottom) {
Scanner scanner("@left-bottom", &string_pool_);
ASSERT_EQ(kLeftBottomToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansNamespace) {
Scanner scanner("@namespace", &string_pool_);
ASSERT_EQ(kNamespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansPage) {
Scanner scanner("@page", &string_pool_);
ASSERT_EQ(kPageToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansRightTop) {
Scanner scanner("@right-top", &string_pool_);
ASSERT_EQ(kRightTopToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansRightMiddle) {
Scanner scanner("@right-middle", &string_pool_);
ASSERT_EQ(kRightMiddleToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansRightBottom) {
Scanner scanner("@right-bottom", &string_pool_);
ASSERT_EQ(kRightBottomToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansTopLeft) {
Scanner scanner("@top-left", &string_pool_);
ASSERT_EQ(kTopLeftToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansTopRight) {
Scanner scanner("@top-right", &string_pool_);
ASSERT_EQ(kTopRightToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansTopCenter) {
Scanner scanner("@top-center", &string_pool_);
ASSERT_EQ(kTopCenterToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansTopLeftCorner) {
Scanner scanner("@top-left-corner", &string_pool_);
ASSERT_EQ(kTopLeftCornerToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_ScansTopRightCorner) {
Scanner scanner("@top-right-corner", &string_pool_);
ASSERT_EQ(kTopRightCornerToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansWebkitAtRule) {
Scanner scanner("@-webkit-region foo {foo[ baz( abc; ) ], bar[baz { efg }] }",
&string_pool_);
ASSERT_EQ(kOtherBrowserAtBlockToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansColon) {
Scanner scanner("::", &string_pool_);
ASSERT_EQ(':', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(':', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, ScansCurlyBrackets) {
Scanner scanner("{}", &string_pool_);
ASSERT_EQ('{', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ('}', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, AdvancesLocation) {
Scanner scanner("body {\n}", &string_pool_);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("body", token_value_.string);
ASSERT_EQ(1, token_location_.first_line);
ASSERT_EQ(1, token_location_.first_column);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(1, token_location_.first_line);
ASSERT_EQ(5, token_location_.first_column);
ASSERT_EQ('{', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(1, token_location_.first_line);
ASSERT_EQ(6, token_location_.first_column);
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(1, token_location_.first_line);
ASSERT_EQ(7, token_location_.first_column);
ASSERT_EQ('}', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(2, token_location_.first_line);
ASSERT_EQ(1, token_location_.first_column);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, EntersAndExitsMediaQueryMode) {
Scanner scanner("@media only; only", &string_pool_);
// Entered "media query" mode, "only" should be a keyword.
ASSERT_EQ(kMediaToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kMediaOnlyToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(';', yylex(&token_value_, &token_location_, &scanner));
// Exited "media query" mode, "only" should be an identifier.
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("only", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, DISABLED_EntersAndExitsSupportsMode) {
Scanner scanner("@supports or; or", &string_pool_);
// Entered "supports" mode, "or" should be a keyword.
ASSERT_EQ(kSupportsToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kSupportsOrToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(';', yylex(&token_value_, &token_location_, &scanner));
// Exited "supports" mode, "or" should be an identifier.
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("or", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
TEST_F(ScannerTest, EntersAndExitsNthChildMode) {
Scanner scanner("nth-child(n+1) n+1", &string_pool_);
// Entered "nth-child" mode, "n+1" should be a single token.
ASSERT_EQ(kNthChildFunctionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kNthToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n+1", token_value_.string);
ASSERT_EQ(')', yylex(&token_value_, &token_location_, &scanner));
// Exited "nth-child" mode, "n+1" should be a sequence of tokens.
ASSERT_EQ(kWhitespaceToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("n", token_value_.string);
ASSERT_EQ('+', yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(kIntegerToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ(1, token_value_.integer);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
}
} // namespace css_parser
} // namespace cobalt