blob: bb80bddbb38f8d059e45ae6e50fb75c30efa5499 [file] [log] [blame]
// Copyright 2014 Google Inc. 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 "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.
class ScannerTest : public ::testing::Test {
protected:
StringPool string_pool_;
TokenValue token_value_;
YYLTYPE token_location_;
};
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_F(ScannerTest, ScansPercentage) {
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_F(ScannerTest, ScansReal) {
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_F(ScannerTest, ScansNegativeReal) {
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, ScansScientificNotationNumber) {
// Scientific notation is required by the standard but is not supported
// by WebKit or Blink. So we don't support it either.
Scanner scanner("1e-14", &string_pool_);
ASSERT_EQ(kInvalidNumberToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("1", token_value_.string);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("e-14", 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_);
#if defined(COBALT_WIN) && _MSC_VER < 1900
// On Windows, with a MSVS version prior to VS2015, the behavior of
// |std::strtod| used to scan a number doesn't conform to the standard, so
// we get a different result on that platform.
ASSERT_EQ(kInvalidDimensionToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("0x0", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
#else
ASSERT_EQ(kInvalidNumberToken,
yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("0", token_value_.string);
ASSERT_EQ(kIdentifierToken, yylex(&token_value_, &token_location_, &scanner));
ASSERT_EQ("x0", token_value_.string);
ASSERT_EQ(kEndOfFileToken, yylex(&token_value_, &token_location_, &scanner));
#endif
}
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));
}
TEST_F(ScannerTest, ScansKnownDashFunction) {
Scanner scanner("-cobalt-mtm()", &string_pool_);
ASSERT_EQ(kCobaltMtmFunctionToken,
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, ScansKnownDashFunctionWithoutClosingAtEnd) {
Scanner scanner("-cobalt-mtm(", &string_pool_);
ASSERT_EQ(kCobaltMtmFunctionToken,
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, 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_F(ScannerTest, ScansCentimeters) {
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_F(ScannerTest, ScansZeroGlyphWidthsAkaCh) {
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_F(ScannerTest, ScansDegrees) {
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_F(ScannerTest, ScansDotsPerPixel) {
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_F(ScannerTest, ScansDotsPerCentimeter) {
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_F(ScannerTest, ScansDotsPerInch) {
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_F(ScannerTest, ScansFontSizesAkaEm) {
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_F(ScannerTest, ScansXHeightsAkaEx) {
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_F(ScannerTest, ScansFractions) {
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_F(ScannerTest, ScansGradians) {
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_F(ScannerTest, ScansHertz) {
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_F(ScannerTest, ScansInches) {
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_F(ScannerTest, ScansKilohertz) {
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_F(ScannerTest, ScansMillimeters) {
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_F(ScannerTest, ScansMilliseconds) {
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_F(ScannerTest, ScansPixels) {
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_F(ScannerTest, ScansPoints) {
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_F(ScannerTest, ScansPicas) {
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_F(ScannerTest, ScansRadians) {
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_F(ScannerTest, ScansRootElementFontSizesAkaRem) {
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_F(ScannerTest, ScansSeconds) {
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_F(ScannerTest, ScansTurns) {
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_F(ScannerTest, ScansViewportWidthPercentsAkaVw) {
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_F(ScannerTest, ScansViewportHeightPercentsAkaVh) {
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_F(ScannerTest, ScansViewportSmallerSizePercentsAkaVmin) {
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_F(ScannerTest, ScanskViewportLargerSizePercentsAkaVmax) {
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