Skip to content

Commit

Permalink
Add rustdoc test support and change logger output
Browse files Browse the repository at this point in the history
We add the missing component for tests here which is doctests! We now
have rustdoc integrated with it's own module like rustc. This commit
does a few things in particular:

- Add support to run rustdoc tests
- Add a doctest to Rustc for testing purposes
- Changes the logging output to be more consistent with cargo's minus
  coloring
- Removes some logging from building test binaries so as not to be
  confusing as to what's going on which is building test binaries, not
  the freight library per se
  • Loading branch information
mgattozzi committed Aug 3, 2023
1 parent edb6326 commit 530d3ad
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .gitignore
@@ -1,2 +1,9 @@
/target
.direnv


# Added by cargo
#
# already existing elements were commented out

#/target
52 changes: 29 additions & 23 deletions src/lib.rs
@@ -1,10 +1,12 @@
mod config;
mod logger;
pub mod rustc;
pub mod rustdoc;

use crate::rustc::CrateType;
use crate::rustc::Edition;
use crate::rustc::Rustc;
use crate::rustdoc::RustDoc;
use config::Manifest;
use logger::Logger;
use std::env;
Expand All @@ -23,7 +25,7 @@ fn lib_compile(
lib_path: &Path,
out_dir: &Path,
) -> Result<()> {
logger.compiling_crate(&manifest.crate_name);
logger.compiling_crate(&manifest.crate_name)?;
Rustc::builder()
.edition(manifest.edition)
.crate_type(CrateType::Lib)
Expand All @@ -32,7 +34,6 @@ fn lib_compile(
.lib_dir(out_dir.clone())
.done()
.run(lib_path.to_str().unwrap())?;
logger.done_compiling();
Ok(())
}

Expand All @@ -43,7 +44,7 @@ fn bin_compile(
out_dir: &Path,
externs: &[&str],
) -> Result<()> {
logger.compiling_bin(&manifest.crate_name);
logger.compiling_bin(&manifest.crate_name)?;
let mut builder = Rustc::builder()
.edition(manifest.edition)
.crate_type(CrateType::Bin)
Expand All @@ -56,18 +57,15 @@ fn bin_compile(
}

builder.done().run(bin_path.to_str().unwrap())?;
logger.done_compiling();
Ok(())
}

fn test_compile(
logger: &mut Logger,
manifest: &Manifest,
bin_path: &Path,
out_dir: &Path,
externs: &[&str],
) -> Result<()> {
logger.compiling_bin(&manifest.crate_name);
let mut builder = Rustc::builder()
.edition(manifest.edition)
.crate_type(CrateType::Bin)
Expand All @@ -85,7 +83,6 @@ fn test_compile(
}

builder.done().run(bin_path.to_str().unwrap())?;
logger.done_compiling();
Ok(())
}

Expand Down Expand Up @@ -136,42 +133,51 @@ pub fn build_tests() -> Result<()> {

match (lib_rs.exists(), main_rs.exists()) {
(true, true) => {
test_compile(&mut logger, &manifest, &lib_rs, &target_tests, &[])?;
test_compile(&manifest, &lib_rs, &target_tests, &[])?;
lib_compile(&mut logger, &manifest, &lib_rs, &target_tests)?;
test_compile(
&mut logger,
&manifest,
&main_rs,
&target_tests,
&[&manifest.crate_name],
)?;
test_compile(&manifest, &main_rs, &target_tests, &[&manifest.crate_name])?;
}
(true, false) => {
test_compile(&mut logger, &manifest, &lib_rs, &target_tests, &[])?;
test_compile(&manifest, &lib_rs, &target_tests, &[])?;
}
(false, true) => {
test_compile(&mut logger, &manifest, &main_rs, &target_tests, &[])?;
test_compile(&manifest, &main_rs, &target_tests, &[])?;
}
(false, false) => return Err("There is nothing to compile".into()),
}

logger.done_compiling()?;
Ok(())
}

pub fn run_tests(test_args: Vec<String>) -> Result<()> {
for item in root_dir()?
.join("target")
.join("debug")
.join("tests")
.read_dir()?
{
let mut logger = Logger::new();
let root = root_dir()?;
let manifest = Manifest::parse_from_file(root.join("Freight.toml"))?;
for item in root.join("target").join("debug").join("tests").read_dir()? {
let item = item?;
let path = item.path();
let is_test = path.extension().is_none();
if is_test {
let file_name = path.file_name().unwrap().to_str().unwrap();
if file_name == "test_freight_main" {
logger.main_unit_test()?;
} else if file_name == "test_freight_lib" {
logger.lib_unit_test()?;
}
Command::new(path).args(&test_args).spawn()?.wait()?;
}
}
let lib = root.join("src").join("lib.rs");
if lib.exists() {
logger.doc_test(&manifest.crate_name)?;
RustDoc::new(
manifest.edition,
manifest.crate_name,
root.join("target").join("debug"),
)
.test(lib)?;
}
Ok(())
}

Expand Down
47 changes: 37 additions & 10 deletions src/logger.rs
@@ -1,3 +1,4 @@
use crate::Result;
use std::io;
use std::io::Write;

Expand All @@ -11,17 +12,43 @@ impl Logger {
out: io::stdout().lock(),
}
}
pub fn compiling_crate(&mut self, crate_name: &str) {
let _ = self
.out
.write_all(format!("Compiling crate {crate_name}...").as_bytes());
pub fn compiling_crate(&mut self, crate_name: &str) -> Result<()> {
self.out
.write_all(format!(" Compiling lib {crate_name}\n").as_bytes())?;
self.out.flush()?;
Ok(())
}
pub fn compiling_bin(&mut self, crate_name: &str) {
let _ = self
.out
.write_all(format!("Compiling bin {crate_name}...").as_bytes());
pub fn compiling_bin(&mut self, crate_name: &str) -> Result<()> {
self.out
.write_all(format!(" Compiling bin {crate_name}\n").as_bytes())?;
self.out.flush()?;
Ok(())
}
pub fn done_compiling(&mut self) {
let _ = self.out.write_all(b"Done\n");
pub fn done_compiling(&mut self) -> Result<()> {
self.out.write_all(b" Finished dev\n")?;
self.out.flush()?;
Ok(())
}
pub fn main_unit_test(&mut self) -> Result<()> {
self.unit_test("src/main.rs")?;
Ok(())
}
pub fn lib_unit_test(&mut self) -> Result<()> {
self.unit_test("src/lib.rs")?;
Ok(())
}
fn unit_test(&mut self, file: &str) -> Result<()> {
self.out.write_all(b" Running unittests ")?;
self.out.write_all(file.as_bytes())?;
self.out.write_all(b"\n")?;
self.out.flush()?;
Ok(())
}
pub fn doc_test(&mut self, crate_name: &str) -> Result<()> {
self.out.write_all(b" Doc-tests ")?;
self.out.write_all(crate_name.as_bytes())?;
self.out.write_all(b"\n")?;
self.out.flush()?;
Ok(())
}
}
16 changes: 16 additions & 0 deletions src/rustc.rs
Expand Up @@ -18,6 +18,22 @@ pub struct Rustc {
}

impl Rustc {
/// Create a builder type to build up commands to then invoke rustc with.
/// ```
/// # use std::error::Error;
/// # use freight::rustc::Rustc;
/// # use freight::rustc::Edition;
/// # use freight::rustc::CrateType;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let builder = Rustc::builder()
/// .edition(Edition::E2021)
/// .crate_type(CrateType::Bin)
/// .crate_name("freight")
/// .out_dir(".")
/// .lib_dir(".");
/// # Ok(())
/// # }
/// ```
pub fn builder() -> RustcBuilder {
RustcBuilder {
..Default::default()
Expand Down
40 changes: 40 additions & 0 deletions src/rustdoc.rs
@@ -0,0 +1,40 @@
use super::Result;
use crate::rustc::Edition;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

pub struct RustDoc {
edition: Edition,
crate_name: String,
lib_path: PathBuf,
}

impl RustDoc {
pub fn new(
edition: Edition,
crate_name: impl Into<String>,
lib_path: impl Into<PathBuf>,
) -> Self {
Self {
edition,
crate_name: crate_name.into(),
lib_path: lib_path.into(),
}
}
pub fn test(&self, path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref();
Command::new("rustdoc")
.arg("--test")
.arg(path)
.arg("--crate-name")
.arg(&self.crate_name)
.arg("--edition")
.arg(self.edition.to_string())
.arg("-L")
.arg(&self.lib_path)
.spawn()?
.wait()?;
Ok(())
}
}

0 comments on commit 530d3ad

Please sign in to comment.