Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature-gate tests to reduce dependencies #108

Merged
merged 18 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f37c5c6
Feature-gate all features in order to reduce the dependencies pulled in
rlee287 Sep 12, 2021
b5c50fd
Break long cfg(any(...)) lines
rlee287 Sep 12, 2021
1e5f024
Update documentation to state the features required for each macro.
rlee287 Sep 12, 2021
f9b7aaa
Forgot to break one more long line
rlee287 Sep 12, 2021
663a15f
Update Github Actions flow to specify feature flags
rlee287 Sep 12, 2021
915fd4c
Specify bash for check for shell if-else to work on Windows
rlee287 Sep 13, 2021
e98a078
Use the built-in compile_error! macro to require at least one feature
rlee287 Sep 14, 2021
e40d94c
Rename the markdown feature to markdown_deps_updated
rlee287 Sep 14, 2021
17a2442
Rename the regex_version feature to contains_regex
rlee287 Sep 14, 2021
b54a570
Rename html_root_url feature to html_root_url_updated
rlee287 Sep 14, 2021
99742f0
Enable all features by default
rlee287 Sep 14, 2021
356a7c9
Remove most imports via fully qualified paths, and move most of the rest
rlee287 Sep 14, 2021
d1863e6
Update Github Actions workflow with feature names and suppressing def…
rlee287 Sep 14, 2021
2083fc0
Move around feature listing/documentation
rlee287 Sep 16, 2021
2383a33
Remove feature gate for custom Result type
rlee287 Sep 16, 2021
94746dc
Remove feature gate from read_file helper function
rlee287 Sep 16, 2021
8940738
Add comment explaining why some imports are inside functions
rlee287 Sep 16, 2021
27b67b8
Remove last imports in helpers.rs by qualifying helper func types
rlee287 Sep 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,26 @@ jobs:
- name: Install ${{ matrix.rust }} Rust
run: rustup default ${{ matrix.rust }}

- name: Build and test
run: cargo test
# Verify that features work by themselves
# Features should not interfere with each other
# Should only need to check 0, 1, and (all) 3 features enabled

# Use if statement to invert exit code: this should fail
- name: Check failure to build with no features
run: if cargo check --no-default-features; then false; else true; fi
shell: bash

- name: Build and test with markdown_deps_updated feature
run: cargo test --no-default-features --features markdown_deps_updated

- name: Build and test with html_root_url_updated feature
run: cargo test --no-default-features --features html_root_url_updated

- name: Build and test with contains_regex feature
run: cargo test --no-default-features --features contains_regex

- name: Build and test with all features
run: cargo test --all-features

build-documentation:
name: Build documentation
Expand Down
20 changes: 13 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ categories = ["development-tools", "rust-patterns"]
license = "MIT"
edition = "2018"

[features]
default = ["markdown_deps_updated", "html_root_url_updated", "contains_regex"]
markdown_deps_updated = ["pulldown-cmark", "semver-parser", "toml"]
html_root_url_updated = ["url", "semver-parser", "syn", "proc-macro2"]
contains_regex = ["regex"]

[dependencies]
pulldown-cmark = { version = "0.8", default-features = false }
semver-parser = "0.9"
syn = { version = "1.0", features = ["full"] }
proc-macro2 = { version = "1.0", features = ["span-locations"] }
toml = "0.5"
url = "2.0"
regex = { version = "1.3", default-features = false, features = ["std", "unicode"] }
pulldown-cmark = { version = "0.8", default-features = false, optional = true }
semver-parser = { version = "0.9", optional = true }
syn = { version = "1.0", default-features = false, features = ["parsing", "printing", "full"], optional = true }
proc-macro2 = { version = "1.0", default-features = false, features = ["span-locations"], optional = true }
toml = { version = "0.5", optional = true }
url = { version = "2.0", optional = true }
regex = { version = "1.3", default-features = false, features = ["std", "unicode"], optional = true }

[dev-dependencies]
tempfile = "3.1"
1 change: 1 addition & 0 deletions src/contains_regex.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg(feature = "contains_regex")]
use regex::{escape, Regex};

