summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc390
1 files changed, 390 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
new file mode 100644
index 00000000000..04f7b706b78
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_supports_parser_test.cc
@@ -0,0 +1,390 @@
+// Copyright 2020 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_supports_parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_impl.h"
+#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+
+using Result = CSSSupportsParser::Result;
+
+class CSSSupportsParserTest : public testing::Test {
+ public:
+ CSSParserContext* MakeContext() {
+ return MakeGarbageCollected<CSSParserContext>(
+ kHTMLStandardMode, SecureContextMode::kInsecureContext);
+ }
+
+ Vector<CSSParserToken, 32> Tokenize(const String& string) {
+ return CSSTokenizer(string).TokenizeToEOF();
+ }
+
+ Result SupportsCondition(String string, CSSSupportsParser::Mode mode) {
+ CSSParserImpl impl(MakeContext());
+ auto tokens = Tokenize(string);
+ return CSSSupportsParser::SupportsCondition(tokens, impl, mode);
+ }
+
+ Result AtSupports(String string) {
+ return SupportsCondition(string, CSSSupportsParser::Mode::kForAtRule);
+ }
+
+ Result WindowCSSSupports(String string) {
+ return SupportsCondition(string, CSSSupportsParser::Mode::kForWindowCSS);
+ }
+
+ Result ConsumeSupportsCondition(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeSupportsCondition(range);
+ }
+
+ Result ConsumeSupportsInParens(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeSupportsInParens(range);
+ }
+
+ Result ConsumeSupportsFeature(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeSupportsFeature(range);
+ }
+
+ Result ConsumeSupportsSelectorFn(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeSupportsSelectorFn(range);
+ }
+
+ Result ConsumeSupportsDecl(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeSupportsDecl(range);
+ }
+
+ Result ConsumeGeneralEnclosed(String string) {
+ CSSParserImpl impl(MakeContext());
+ CSSSupportsParser parser(impl);
+ auto tokens = Tokenize(string);
+ CSSParserTokenRange range = tokens;
+ return parser.ConsumeGeneralEnclosed(range);
+ }
+};
+
+TEST_F(CSSSupportsParserTest, ResultNot) {
+ EXPECT_EQ(Result::kSupported, !Result::kUnsupported);
+ EXPECT_EQ(Result::kUnsupported, !Result::kSupported);
+ EXPECT_EQ(Result::kParseFailure, !Result::kParseFailure);
+ EXPECT_EQ(Result::kUnknown, !Result::kUnknown);
+}
+
+TEST_F(CSSSupportsParserTest, ResultAnd) {
+ EXPECT_EQ(Result::kSupported, Result::kSupported & Result::kSupported);
+ EXPECT_EQ(Result::kUnsupported, Result::kUnsupported & Result::kSupported);
+ EXPECT_EQ(Result::kUnsupported, Result::kSupported & Result::kUnsupported);
+ EXPECT_EQ(Result::kUnsupported, Result::kUnsupported & Result::kUnsupported);
+
+ EXPECT_EQ(Result::kParseFailure, Result::kSupported & Result::kParseFailure);
+ EXPECT_EQ(Result::kParseFailure, Result::kParseFailure & Result::kSupported);
+
+ EXPECT_EQ(Result::kUnknown, Result::kUnknown & Result::kUnknown);
+ EXPECT_EQ(Result::kUnsupported, Result::kSupported & Result::kUnknown);
+ EXPECT_EQ(Result::kUnsupported, Result::kUnknown & Result::kSupported);
+}
+
+TEST_F(CSSSupportsParserTest, ResultOr) {
+ EXPECT_EQ(Result::kSupported, Result::kSupported | Result::kSupported);
+ EXPECT_EQ(Result::kSupported, Result::kUnsupported | Result::kSupported);
+ EXPECT_EQ(Result::kSupported, Result::kSupported | Result::kUnsupported);
+ EXPECT_EQ(Result::kUnsupported, Result::kUnsupported | Result::kUnsupported);
+
+ EXPECT_EQ(Result::kParseFailure, Result::kSupported | Result::kParseFailure);
+ EXPECT_EQ(Result::kParseFailure, Result::kParseFailure | Result::kSupported);
+
+ EXPECT_EQ(Result::kUnknown, Result::kUnknown | Result::kUnknown);
+ EXPECT_EQ(Result::kSupported, Result::kSupported | Result::kUnknown);
+ EXPECT_EQ(Result::kSupported, Result::kUnknown | Result::kSupported);
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsCondition) {
+ // not <supports-in-parens>
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsCondition("not (asdf:red)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition("(not (color:red))"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsCondition("nay (color:red)"));
+
+ // <supports-in-parens> [ and <supports-in-parens> ]*
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsCondition("(color:red) and (color:green)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition("(color:red) and (asdf:green)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition("(asdf:red) and (asdf:green)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition(
+ "(color:red) and (color:green) and (asdf:color)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsCondition(
+ "(color:red) and (color:green) and (not (asdf:color))"));
+
+ // <supports-in-parens> [ or <supports-in-parens> ]*
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsCondition("(color:red) or (color:asdf)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsCondition("(color:asdf) or (color:green)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition("(asdf:red) or (asdf:green)"));
+ EXPECT_EQ(
+ Result::kSupported,
+ ConsumeSupportsCondition("(color:red) or (color:green) or (asdf:color)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsCondition(
+ "(color:asdf1) or (color:asdf2) or (asdf:asdf2)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsCondition(
+ "(color:asdf) or (color:ghjk) or (not (asdf:color))"));
+
+ // <supports-feature>
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsCondition("(color:red)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsCondition("(color:asdf)"));
+
+ // <general-enclosed>
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsCondition("asdf(1)"));
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsInParens) {
+ // ( <supports-condition> )
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsInParens("(not (asdf:red))"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsInParens("(not (color:red))"));
+
+ // <supports-feature>
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsInParens("(color:red)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsInParens("(color:asdf)"));
+
+ // <general-enclosed>
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsInParens("asdf(1)"));
+
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsInParens("(color:red)and (color:green)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsInParens("(color:red)or (color:green)"));
+ {
+ ScopedCSSSupportsSelectorForTest css_supports_selector(true);
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsInParens("selector(div)or (color:green)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsInParens("selector(div)and (color:green)"));
+ }
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsSelectorFn) {
+ ScopedCSSSupportsSelectorForTest css_supports_selector(true);
+
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(*)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(*:hover)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(:hover)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(::before)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(div)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(div"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(.a)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(#a)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(div.a)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(div a)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(a > div)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(a ~ div)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(a + div)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsSelectorFn("selector(*|a)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(a + div#test)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(a + div#test::before)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(a.cls:hover)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(a.cls::before)"));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsSelectorFn("selector(div::-webkit-clear-button)"));
+
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div::-webkit-asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(a + div::-webkit-asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div.cls::-webkit-asdf)"));
+
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div.~cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div. ~cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div .~ cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div$ cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div $cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(div $ cls)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(unknown|a)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(a::asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(a:asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(a, body)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(*:asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(*::asdf)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsSelectorFn("selector(:asdf)"));
+ EXPECT_EQ(Result::kUnsupported,
+ ConsumeSupportsSelectorFn("selector(::asdf)"));
+
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("#test"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("test"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("test(1)"));
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsSelectorFnWithFeatureDisabled) {
+ ScopedCSSSupportsSelectorForTest css_supports_selector(false);
+
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("selector(*)"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("selector(div)"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsSelectorFn("selector(.a)"));
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsDecl) {
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(color:red)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(color: red)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(color : red)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(color :red)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("( color:red )"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(--x:red)"));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(--x:\tred) "));
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(--x:\tred) \t "));
+ EXPECT_EQ(Result::kSupported,
+ ConsumeSupportsDecl("(color:green !important)"));
+ // For some reason EOF is allowed in place of ')' (everywhere in Blink).
+ // Seems to be the case in Firefox too.
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsDecl("(color:red"));
+
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsDecl("(color:asdf)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsDecl("(asdf)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsDecl("(color)"));
+ EXPECT_EQ(Result::kUnsupported, ConsumeSupportsDecl("(color:)"));
+
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl(""));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl("("));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl(")"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl("()"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl("color:red)"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsDecl("color:red"));
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeSupportsFeature) {
+ EXPECT_EQ(Result::kSupported, ConsumeSupportsFeature("(color:red)"));
+
+ {
+ ScopedCSSSupportsSelectorForTest css_supports_selector(true);
+ EXPECT_EQ(Result::kParseFailure, ConsumeSupportsFeature("asdf(1)"));
+ }
+}
+
+TEST_F(CSSSupportsParserTest, ConsumeGeneralEnclosed) {
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(asdf)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("( asdf )"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(3)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("max(1, 2)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)\t"));
+
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed(""));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("("));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed(")"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("()"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("color:red"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("asdf"));
+
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(asdf)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("( asdf )"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(3)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("max(1, 2)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("asdf(1, 2)\t"));
+
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed(""));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("("));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed(")"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("()"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("color:red"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("asdf"));
+
+ // Invalid <any-value>:
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("(asdf})"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("(asd]f)"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("(\"as\ndf\")"));
+ EXPECT_EQ(Result::kParseFailure, ConsumeGeneralEnclosed("(url(as'df))"));
+
+ // Valid <any-value>
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(as;df)"));
+ EXPECT_EQ(Result::kUnknown, ConsumeGeneralEnclosed("(as ! df)"));
+}
+
+TEST_F(CSSSupportsParserTest, AtSupportsCondition) {
+ EXPECT_EQ(Result::kSupported, AtSupports("(--x:red)"));
+ EXPECT_EQ(Result::kSupported, AtSupports("(--x:red) and (color:green)"));
+ EXPECT_EQ(Result::kSupported, AtSupports("(--x:red) or (color:asdf)"));
+ EXPECT_EQ(Result::kSupported,
+ AtSupports("not ((color:gjhk) or (color:asdf))"));
+ EXPECT_EQ(Result::kSupported,
+ AtSupports("(display: none) and ( (display: none) )"));
+
+ EXPECT_EQ(Result::kUnsupported, AtSupports("(color:ghjk) or (color:asdf)"));
+ EXPECT_EQ(Result::kUnsupported, AtSupports("(color:ghjk) or asdf(1)"));
+ EXPECT_EQ(Result::kParseFailure, AtSupports("color:red"));
+ EXPECT_EQ(
+ Result::kParseFailure,
+ AtSupports("(display: none) and (display: block) or (display: inline)"));
+ EXPECT_EQ(Result::kParseFailure,
+ AtSupports("not (display: deadbeef) and (display: block)"));
+ EXPECT_EQ(Result::kParseFailure,
+ AtSupports("(margin: 0) and (display: inline) or (width:1em)"));
+
+ // "and("/"or(" are function tokens, hence not allowed here.
+ EXPECT_EQ(Result::kParseFailure, AtSupports("(left:0) and(top:0)"));
+ EXPECT_EQ(Result::kParseFailure, AtSupports("(left:0) or(top:0)"));
+}
+
+TEST_F(CSSSupportsParserTest, WindowCSSSupportsCondition) {
+ EXPECT_EQ(Result::kSupported, WindowCSSSupports("(--x:red)"));
+ EXPECT_EQ(Result::kSupported, WindowCSSSupports("( --x:red )"));
+ EXPECT_EQ(Result::kSupported,
+ WindowCSSSupports("(--x:red) and (color:green)"));
+ EXPECT_EQ(Result::kSupported, WindowCSSSupports("(--x:red) or (color:asdf)"));
+ EXPECT_EQ(Result::kSupported,
+ WindowCSSSupports("not ((color:gjhk) or (color:asdf))"));
+
+ EXPECT_EQ(Result::kUnsupported,
+ WindowCSSSupports("(color:ghjk) or (color:asdf)"));
+ EXPECT_EQ(Result::kUnsupported, WindowCSSSupports("(color:ghjk) or asdf(1)"));
+ EXPECT_EQ(Result::kSupported, WindowCSSSupports("color:red"));
+}
+
+} // namespace blink