/* * Copyright 2022 Arnaud Golfouse * * 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 https://mozilla.org/MPL/2.0/. */ use std::{ fs, io, path::{Path, PathBuf}, process::Command, }; const LICENSE_TEXT: &str = r"/* * Copyright 2022 Arnaud Golfouse * * 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 https://mozilla.org/MPL/2.0/. */"; const SOURCE_DIRS: &[&str] = &["src", "examples", "tests", "benches"]; fn get_all_rust_file_paths() -> Result, io::Error> { fn get_all_rust_file_paths_inner( root: bool, path: PathBuf, output: &mut Vec, ) -> Result<(), io::Error> { if path.is_dir() { for entry in path.read_dir()? { let entry = entry?.path(); if !(root && entry.iter().last() == Some(std::ffi::OsStr::new("target"))) { get_all_rust_file_paths_inner(false, entry, output)?; } } } else if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("rs") { output.push(path); } Ok(()) } let mut result = Vec::new(); get_all_rust_file_paths_inner(true, PathBuf::from("."), &mut result)?; Ok(result) } fn get_root_rust_file_paths() -> Result, io::Error> { fn get_root_rust_file_paths_inner( path: PathBuf, output: &mut Vec, ) -> Result<(), io::Error> { if path.is_dir() { for entry in path.read_dir()? { let entry = entry?; let path = entry.path(); if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("rs") { output.push(path); } } } Ok(()) } let mut result = Vec::new(); for source in SOURCE_DIRS { get_root_rust_file_paths_inner(PathBuf::from(source), &mut result)?; } Ok(result) } fn check_license(path: &Path) -> bool { let file = fs::read_to_string(path).unwrap(); file.contains(LICENSE_TEXT) } fn check_format(path: &Path) -> Result<(), String> { let mut command = Command::new("rustfmt"); command.arg("--check").arg(path); let output = command.output().unwrap(); if output.status.success() { Ok(()) } else { Err(String::from_utf8_lossy(&output.stdout).into()) } } #[test] fn license() { let files = get_all_rust_file_paths().unwrap(); for file in files { if !check_license(&file) { panic!("license text for file {} is incorrect", file.display()); } } } #[test] fn formatting() { let root_files = get_root_rust_file_paths().unwrap(); for root_file in root_files { // formatting is automatically done on modules from the root file if let Err(msg) = check_format(&root_file) { panic!("incorrect formatting:\n{msg}"); } } } #[test] fn doclinks() { let mut command = Command::new("cargo"); command .arg("rustdoc") .arg("--") .arg("-D") .arg("rustdoc::broken_intra_doc_links"); let output = command.output().unwrap(); if !output.status.success() { panic!("\n{}", String::from_utf8_lossy(&output.stderr)) } }