use crate::helpers::{read_file, Result};
Expand Down
31 changes: 21 additions & 10 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::fmt::Display;
use std::fs::File;
use std::io::{self, Read};
use std::result;

use semver_parser::range::{Op, VersionReq};
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
use semver_parser::range::VersionReq;
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
use semver_parser::version::Version;

/// The common result type, our errors will be simple strings.
pub type Result<T> = result::Result<T, String>;
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated",
feature = "contains_regex"))]
pub type Result<T> = std::result::Result<T, String>;

#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
fn join<T>(iter: T, sep: &str) -> String
where
T: IntoIterator,
T::Item: Display,
T::Item: std::fmt::Display,
{
let mut buf = String::new();
let mut iter = iter.into_iter();
Expand All @@ -33,20 +33,27 @@ where
/// Return all data from `path`. Line boundaries are normalized from
/// "\r\n" to "\n" to make sure "^" and "$" will match them. See
/// https://github.com/rust-lang/regex/issues/244 for details.
pub fn read_file(path: &str) -> io::Result<String> {
let mut file = File::open(path)?;
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated",
rlee287 marked this conversation as resolved.
Show resolved Hide resolved
feature = "contains_regex"))]
pub fn read_file(path: &str) -> std::io::Result<String> {
use std::io::Read;

let mut file = std::fs::File::open(path)?;
let mut buf = String::new();
file.read_to_string(&mut buf)?;
Ok(buf.replace("\r\n", "\n"))
}

/// Indent every line in text by four spaces.
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
pub fn indent(text: &str) -> String {
join(text.lines().map(|line| String::from(" ") + line), "\n")
}

/// Verify that the version range request matches the given version.
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
pub fn version_matches_request(version: &Version, request: &VersionReq) -> Result<()> {
use semver_parser::range::Op;
if request.predicates.len() != 1 {
// Can only handle simple dependencies
return Ok(());
Expand Down Expand Up @@ -93,11 +100,15 @@ pub fn version_matches_request(version: &Version, request: &VersionReq) -> Resul

#[cfg(test)]
mod tests {
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
use semver_parser::range::parse as parse_request;
#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
use semver_parser::version::parse as parse_version;

#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
use super::*;

#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
mod test_version_matches_request {
use super::*;

Expand Down
1 change: 1 addition & 0 deletions src/html_root_url.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg(feature = "html_root_url_updated")]
use semver_parser::range::parse as parse_request;
use semver_parser::version::parse as parse_version;
use semver_parser::version::Version;
Expand Down
30 changes: 27 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@
//! version numbers need updating:
//!
//! * TOML examples in the `README.md` files that show how to add a
//! dependency on your crate. See [`assert_markdown_deps_updated`].
//! dependency on your crate, gated behind the
rlee287 marked this conversation as resolved.
Show resolved Hide resolved
//! "markdown_deps_updated" feature.
//! See [`assert_markdown_deps_updated`].
//!
//! * A `Changelog.md` file that should at least mention the current
//! version. See [`assert_contains_regex`].
//! version, gated behind the "regex_version" feature.
//! See [`assert_contains_regex`].
//!
//! * The [`html_root_url`] attribute that tells other crates where to
//! find your documentation. See [`assert_html_root_url_updated`].
//! find your documentation, gated behind the "html_root_url" feature.
//! See [`assert_html_root_url_updated`].
//!
//! At least one of the three features must be enabled.
//!
//! A typical configuration will use an integration test to verify
//! that all version numbers are in sync. Create a
Expand All @@ -22,18 +28,22 @@
//! ```rust
//! #[test]
//! # fn fake_hidden_test_case_1() {}
//! # #[cfg(feature = "markdown_deps_updated")]
//! fn test_readme_deps() {
//! version_sync::assert_markdown_deps_updated!("README.md");
//! }
//!
//! #[test]
//! # fn fake_hidden_test_case_2() {}
//! # #[cfg(feature = "html_root_url_updated")]
//! fn test_html_root_url() {
//! version_sync::assert_html_root_url_updated!("src/lib.rs");
//! }
//!
//! # fn main() {
//! # #[cfg(feature = "markdown_deps_updated")]
//! # test_readme_deps();
//! # #[cfg(feature = "html_root_url_updated")]
//! # test_html_root_url();
//! # }
//! ```
Expand All @@ -54,11 +64,20 @@ mod helpers;
mod html_root_url;
mod markdown_deps;

// Ensure that at least one feature is enabled
#[cfg(not(any(feature = "contains_regex", feature = "html_root_url_updated",
feature = "markdown_deps_updated")))]
std::compile_error!("Please select at least one feature.");

