From 6e413653e72fd1eb471d779be63bccfa05d7c47f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 26 Apr 2017 18:16:10 -0700 Subject: [PATCH] Add unit tests for revalidation selectors. If these break, our cache may be subtly wrong in certain situations, which may be hard to detect. MozReview-Commit-ID: AXG2tpGnQ6k --- tests/unit/style/stylist.rs | 107 +++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/tests/unit/style/stylist.rs b/tests/unit/style/stylist.rs index 475eb7bc144..4f7ba303e08 100644 --- a/tests/unit/style/stylist.rs +++ b/tests/unit/style/stylist.rs @@ -4,15 +4,17 @@ use html5ever_atoms::LocalName; use selectors::parser::LocalName as LocalNameSelector; +use selectors::parser::Selector; use servo_atoms::Atom; use std::sync::Arc; use style::properties::{PropertyDeclarationBlock, PropertyDeclaration}; use style::properties::{longhands, Importance}; use style::rule_tree::CascadeLevel; -use style::selector_parser::SelectorParser; +use style::selector_parser::{SelectorImpl, SelectorParser}; use style::shared_lock::SharedRwLock; use style::stylesheets::StyleRule; use style::stylist::{Rule, SelectorMap}; +use style::stylist::needs_revalidation; use style::thread_state; /// Helper method to get some Rules from selector strings. @@ -56,6 +58,109 @@ fn get_mock_map(selectors: &[&str]) -> (SelectorMap, SharedRwLock) { (map, shared_lock) } +fn parse_selectors(selectors: &[&str]) -> Vec> { + selectors.iter() + .map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0 + .into_iter() + .nth(0) + .unwrap()) + .collect() +} + +#[test] +fn test_revalidation_selectors() { + let test = parse_selectors(&[ + // Not revalidation selectors. + "div", + "#bar", + "div:not(.foo)", + "div span", + "div > span", + + // Attribute selectors. + "div[foo]", + "div:not([foo])", + "div[foo = \"bar\"]", + "div[foo ~= \"bar\"]", + "div[foo |= \"bar\"]", + "div[foo ^= \"bar\"]", + "div[foo $= \"bar\"]", + "div[foo *= \"bar\"]", + "*|div[foo][bar = \"baz\"]", + + // Non-state-based pseudo-classes. + "div:empty", + "div:first-child", + "div:last-child", + "div:only-child", + "div:nth-child(2)", + "div:nth-last-child(2)", + "div:nth-of-type(2)", + "div:nth-last-of-type(2)", + "div:first-of-type", + "div:last-of-type", + "div:only-of-type", + + // Note: it would be nice to test :moz-any and the various other non-TS + // pseudo classes supported by gecko, but we don't have access to those + // in these unit tests. :-( + + // Sibling combinators. + "span + div", + "span ~ div", + + // Revalidation selectors that will get sliced. + "td > h1[dir]", + "td > span + h1[dir]", + "table td > span + div ~ h1[dir]", + ]).into_iter() + .filter(|s| needs_revalidation(&s)) + .map(|s| s.inner.slice_to_first_ancestor_combinator().complex) + .collect::>(); + + let reference = parse_selectors(&[ + // Attribute selectors. + "div[foo]", + "div:not([foo])", + "div[foo = \"bar\"]", + "div[foo ~= \"bar\"]", + "div[foo |= \"bar\"]", + "div[foo ^= \"bar\"]", + "div[foo $= \"bar\"]", + "div[foo *= \"bar\"]", + "*|div[foo][bar = \"baz\"]", + + // Non-state-based pseudo-classes. + "div:empty", + "div:first-child", + "div:last-child", + "div:only-child", + "div:nth-child(2)", + "div:nth-last-child(2)", + "div:nth-of-type(2)", + "div:nth-last-of-type(2)", + "div:first-of-type", + "div:last-of-type", + "div:only-of-type", + + // Sibling combinators. + "span + div", + "span ~ div", + + // Revalidation selectors that got sliced. + "h1[dir]", + "span + h1[dir]", + "span + div ~ h1[dir]", + ]).into_iter() + .map(|s| s.inner.complex) + .collect::>(); + + assert_eq!(test.len(), reference.len()); + for (t, r) in test.into_iter().zip(reference.into_iter()) { + assert_eq!(t, r) + } +} + #[test] fn test_rule_ordering_same_specificity() { let (rules_list, _) = get_mock_rules(&["a.intro", "img.sidebar"]);