blob: 2ca146e7eca246738392ae9ce7d14feeabab9097 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace {
TEST(CSSParserTokenStreamTest, EmptyStream) {
CSSTokenizer tokenizer("");
CSSParserTokenStream stream(tokenizer);
EXPECT_TRUE(stream.Consume().IsEOF());
EXPECT_TRUE(stream.Peek().IsEOF());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, PeekThenConsume) {
CSSTokenizer tokenizer("A"); // kIdent
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.Peek().GetType());
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, ConsumeThenPeek) {
CSSTokenizer tokenizer("A"); // kIdent
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, ConsumeMultipleTokens) {
CSSTokenizer tokenizer("A 1"); // kIdent kWhitespace kNumber
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
EXPECT_EQ(kNumberToken, stream.Consume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterPeek) {
CSSTokenizer tokenizer("A"); // kIdent
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.Peek().GetType());
EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType());
EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterAtEnd) {
CSSTokenizer tokenizer("A"); // kIdent
CSSParserTokenStream stream(tokenizer);
EXPECT_FALSE(stream.AtEnd());
EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType());
EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, UncheckedConsumeComponentValue) {
CSSTokenizer tokenizer("A{1}{2{3}}B");
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.Peek().GetType());
stream.UncheckedConsumeComponentValue();
EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
stream.UncheckedConsumeComponentValue();
EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType());
stream.UncheckedConsumeComponentValue();
EXPECT_EQ(kIdentToken, stream.Peek().GetType());
stream.UncheckedConsumeComponentValue();
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, ConsumeWhitespace) {
CSSTokenizer tokenizer(" \t\n"); // kWhitespace
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, ConsumeIncludingWhitespace) {
CSSTokenizer tokenizer("A \t\n"); // kIdent kWhitespace
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(kIdentToken, stream.ConsumeIncludingWhitespace().GetType());
EXPECT_TRUE(stream.AtEnd());
}
TEST(CSSParserTokenStreamTest, RangesDoNotGetInvalidatedWhenConsuming) {
StringBuilder s;
s.Append("1 ");
for (int i = 0; i < 100; i++)
s.Append("A ");
CSSTokenizer tokenizer(s.ToString());
CSSParserTokenStream stream(tokenizer);
// Consume a single token range.
auto range = stream.ConsumeUntilPeekedTypeIs<kIdentToken>();
EXPECT_EQ(kNumberToken, range.Peek().GetType());
// Consume remaining tokens to try to invalidate the range.
while (!stream.AtEnd())
stream.ConsumeIncludingWhitespace();
EXPECT_EQ(kNumberToken, range.ConsumeIncludingWhitespace().GetType());
EXPECT_TRUE(range.AtEnd());
}
TEST(CSSParserTokenStreamTest, BlockErrorRecoveryConsumesRestOfBlock) {
CSSTokenizer tokenizer("{B }1");
CSSParserTokenStream stream(tokenizer);
{
CSSParserTokenStream::BlockGuard guard(stream);
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_FALSE(stream.AtEnd());
} // calls destructor
EXPECT_EQ(kNumberToken, stream.Consume().GetType());
}
TEST(CSSParserTokenStreamTest, BlockErrorRecoveryOnSuccess) {
CSSTokenizer tokenizer("{B }1");
CSSParserTokenStream stream(tokenizer);
{
CSSParserTokenStream::BlockGuard guard(stream);
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
EXPECT_TRUE(stream.AtEnd());
} // calls destructor
EXPECT_EQ(kNumberToken, stream.Consume().GetType());
}
TEST(CSSParserTokenStreamTest, BlockErrorRecoveryConsumeComponentValue) {
CSSTokenizer tokenizer("{{B} C}1");
CSSParserTokenStream stream(tokenizer);
{
CSSParserTokenStream::BlockGuard guard(stream);
stream.EnsureLookAhead();
stream.UncheckedConsumeComponentValue();
} // calls destructor
EXPECT_EQ(kNumberToken, stream.Consume().GetType());
}
TEST(CSSParserTokenStreamTest, OffsetAfterPeek) {
CSSTokenizer tokenizer("ABC");
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(0U, stream.Offset());
EXPECT_EQ(kIdentToken, stream.Peek().GetType());
EXPECT_EQ(0U, stream.Offset());
}
TEST(CSSParserTokenStreamTest, OffsetAfterConsumes) {
CSSTokenizer tokenizer("ABC 1 {23 }");
CSSParserTokenStream stream(tokenizer);
EXPECT_EQ(0U, stream.Offset());
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
EXPECT_EQ(3U, stream.Offset());
EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType());
EXPECT_EQ(4U, stream.Offset());
EXPECT_EQ(kNumberToken, stream.ConsumeIncludingWhitespace().GetType());
EXPECT_EQ(6U, stream.Offset());
stream.EnsureLookAhead();
stream.UncheckedConsumeComponentValue();
EXPECT_EQ(11U, stream.Offset());
}
TEST(CSSParserTokenStreamTest, LookAheadOffset) {
CSSTokenizer tokenizer("ABC/* *//* */1");
CSSParserTokenStream stream(tokenizer);
stream.EnsureLookAhead();
EXPECT_EQ(0U, stream.Offset());
EXPECT_EQ(0U, stream.LookAheadOffset());
EXPECT_EQ(kIdentToken, stream.Consume().GetType());
stream.EnsureLookAhead();
EXPECT_EQ(3U, stream.Offset());
EXPECT_EQ(13U, stream.LookAheadOffset());
}
TEST(CSSParserTokenStreamTest, ConsumeUntilPeekedTypeIsEmpty) {
CSSTokenizer tokenizer("{23 }");
CSSParserTokenStream stream(tokenizer);
auto range = stream.ConsumeUntilPeekedTypeIs<>();
EXPECT_TRUE(stream.AtEnd());
EXPECT_EQ(kLeftBraceToken, range.Consume().GetType());
EXPECT_EQ(kNumberToken, range.Consume().GetType());
EXPECT_EQ(kWhitespaceToken, range.Consume().GetType());
EXPECT_EQ(kRightBraceToken, range.Consume().GetType());
EXPECT_TRUE(range.AtEnd());
}
} // namespace
} // namespace blink