diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2017-11-30 16:04:11 +0100 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2017-12-07 13:50:09 +0100 |
commit | 05a364c7b8d5787fdd25f42a874c949ebaca1e56 (patch) | |
tree | 1fb1a196747bbbc38344319a869d6bd819d0ff96 /ports | |
parent | 1a950d263a631c59534eb2c97e92348321e42d63 (diff) | |
download | servo-05a364c7b8d5787fdd25f42a874c949ebaca1e56.tar.gz servo-05a364c7b8d5787fdd25f42a874c949ebaca1e56.zip |
Move Stylo unit tests out of tests/unit
This will allow writing `tests/unit/*` in the root `Cargo.toml` file
to designate Servo unit tests.
Diffstat (limited to 'ports')
-rw-r--r-- | ports/geckolib/Cargo.toml | 2 | ||||
-rw-r--r-- | ports/geckolib/tests/Cargo.toml | 30 | ||||
-rw-r--r-- | ports/geckolib/tests/build.rs | 75 | ||||
-rw-r--r-- | ports/geckolib/tests/lib.rs | 37 | ||||
-rw-r--r-- | ports/geckolib/tests/servo_function_signatures.rs | 26 | ||||
-rw-r--r-- | ports/geckolib/tests/size_of.rs | 63 | ||||
-rw-r--r-- | ports/geckolib/tests/specified_values.rs | 50 |
7 files changed, 282 insertions, 1 deletions
diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml index 70ffc615d9b..5f370937b68 100644 --- a/ports/geckolib/Cargo.toml +++ b/ports/geckolib/Cargo.toml @@ -33,4 +33,4 @@ style = {path = "../../components/style", features = ["gecko"]} style_traits = {path = "../../components/style_traits"} [dev-dependencies] -stylo_tests = {path = "../../tests/unit/stylo"} +stylo_tests = {path = "./tests"} diff --git a/ports/geckolib/tests/Cargo.toml b/ports/geckolib/tests/Cargo.toml new file mode 100644 index 00000000000..7747fff2da9 --- /dev/null +++ b/ports/geckolib/tests/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "stylo_tests" +version = "0.0.1" +authors = ["The Servo Project Developers"] +license = "MPL-2.0" + +build = "build.rs" + +[lib] +name = "stylo_tests" +path = "lib.rs" +doctest = false + +[dependencies] +atomic_refcell = "0.1" +cssparser = "0.23.0" +env_logger = "0.4" +euclid = "0.15" +geckoservo = {path = "../../../ports/geckolib"} +libc = "0.2" +log = {version = "0.3.5", features = ["release_max_level_info"]} +malloc_size_of = {path = "../../../components/malloc_size_of"} +selectors = {path = "../../../components/selectors", features = ["gecko_like_types"]} +size_of_test = {path = "../../../components/size_of_test"} +smallvec = "0.6" +style_traits = {path = "../../../components/style_traits"} +style = {path = "../../../components/style", features = ["gecko"]} + +[build-dependencies] +regex = "0.2" diff --git a/ports/geckolib/tests/build.rs b/ports/geckolib/tests/build.rs new file mode 100644 index 00000000000..7712698c4b8 --- /dev/null +++ b/ports/geckolib/tests/build.rs @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +extern crate regex; + +use regex::Regex; +use std::env; +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; +use std::path::Path; + +fn main() { + if std::mem::size_of::<Option<bool>>() == 1 { + // https://github.com/rust-lang/rust/pull/45225 + println!("cargo:rustc-cfg=rustc_has_pr45225") + } + + let root_path = Path::new("../../../"); + let bindings_file = root_path.join("components/style/gecko/generated/bindings.rs"); + let glue_file = root_path.join("ports/geckolib/glue.rs"); + + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed={}", glue_file.display()); + println!("cargo:rerun-if-changed={}", bindings_file.display()); + + let env_out_dir = env::var("OUT_DIR").unwrap(); + let out_dir = Path::new(&env_out_dir); + + { + let output = out_dir.join("check_bindings.rs"); + let r = BufReader::new(File::open(bindings_file).unwrap()); + let mut w = File::create(output).unwrap(); + + w.write_all(b"fn assert_types() {\n").unwrap(); + + let matcher = Regex::new(r"fn\s*Servo_([a-zA-Z0-9_]+)\s*\(").unwrap(); + + for line in r.lines() { + let s = line.unwrap(); + for cap in matcher.captures_iter(&s) { + w.write_all(format!(" [ Servo_{0}, bindings::Servo_{0} ];\n", &cap[1]).as_bytes()).unwrap(); + } + } + + w.write_all(b"}\n").unwrap(); + } + + { + let output = out_dir.join("glue.rs"); + let r = BufReader::new(File::open(glue_file).unwrap()); + let mut w = File::create(output).unwrap(); + + w.write_all(b"pub use style::gecko::arc_types::*;\n").unwrap(); + + for line in r.lines() { + let s = line.unwrap().replace("pub extern \"C\" fn", "pub unsafe extern \"C\" fn"); + w.write_all(s.as_bytes()).unwrap(); + w.write_all(b"\n").unwrap(); + } + } + + // https://github.com/rust-lang/cargo/issues/3544 + let style_out_dir = env::var_os("DEP_FOR SOME REASON THE LINKS KEY IS REQUIRED \ + TO PASS DATA AROUND BETWEEN BUILD SCRIPTS_OUT_DIR").unwrap(); + File::create(out_dir.join("bindings.rs")) + .unwrap() + .write_all(format!("include!(concat!({:?}, \"/gecko/structs.rs\"));", + style_out_dir).as_bytes()) + .unwrap(); + + if env::var_os("MOZ_SRC").is_some() { + println!("cargo:rustc-cfg=linking_with_gecko") + } +} diff --git a/ports/geckolib/tests/lib.rs b/ports/geckolib/tests/lib.rs new file mode 100644 index 00000000000..62fd455239d --- /dev/null +++ b/ports/geckolib/tests/lib.rs @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Disable this entire crate on Windows when Gecko symbols are not available +// as linking would fail: +// https://github.com/rust-lang/rust/pull/44603#issuecomment-338807312 +// +// On Linux and OS X linking succeeds anyway. +// Presumably these symbol declarations don’t need to be resolved +// as they’re not used in any code called from this crate. +#![cfg(any(linking_with_gecko, not(windows)))] + +extern crate atomic_refcell; +extern crate cssparser; +extern crate env_logger; +extern crate geckoservo; +#[macro_use] extern crate log; +extern crate malloc_size_of; +extern crate selectors; +extern crate smallvec; +#[macro_use] extern crate size_of_test; +#[macro_use] extern crate style; +extern crate style_traits; + +#[cfg(target_pointer_width = "64")] +mod size_of; +mod specified_values; + +mod servo_function_signatures; + +use style::*; + +#[allow(dead_code, improper_ctypes)] +mod bindings { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} diff --git a/ports/geckolib/tests/servo_function_signatures.rs b/ports/geckolib/tests/servo_function_signatures.rs new file mode 100644 index 00000000000..90d925fb1e1 --- /dev/null +++ b/ports/geckolib/tests/servo_function_signatures.rs @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![allow(unused)] + +use self::glue::*; +use style::gecko_bindings::bindings; +use style::gecko_properties::*; + +include!(concat!(env!("OUT_DIR"), "/check_bindings.rs")); + +#[path = "../../../ports/geckolib/error_reporter.rs"] +mod error_reporter; + +#[path = "../../../ports/geckolib/stylesheet_loader.rs"] +mod stylesheet_loader; + +#[allow(non_snake_case, unused_unsafe, private_no_mangle_fns)] +mod glue { + // this module pretends to be glue.rs, with the safe functions swapped for unsafe ones. This is + // a hack to compensate for the fact that `fn` types cannot coerce to `unsafe fn` types. The + // imports are populated with the same things so the type assertion should be equivalent + use geckoservo::*; + include!(concat!(env!("OUT_DIR"), "/glue.rs")); +} diff --git a/ports/geckolib/tests/size_of.rs b/ports/geckolib/tests/size_of.rs new file mode 100644 index 00000000000..9c2f6cbba1c --- /dev/null +++ b/ports/geckolib/tests/size_of.rs @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use selectors::gecko_like_types as dummies; +use servo_arc::Arc; +use std::mem::{size_of, align_of}; +use style; +use style::applicable_declarations::ApplicableDeclarationBlock; +use style::data::{ElementData, ElementStyles}; +use style::gecko::selector_parser as real; +use style::properties::ComputedValues; +use style::rule_tree::{RuleNode, StrongRuleNode}; +use style::values::computed; +use style::values::specified; + +#[test] +fn size_of_selectors_dummy_types() { + assert_eq!(size_of::<dummies::PseudoClass>(), size_of::<real::NonTSPseudoClass>()); + assert_eq!(align_of::<dummies::PseudoClass>(), align_of::<real::NonTSPseudoClass>()); + + assert_eq!(size_of::<dummies::PseudoElement>(), size_of::<real::PseudoElement>()); + assert_eq!(align_of::<dummies::PseudoElement>(), align_of::<real::PseudoElement>()); + + assert_eq!(size_of::<dummies::Atom>(), size_of::<style::Atom>()); + assert_eq!(align_of::<dummies::Atom>(), align_of::<style::Atom>()); +} + +// The size of this is critical to performance on the bloom-basic microbenchmark. +// When iterating over a large Rule array, we want to be able to fast-reject +// selectors (with the inline hashes) with as few cache misses as possible. +size_of_test!(test_size_of_rule, style::stylist::Rule, 32); + +// Large pages generate tens of thousands of ComputedValues. +size_of_test!(test_size_of_cv, ComputedValues, 256); + +size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8); +size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8); + +size_of_test!(test_size_of_element_styles, ElementStyles, 16); +size_of_test!(test_size_of_element_data, ElementData, 24); + +size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32); + +size_of_test!(test_size_of_application_declaration_block, ApplicableDeclarationBlock, 24); + +// FIXME(bholley): This can shrink with a little bit of work. +// See https://github.com/servo/servo/issues/17280 +size_of_test!(test_size_of_rule_node, RuleNode, 80); + +// This is huge, but we allocate it on the stack and then never move it, +// we only pass `&mut SourcePropertyDeclaration` references around. +size_of_test!(test_size_of_parsed_declaration, style::properties::SourcePropertyDeclaration, 576); + +size_of_test!(test_size_of_computed_image, computed::image::Image, 40); +size_of_test!(test_size_of_specified_image, specified::image::Image, 40); + +// FIXME(bz): These can shrink if we move the None_ value inside the +// enum instead of paying an extra word for the Either discriminant. +size_of_test!(test_size_of_computed_image_layer, computed::image::ImageLayer, + if cfg!(rustc_has_pr45225) { 40 } else { 48 }); +size_of_test!(test_size_of_specified_image_layer, specified::image::ImageLayer, + if cfg!(rustc_has_pr45225) { 40 } else { 48 }); diff --git a/ports/geckolib/tests/specified_values.rs b/ports/geckolib/tests/specified_values.rs new file mode 100644 index 00000000000..6bc01a97a46 --- /dev/null +++ b/ports/geckolib/tests/specified_values.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use style; + +#[cfg(all(test, target_pointer_width = "64"))] +#[test] +fn size_of_specified_values() { + use std::mem::size_of; + let threshold = 24; + + let mut bad_properties = vec![]; + + macro_rules! check_property { + ( $( { $name: ident, $boxed: expr } )+ ) => { + $( + let size = size_of::<style::properties::longhands::$name::SpecifiedValue>(); + let is_boxed = $boxed; + if (!is_boxed && size > threshold) || (is_boxed && size <= threshold) { + bad_properties.push((stringify!($name), size, is_boxed)); + } + )+ + } + } + + longhand_properties_idents!(check_property); + + let mut failing_messages = vec![]; + + for bad_prop in bad_properties { + if !bad_prop.2 { + failing_messages.push( + format!("Your changes have increased the size of {} SpecifiedValue to {}. The threshold is \ + currently {}. SpecifiedValues affect size of PropertyDeclaration enum and \ + increasing the size may negative affect style system performance. Please consider \ + using `boxed=\"True\"` in this longhand.", + bad_prop.0, bad_prop.1, threshold)); + } else if bad_prop.2 { + failing_messages.push( + format!("Your changes have decreased the size of {} SpecifiedValue to {}. Good work! \ + The threshold is currently {}. Please consider removing `boxed=\"True\"` from this longhand.", + bad_prop.0, bad_prop.1, threshold)); + } + } + + if !failing_messages.is_empty() { + panic!("{}", failing_messages.join("\n\n")); + } +} |