#[cfg(feature = "contains_regex")]
pub use crate::contains_regex::check_contains_regex;
#[cfg(feature = "html_root_url_updated")]
pub use crate::html_root_url::check_html_root_url;
#[cfg(feature = "markdown_deps_updated")]
pub use crate::markdown_deps::check_markdown_deps;

/// Assert that dependencies on the current package are up to date.
/// Requires the "markdown_deps_updated" feature.
rlee287 marked this conversation as resolved.
Show resolved Hide resolved
///
/// The macro will call [`check_markdown_deps`] on the file name given
/// in order to check that the TOML examples found all depend on a
Expand Down Expand Up @@ -95,6 +114,7 @@ pub use crate::markdown_deps::check_markdown_deps;
///
/// [`check_markdown_deps`]: fn.check_markdown_deps.html
#[macro_export]
#[cfg(feature = "markdown_deps_updated")]
macro_rules! assert_markdown_deps_updated {
($path:expr) => {
let pkg_name = env!("CARGO_PKG_NAME");
Expand All @@ -106,6 +126,7 @@ macro_rules! assert_markdown_deps_updated {
}

/// Assert that the `html_root_url` attribute is up to date.
/// Requires the "html_root_url_updated" feature.
///
/// Library code is [expected to set `html_root_url`][api-guidelines]
/// to point to docs.rs so that rustdoc can generate correct links
Expand Down Expand Up @@ -147,6 +168,7 @@ macro_rules! assert_markdown_deps_updated {
/// [api-guidelines]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#crate-sets-html_root_url-attribute-c-html-root
/// [`check_html_root_url`]: fn.check_html_root_url.html
#[macro_export]
#[cfg(feature = "html_root_url_updated")]
macro_rules! assert_html_root_url_updated {
($path:expr) => {
let pkg_name = env!("CARGO_PKG_NAME");
Expand All @@ -158,6 +180,7 @@ macro_rules! assert_html_root_url_updated {
}

/// Assert that versions numbers are up to date via a regex.
/// Requires the "contains_regex" feature.
///
/// This macro allows you verify that the current version number is
/// mentioned in a particular file, such as a changelog file. You do
Expand Down Expand Up @@ -210,6 +233,7 @@ macro_rules! assert_html_root_url_updated {
///
/// [`check_contains_regex`]: fn.check_contains_regex.html
#[macro_export]
#[cfg(feature = "contains_regex")]
macro_rules! assert_contains_regex {
($path:expr, $format:expr) => {
let pkg_name = env!("CARGO_PKG_NAME");
Expand Down
1 change: 1 addition & 0 deletions src/markdown_deps.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg(feature = "markdown_deps_updated")]
use pulldown_cmark::{CodeBlockKind::Fenced, Event, Parser, Tag};
use semver_parser::range::parse as parse_request;
use semver_parser::range::VersionReq;
Expand Down
3 changes: 3 additions & 0 deletions tests/version-numbers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#[test]
#[cfg(feature = "markdown_deps_updated")]
fn test_readme_deps() {
version_sync::assert_markdown_deps_updated!("README.md");
}

#[test]
#[cfg(feature = "contains_regex")]
fn test_readme_changelog() {
version_sync::assert_contains_regex!(
"README.md",
Expand All @@ -12,6 +14,7 @@ fn test_readme_changelog() {
}

#[test]
#[cfg(feature = "html_root_url_updated")]
fn test_html_root_url() {
version_sync::assert_html_root_url_updated!("src/lib.rs");
}