Add support for multiple formats to test cases

This patch adds support for multiple rustdoc output formats to the test
suite.  This is a preparation for adding support for rustdoc’s JSON
output.
This commit is contained in:
Robin Krahl 2020-09-12 18:38:49 +02:00
parent b0485d515c
commit 601ec251f8
No known key found for this signature in database
GPG Key ID: 8E9B0870524F69D8
299 changed files with 98 additions and 56 deletions

View File

@ -5,6 +5,10 @@ SPDX-License-Identifier: MIT
# Changelog for rusty-man # Changelog for rusty-man
# Unreleased
- Prepare supporting multiple parser backends.
## v0.4.2 (2021-06-06) ## v0.4.2 (2021-06-06)
This patch releases adds support for the new search index format (Rust 1.52.0 This patch releases adds support for the new search index format (Rust 1.52.0

View File

@ -255,7 +255,7 @@ impl Index {
mod tests { mod tests {
use super::{CrateData, Data, Index, IndexItem, ItemData}; use super::{CrateData, Data, Index, IndexItem, ItemData};
use crate::doc::ItemType; use crate::doc::ItemType;
use crate::test_utils::with_rustdoc; use crate::test_utils::{with_rustdoc, Format};
#[test] #[test]
fn test_empty() { fn test_empty() {
@ -296,7 +296,7 @@ mod tests {
#[test] #[test]
fn test_index() { fn test_index() {
with_rustdoc(">=1.44.0, <1.50.0", |_, path| { with_rustdoc(">=1.44.0, <1.50.0", Format::all(), |_, _, path| {
let index = Index::load(path.join("search-index.js")).unwrap().unwrap(); let index = Index::load(path.join("search-index.js")).unwrap().unwrap();
let empty: Vec<IndexItem> = Vec::new(); let empty: Vec<IndexItem> = Vec::new();
@ -315,7 +315,7 @@ mod tests {
assert_eq!(empty, index.find(&"NodeDataReff".to_owned().into())); assert_eq!(empty, index.find(&"NodeDataReff".to_owned().into()));
}); });
with_rustdoc(">=1.50.0", |_, path| { with_rustdoc(">=1.50.0", Format::all(), |_, _, path| {
let index = Index::load(path.join("search-index.js")).unwrap().unwrap(); let index = Index::load(path.join("search-index.js")).unwrap().unwrap();
let empty: Vec<IndexItem> = Vec::new(); let empty: Vec<IndexItem> = Vec::new();
@ -334,7 +334,7 @@ mod tests {
assert_eq!(empty, index.find(&"NodeDataReff".to_owned().into())); assert_eq!(empty, index.find(&"NodeDataReff".to_owned().into()));
}); });
with_rustdoc(">=1.44.0", |_, path| { with_rustdoc(">=1.44.0", Format::all(), |_, _, path| {
let index = Index::load(path.join("search-index.js")).unwrap().unwrap(); let index = Index::load(path.join("search-index.js")).unwrap().unwrap();
let empty: Vec<IndexItem> = Vec::new(); let empty: Vec<IndexItem> = Vec::new();

View File

@ -208,11 +208,11 @@ fn select_item(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::source; use crate::source;
use crate::test_utils::with_rustdoc; use crate::test_utils::{with_rustdoc, Format};
#[test] #[test]
fn test_find_doc() { fn test_find_doc() {
with_rustdoc("*", |_, path| { with_rustdoc("*", Format::all(), |_, _, path| {
let sources = source::Sources::new(vec![source::get_source(path).unwrap()]); let sources = source::Sources::new(vec![source::get_source(path).unwrap()]);
assert!(sources assert!(sources

View File

@ -759,11 +759,11 @@ fn get_item_group_id(ty: doc::ItemType) -> &'static str {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::doc; use crate::doc;
use crate::test_utils::with_rustdoc; use crate::test_utils::{with_rustdoc, Format};
#[test] #[test]
fn test_find_item() { fn test_find_item() {
with_rustdoc("*", |_, path| { with_rustdoc("*", Format::all(), |_, _, path| {
let path = path.join("kuchiki").join("all.html"); let path = path.join("kuchiki").join("all.html");
let parser = super::Parser::from_file(path).unwrap(); let parser = super::Parser::from_file(path).unwrap();
@ -777,7 +777,7 @@ mod tests {
#[test] #[test]
fn test_parse_item_doc() { fn test_parse_item_doc() {
with_rustdoc("*", |_, path| { with_rustdoc("*", Format::all(), |_, _, path| {
let path = path.join("kuchiki").join("struct.NodeRef.html"); let path = path.join("kuchiki").join("struct.NodeRef.html");
let name: doc::Fqn = "kuchiki::NodeRef".to_owned().into(); let name: doc::Fqn = "kuchiki::NodeRef".to_owned().into();
let doc = super::Parser::from_file(path) let doc = super::Parser::from_file(path)
@ -794,7 +794,7 @@ mod tests {
#[test] #[test]
fn test_find_member() { fn test_find_member() {
with_rustdoc("*", |_, path| { with_rustdoc("*", Format::all(), |_, _, path| {
let path = path.join("kuchiki").join("struct.NodeDataRef.html"); let path = path.join("kuchiki").join("struct.NodeDataRef.html");
let name: doc::Fqn = "kuchiki::NodeDataRef::as_node".to_owned().into(); let name: doc::Fqn = "kuchiki::NodeDataRef::as_node".to_owned().into();
let ty = super::Parser::from_file(path) let ty = super::Parser::from_file(path)
@ -807,7 +807,7 @@ mod tests {
#[test] #[test]
fn test_parse_member_doc() { fn test_parse_member_doc() {
with_rustdoc("*", |_, path| { with_rustdoc("*", Format::all(), |_, _, path| {
let path = path.join("kuchiki").join("struct.NodeDataRef.html"); let path = path.join("kuchiki").join("struct.NodeDataRef.html");
let name: doc::Fqn = "kuchiki::NodeDataRef::as_node".to_owned().into(); let name: doc::Fqn = "kuchiki::NodeDataRef::as_node".to_owned().into();
let doc = super::Parser::from_file(path) let doc = super::Parser::from_file(path)

View File

@ -4,19 +4,46 @@
//! Utility functions for executing tests with the output of different rustdoc versions. //! Utility functions for executing tests with the output of different rustdoc versions.
use std::env; use std::env;
use std::fmt;
use std::fs; use std::fs;
use std::path; use std::path;
use std::process; use std::process;
use std::sync; use std::sync;
static mut VERSIONS: Option<Vec<(semver::Version, path::PathBuf)>> = None; static mut VERSIONS: Option<Vec<(semver::Version, Format, path::PathBuf)>> = None;
static INIT: sync::Once = sync::Once::new(); static INIT: sync::Once = sync::Once::new();
fn get_versions() -> &'static [(semver::Version, path::PathBuf)] { #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Format {
Html,
}
impl Format {
pub fn all() -> &'static [Format] {
FORMATS
}
}
static FORMATS: &[Format] = &[Format::Html];
impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Format::Html => "html",
})
}
}
fn get_versions() -> &'static [(semver::Version, Format, path::PathBuf)] {
INIT.call_once(|| { INIT.call_once(|| {
let mut versions = find_rust_versions("tests/html"); let mut versions = Vec::new();
for format in Format::all() {
versions.append(&mut find_rust_versions(*format));
if env::var("RUSTY_MAN_GENERATE").is_ok() { if env::var("RUSTY_MAN_GENERATE").is_ok() {
versions.push(generate_docs()); if let Some(docs) = generate_docs(*format) {
versions.push(docs);
}
}
} }
unsafe { unsafe {
VERSIONS = Some(versions); VERSIONS = Some(versions);
@ -26,21 +53,31 @@ fn get_versions() -> &'static [(semver::Version, path::PathBuf)] {
unsafe { VERSIONS.as_ref().unwrap() } unsafe { VERSIONS.as_ref().unwrap() }
} }
fn find_rust_versions(path: impl AsRef<path::Path>) -> Vec<(semver::Version, path::PathBuf)> { fn find_rust_versions(format: Format) -> Vec<(semver::Version, Format, path::PathBuf)> {
fs::read_dir(path) let mut path = path::PathBuf::from("tests");
path.push(format.to_string());
if !path.is_dir() {
return Vec::new();
}
fs::read_dir(&path)
.unwrap() .unwrap()
.map(Result::unwrap) .map(Result::unwrap)
.filter(|e| e.file_type().unwrap().is_dir()) .filter(|e| e.file_type().unwrap().is_dir())
.map(|e| { .map(|e| {
( (
semver::Version::parse(&e.file_name().into_string().unwrap()).unwrap(), semver::Version::parse(&e.file_name().into_string().unwrap()).unwrap(),
format,
e.path(), e.path(),
) )
}) })
.collect() .collect()
} }
fn generate_docs() -> (semver::Version, path::PathBuf) { fn generate_docs(format: Format) -> Option<(semver::Version, Format, path::PathBuf)> {
if format != Format::Html {
return None;
}
// TODO: check which rustc/rustdoc $CARGO is using // TODO: check which rustc/rustdoc $CARGO is using
let version = rustc_version::version().unwrap(); let version = rustc_version::version().unwrap();
let mut path = tempfile::tempdir().unwrap().into_path(); let mut path = tempfile::tempdir().unwrap().into_path();
@ -56,25 +93,26 @@ fn generate_docs() -> (semver::Version, path::PathBuf) {
.output() .output()
.unwrap(); .unwrap();
path.push("doc"); path.push("doc");
(version, path) Some((version, format, path))
} }
/// Calls the given function with all paths to rustdoc documentation generated by rustdoc versions /// Calls the given function with all paths to rustdoc documentation generated by rustdoc versions
/// that match the given requirement string. /// that match the given requirement string.
pub fn with_rustdoc<F>(version: &str, f: F) pub fn with_rustdoc<F>(version: &str, formats: &[Format], f: F)
where where
F: Fn(&semver::Version, &path::Path), F: Fn(&semver::Version, Format, &path::Path),
{ {
let version_req = semver::VersionReq::parse(version).unwrap(); let version_req = semver::VersionReq::parse(version).unwrap();
let versions = get_versions(); let versions = get_versions();
for (version, path) in versions { for (version, format, path) in versions {
if version_req.matches(&version) { if version_req.matches(&version) && formats.contains(format) {
log::warn!( log::warn!(
"Executing test case for version {} at {}", "Executing test case for version {} at {} (format {})",
version, version,
path.display() path.display(),
format
); );
f(version, &path); f(version, *format, &path);
} }
} }
} }

View File

@ -10,7 +10,7 @@ use std::process;
use assert_cmd::prelude::*; use assert_cmd::prelude::*;
use test_utils::with_rustdoc; use test_utils::{with_rustdoc, Format};
fn run(path: impl AsRef<path::Path>, args: &[&str]) -> assert_cmd::assert::Assert { fn run(path: impl AsRef<path::Path>, args: &[&str]) -> assert_cmd::assert::Assert {
process::Command::cargo_bin(env!("CARGO_PKG_NAME")) process::Command::cargo_bin(env!("CARGO_PKG_NAME"))
@ -29,12 +29,12 @@ fn get_stdout(path: impl AsRef<path::Path>, args: &[&str]) -> String {
} }
macro_rules! generate_run { macro_rules! generate_run {
($name:ident $version:literal $args:expr) => { ($name:ident $version:literal $formats:expr; $args:expr) => {
#[test] #[test]
fn $name() { fn $name() {
with_rustdoc($version, |version, path| { with_rustdoc($version, $formats, |version, format, path| {
insta::assert_snapshot!( insta::assert_snapshot!(
format!("{}_{}", version, std::stringify!($name)), format!("{}_{}_{}", version, format, std::stringify!($name)),
get_stdout(path, $args) get_stdout(path, $args)
); );
}); });
@ -43,50 +43,50 @@ macro_rules! generate_run {
} }
macro_rules! assert_doc { macro_rules! assert_doc {
($( $name:ident($version:literal): $item:literal ),* $(,)? ) => { ($( $name:ident($version:literal, $formats:expr): $item:literal ),* $(,)? ) => {
$( $(
generate_run!($name $version &[$item]); generate_run!($name $version $formats; &[$item]);
)* )*
}; };
} }
macro_rules! assert_examples { macro_rules! assert_examples {
($( $name:ident($version:literal): $item:literal ),* $(,)? ) => { ($( $name:ident($version:literal, $formats:expr): $item:literal ),* $(,)? ) => {
$( $(
generate_run!($name $version &["-e", $item]); generate_run!($name $version $formats; &["-e", $item]);
)* )*
}; };
} }
assert_doc![ assert_doc![
mod_anyhow("*"): "anyhow", mod_anyhow("*", Format::all()): "anyhow",
macro_anyhow_anyhow("*"): "anyhow::anyhow", macro_anyhow_anyhow("*", Format::all()): "anyhow::anyhow",
macro_anyhow_ensure("*"): "anyhow::ensure", macro_anyhow_ensure("*", Format::all()): "anyhow::ensure",
struct_anyhow_error("<1.51.0"): "anyhow::Error", struct_anyhow_error("<1.51.0", Format::all()): "anyhow::Error",
trait_anyhow_context("*"): "anyhow::Context", trait_anyhow_context("*", Format::all()): "anyhow::Context",
type_anyhow_result("*"): "anyhow::Result", type_anyhow_result("*", Format::all()): "anyhow::Result",
]; ];
assert_doc![ assert_doc![
mod_log("*"): "log", mod_log("*", Format::all()): "log",
macro_log_debug("*"): "log::debug", macro_log_debug("*", Format::all()): "log::debug",
struct_log_metadata("*"): "log::Metadata", struct_log_metadata("*", Format::all()): "log::Metadata",
enum_log_level("*"): "log::Level", enum_log_level("*", Format::all()): "log::Level",
constant_log_static_max_level("*"): "log::STATIC_MAX_LEVEL", constant_log_static_max_level("*", Format::all()): "log::STATIC_MAX_LEVEL",
trait_log_log("*"): "log::Log", trait_log_log("*", Format::all()): "log::Log",
fn_log_logger("*"): "log::logger", fn_log_logger("*", Format::all()): "log::logger",
fn_log_set_logger_racy("*"): "log::set_logger_racy", fn_log_set_logger_racy("*", Format::all()): "log::set_logger_racy",
]; ];
assert_doc![ assert_doc![
mod_rand_core("*"): "rand_core", mod_rand_core("*", Format::all()): "rand_core",
trait_rand_core_rngcore("*"): "rand_core::RngCore", trait_rand_core_rngcore("*", Format::all()): "rand_core::RngCore",
trait_rand_core_seedablerng("*"): "rand_core::SeedableRng", trait_rand_core_seedablerng("*", Format::all()): "rand_core::SeedableRng",
struct_rand_core_block_blockrng("*"): "rand_core::block::BlockRng", struct_rand_core_block_blockrng("*", Format::all()): "rand_core::block::BlockRng",
]; ];
assert_examples![ assert_examples![
examples_mod_anyhow("*"): "anyhow", examples_mod_anyhow("*", Format::all()): "anyhow",
examples_mod_log(">1.40.0"): "log", examples_mod_log(">1.40.0", Format::all()): "log",
examples_struct_rand_core_rngcore("*"): "rand_core::RngCore", examples_struct_rand_core_rngcore("*", Format::all()): "rand_core::RngCore",
]; ];

Some files were not shown because too many files have changed in this diff Show More