OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/css/parser/CSSSelectorParser.h" | 5 #include "core/css/parser/CSSSelectorParser.h" |
6 | 6 |
7 #include "core/css/CSSSelectorList.h" | 7 #include "core/css/CSSSelectorList.h" |
8 #include "core/css/parser/CSSTokenizer.h" | 8 #include "core/css/parser/CSSTokenizer.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 | 63 |
64 {"29N + 77", 29, 77}, | 64 {"29N + 77", 29, 77}, |
65 {"29n - 77", 29, -77}, | 65 {"29n - 77", 29, -77}, |
66 {"+n + 61", 1, 61}, | 66 {"+n + 61", 1, 61}, |
67 {"+N - 63", 1, -63}, | 67 {"+N - 63", 1, -63}, |
68 {"+n/**/- 48", 1, -48}, | 68 {"+n/**/- 48", 1, -48}, |
69 {"-n + 81", -1, 81}, | 69 {"-n + 81", -1, 81}, |
70 {"-N - 88", -1, -88}, | 70 {"-N - 88", -1, -88}, |
71 }; | 71 }; |
72 | 72 |
73 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(testCases); ++i) { | 73 for (auto testCase : testCases) { |
74 SCOPED_TRACE(testCases[i].input); | 74 SCOPED_TRACE(testCase.input); |
75 | 75 |
76 std::pair<int, int> ab; | 76 std::pair<int, int> ab; |
77 CSSTokenizer::Scope scope(testCases[i].input); | 77 CSSTokenizer::Scope scope(testCase.input); |
78 CSSParserTokenRange range = scope.tokenRange(); | 78 CSSParserTokenRange range = scope.tokenRange(); |
79 bool passed = CSSSelectorParser::consumeANPlusB(range, ab); | 79 bool passed = CSSSelectorParser::consumeANPlusB(range, ab); |
80 EXPECT_TRUE(passed); | 80 EXPECT_TRUE(passed); |
81 EXPECT_EQ(ab.first, testCases[i].a); | 81 EXPECT_EQ(ab.first, testCase.a); |
82 EXPECT_EQ(ab.second, testCases[i].b); | 82 EXPECT_EQ(ab.second, testCase.b); |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 TEST(CSSSelectorParserTest, InvalidANPlusB) | 86 TEST(CSSSelectorParserTest, InvalidANPlusB) |
87 { | 87 { |
88 // Some of these have token range prefixes which are valid <an+b> and could | 88 // Some of these have token range prefixes which are valid <an+b> and could |
89 // in theory be valid in consumeANPlusB, but this behaviour isn't needed | 89 // in theory be valid in consumeANPlusB, but this behaviour isn't needed |
90 // anywhere and not implemented. | 90 // anywhere and not implemented. |
91 const char* testCases[] = { | 91 const char* testCases[] = { |
92 " odd", | 92 " odd", |
93 "+ n", | 93 "+ n", |
94 "3m+4", | 94 "3m+4", |
95 "12n--34", | 95 "12n--34", |
96 "12n- -34", | 96 "12n- -34", |
97 "12n- +34", | 97 "12n- +34", |
98 "23n-+43", | 98 "23n-+43", |
99 "10n 5", | 99 "10n 5", |
100 "10n + +5", | 100 "10n + +5", |
101 "10n + -5", | 101 "10n + -5", |
102 }; | 102 }; |
103 | 103 |
104 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(testCases); ++i) { | 104 for (auto testCase : testCases) { |
105 SCOPED_TRACE(testCases[i]); | 105 SCOPED_TRACE(testCase); |
106 | 106 |
107 std::pair<int, int> ab; | 107 std::pair<int, int> ab; |
108 CSSTokenizer::Scope scope(testCases[i]); | 108 CSSTokenizer::Scope scope(testCase); |
109 CSSParserTokenRange range = scope.tokenRange(); | 109 CSSParserTokenRange range = scope.tokenRange(); |
110 bool passed = CSSSelectorParser::consumeANPlusB(range, ab); | 110 bool passed = CSSSelectorParser::consumeANPlusB(range, ab); |
111 EXPECT_FALSE(passed); | 111 EXPECT_FALSE(passed); |
112 } | 112 } |
113 } | 113 } |
114 | 114 |
115 TEST(CSSSelectorParserTest, ShadowDomPseudoInCompound) | 115 TEST(CSSSelectorParserTest, ShadowDomPseudoInCompound) |
116 { | 116 { |
117 const char* testCases[][2] = { | 117 const char* testCases[][2] = { |
118 { "::shadow", "::shadow" }, | 118 { "::shadow", "::shadow" }, |
119 { ".a::shadow", ".a::shadow" }, | 119 { ".a::shadow", ".a::shadow" }, |
120 { "::content", "::content" }, | 120 { "::content", "::content" }, |
121 { ".a::content", ".a::content" }, | 121 { ".a::content", ".a::content" }, |
122 { "::content.a", "::content.a" }, | |
123 { "::content.a.b", "::content.a.b" }, | |
124 { ".a::content.b", ".a::content.b" }, | |
125 }; | 122 }; |
126 | 123 |
127 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(testCases); ++i) { | 124 for (auto testCase : testCases) { |
128 SCOPED_TRACE(testCases[i][0]); | 125 SCOPED_TRACE(testCase[0]); |
129 CSSTokenizer::Scope scope(testCases[i][0]); | 126 CSSTokenizer::Scope scope(testCase[0]); |
130 CSSParserTokenRange range = scope.tokenRange(); | 127 CSSParserTokenRange range = scope.tokenRange(); |
131 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); | 128 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); |
132 EXPECT_STREQ(testCases[i][1], list.selectorsText().ascii().data()); | 129 EXPECT_STREQ(testCase[1], list.selectorsText().ascii().data()); |
133 } | 130 } |
134 } | 131 } |
135 | 132 |
136 TEST(CSSSelectorParserTest, PseudoElementsInCompoundLists) | 133 TEST(CSSSelectorParserTest, PseudoElementsInCompoundLists) |
137 { | 134 { |
138 const char* testCases[] = { | 135 const char* testCases[] = { |
139 ":not(::before)", | 136 ":not(::before)", |
140 ":not(::content)", | 137 ":not(::content)", |
141 ":not(::shadow)", | 138 ":not(::shadow)", |
142 ":host(::before)", | 139 ":host(::before)", |
143 ":host(::content)", | 140 ":host(::content)", |
144 ":host(::shadow)", | 141 ":host(::shadow)", |
145 ":host-context(::before)", | 142 ":host-context(::before)", |
146 ":host-context(::content)", | 143 ":host-context(::content)", |
147 ":host-context(::shadow)", | 144 ":host-context(::shadow)", |
148 ":-webkit-any(::after, ::before)", | 145 ":-webkit-any(::after, ::before)", |
149 ":-webkit-any(::content, span)", | 146 ":-webkit-any(::content, span)", |
150 ":-webkit-any(div, ::shadow)" | 147 ":-webkit-any(div, ::shadow)" |
151 }; | 148 }; |
152 | 149 |
153 for (auto testCase : testCases) { | 150 for (auto testCase : testCases) { |
154 CSSTokenizer::Scope scope(testCase); | 151 CSSTokenizer::Scope scope(testCase); |
155 CSSParserTokenRange range = scope.tokenRange(); | 152 CSSParserTokenRange range = scope.tokenRange(); |
156 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); | 153 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); |
157 EXPECT_FALSE(list.isValid()); | 154 EXPECT_FALSE(list.isValid()); |
158 } | 155 } |
159 } | 156 } |
160 | 157 |
| 158 TEST(CSSSelectorParserTest, ValidSimpleAfterPseudoElementInCompound) |
| 159 { |
| 160 const char* testCases[] = { |
| 161 "::-webkit-volume-slider:hover", |
| 162 "::selection:window-inactive", |
| 163 "::-webkit-scrollbar:disabled", |
| 164 "::-webkit-volume-slider:not(:hover)", |
| 165 "::-webkit-scrollbar:not(:horizontal)" |
| 166 }; |
| 167 |
| 168 for (auto testCase : testCases) { |
| 169 CSSTokenizer::Scope scope(testCase); |
| 170 CSSParserTokenRange range = scope.tokenRange(); |
| 171 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); |
| 172 EXPECT_TRUE(list.isValid()); |
| 173 } |
| 174 } |
| 175 |
| 176 TEST(CSSSelectorParserTest, InvalidSimpleAfterPseudoElementInCompound) |
| 177 { |
| 178 const char* testCases[] = { |
| 179 "::before#id", |
| 180 "::after:hover", |
| 181 ".class::content::before", |
| 182 "::shadow.class", |
| 183 "::selection:window-inactive::before", |
| 184 "::-webkit-volume-slider.class", |
| 185 "::content.a", |
| 186 "::content.a.b", |
| 187 ".a::content.b", |
| 188 "::before:not(.a)", |
| 189 "::shadow:not(::after)", |
| 190 "::content:not(#id)", |
| 191 "::-webkit-scrollbar:vertical:not(:first-child)", |
| 192 "video::-webkit-media-text-track-region-container.scrolling" |
| 193 }; |
| 194 |
| 195 for (auto testCase : testCases) { |
| 196 CSSTokenizer::Scope scope(testCase); |
| 197 CSSParserTokenRange range = scope.tokenRange(); |
| 198 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParser
Context(HTMLStandardMode, nullptr), nullptr); |
| 199 EXPECT_FALSE(list.isValid()); |
| 200 } |
| 201 } |
| 202 |
| 203 TEST(CSSSelectorParserTest, WorkaroundForInvalidCustomPseudoInUAStyle) |
| 204 { |
| 205 // See crbug.com/578131 |
| 206 CSSTokenizer::Scope scope("video::-webkit-media-text-track-region-container.
scrolling"); |
| 207 CSSParserTokenRange range = scope.tokenRange(); |
| 208 CSSSelectorList list = CSSSelectorParser::parseSelector(range, CSSParserCont
ext(UASheetMode, nullptr), nullptr); |
| 209 EXPECT_TRUE(list.isValid()); |
| 210 } |
| 211 |
161 } // namespace | 212 } // namespace |
OLD | NEW |