// Copyright 2020 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "core/fxcrt/css/cfx_csssyntaxparser.h" #include "testing/gtest/include/gtest/gtest.h" // These tests cover the "declaration only" mode of the CSS Syntax Parser // (i.e. inline style="" attribute). The cfx_cssstylesheet_unitttest.cpp // file covers the full-up selector { ... } parsing. TEST(CSSSyntaxParserTest, ParseEmpty) { const wchar_t* input = L""; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseBlank) { const wchar_t* input = L" \n\r\t"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMissingColon) { const wchar_t* input = L"foo "; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMissingValue) { const wchar_t* input = L"foo: "; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseSingleProp1) { const wchar_t* input = L"foo:bar"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseSingleProp2) { const wchar_t* input = L"foo:bar;"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMissingColonMultiple) { const wchar_t* input = L"foo:bar; baz"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMissingPropertyMultiple) { const wchar_t* input = L"foo:bar; baz: "; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"baz", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMultipleProp1) { const wchar_t* input = L"foo : bar; baz : bam"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"baz", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bam", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseMultipleProp2) { const wchar_t* input = L"foo:bar;baz:bam;"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"baz", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bam", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kEOS, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseOpenBrace1) { const wchar_t* input = L"{a:3}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); // TODO(tsepez): these should fail on stray punctuation. EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"{a", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"3", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseOpenBrace2) { const wchar_t* input = L"foo {a:3}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); // TODO(tsepez): these should fail on stray punctuation. EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo {a", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"3", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseOpenBrace3) { const wchar_t* input = L"foo: bar {a:3}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); // TODO(tsepez): these should fail on stray punctuation. EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar {a:3", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseOpenBrace4) { const wchar_t* input = L"foo: bar; {a:3}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); // TODO(tsepez): these should fail on stray punctuation. EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"{a", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"3", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseCloseBrace1) { const wchar_t* input = L"} foo:bar"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseCloseBrace2) { const wchar_t* input = L"foo}:bar"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseCloseBrace3) { const wchar_t* input = L"foo:bar}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); } TEST(CSSSyntaxParserTest, ParseCloseBrace4) { const wchar_t* input = L"foo:bar;}"; CFX_CSSSyntaxParser parser(input); parser.SetParseOnlyDeclarations(); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyName, parser.DoSyntaxParse()); EXPECT_EQ(L"foo", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kPropertyValue, parser.DoSyntaxParse()); EXPECT_EQ(L"bar", parser.GetCurrentString()); EXPECT_EQ(CFX_CSSSyntaxParser::Status::kError, parser.DoSyntaxParse()); }