Skip to content

Commit

Permalink
refactor!(test): use builder pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb committed Jan 2, 2025
1 parent 82ededa commit f6dfd9a
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 36 deletions.
24 changes: 6 additions & 18 deletions rocks-bin/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ use clap::Args;
use eyre::{OptionExt, Result};
use rocks_lib::{
config::Config,
operations::{ensure_busted, ensure_dependencies, run_tests, TestEnv},
progress::MultiProgress,
operations::{self, TestEnv},
project::Project,
tree::Tree,
};

#[derive(Args)]
Expand All @@ -20,26 +18,16 @@ pub struct Test {
pub async fn test(test: Test, config: Config) -> Result<()> {
let project = Project::current()?
.ok_or_eyre("'rocks test' must be run in a project root, with a 'project.rockspec'")?;
let rockspec = project.rockspec();
let lua_version = match rockspec.lua_version_from_config(&config) {
Ok(lua_version) => Ok(lua_version),
Err(_) => rockspec.test_lua_version().ok_or_eyre("lua version not set! Please provide a version through `--lua-version <ver>` or add it to your rockspec's dependencies"),
}?;
let test_config = config.with_lua_version(lua_version);
let tree = Tree::new(
test_config.tree().clone(),
test_config.lua_version().unwrap().clone(),
)?;
let progress = MultiProgress::new_arc();
// TODO(#204): Only ensure busted if running with busted (e.g. a .busted directory exists)
ensure_busted(&tree, &test_config, progress.clone()).await?;
ensure_dependencies(rockspec, &tree, &test_config, progress).await?;
let test_args = test.test_args.unwrap_or_default();
let test_env = if test.impure {
TestEnv::Impure
} else {
TestEnv::Pure
};
run_tests(project, test_args, test_env, test_config).await?;
operations::Test::new(project, &config)
.args(test_args)
.env(test_env)
.run()
.await?;
Ok(())
}
85 changes: 81 additions & 4 deletions rocks-lib/src/operations/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,86 @@ use thiserror::Error;

use super::{Install, InstallError};

pub struct Test<'a> {
project: Project,
config: &'a Config,
args: Vec<String>,
env: TestEnv,
progress: Option<Arc<Progress<MultiProgress>>>,
}

/// A rocks project test runner, providing fine-grained control
/// over how tests should be run.
impl<'a> Test<'a> {
/// Construct a new test runner.
pub fn new(project: Project, config: &'a Config) -> Self {
Self {
project,
config,
args: Vec::new(),
env: TestEnv::default(),
progress: None,
}
}

/// Pass arguments to the test executable.
pub fn args<I>(self, args: I) -> Self
where
I: IntoIterator<Item = String> + Send,
{
Self {
args: self.args.into_iter().chain(args).collect_vec(),
..self
}
}

/// Pass an argument to the test executable.
pub fn arg(self, arg: String) -> Self {
self.args(std::iter::once(arg))
}

/// Define the environment in which to run the tests.
pub fn env(self, env: TestEnv) -> Self {
Self { env, ..self }
}

/// Pass a `MultiProgress` to this runner.
/// By default, a new one will be created.
pub fn progress(self, progress: Arc<Progress<MultiProgress>>) -> Self {
Self {
progress: Some(progress),
..self
}
}

/// Run the test suite
pub async fn run(self) -> Result<(), RunTestsError> {
let progress = match self.progress {
Some(p) => p,
None => MultiProgress::new_arc(),
};
run_tests(self.project, self.args, self.env, self.config, progress).await
}
}

pub enum TestEnv {
/// An environment that is isolated from `HOME` and `XDG` base directories (default).
Pure,
/// An impure environment in which `HOME` and `XDG` base directories can influence
/// the test results.
Impure,
}

impl Default for TestEnv {
fn default() -> Self {
Self::Pure
}
}

#[derive(Error, Debug)]
pub enum RunTestsError {
#[error(transparent)]
InstallTestDependencies(#[from] InstallTestDependenciesError),
#[error("tests failed!")]
TestFailure,
#[error("failed to execute `{0}`: {1}")]
Expand All @@ -32,23 +105,27 @@ pub enum RunTestsError {
Io(#[from] io::Error),
}

pub async fn run_tests<I>(
async fn run_tests<I>(
project: Project,
test_args: I,
env: TestEnv,
config: Config,
config: &Config,
progress: Arc<Progress<MultiProgress>>,
) -> Result<(), RunTestsError>
where
I: IntoIterator<Item = String> + Send,
{
let rockspec = project.rockspec();
let lua_version = match rockspec.lua_version_from_config(&config) {
let lua_version = match rockspec.lua_version_from_config(config) {
Ok(lua_version) => Ok(lua_version),
Err(_) => rockspec
.test_lua_version()
.ok_or(RunTestsError::LuaVersionUnset),
}?;
let tree = Tree::new(config.tree().clone(), lua_version)?;
// TODO(#204): Only ensure busted if running with busted (e.g. a .busted directory exists)
ensure_busted(&tree, config, progress.clone()).await?;
ensure_dependencies(rockspec, &tree, config, progress).await?;
let tree_root = &tree.root().clone();
let paths = Paths::from_tree(tree)?;
let mut command = Command::new("busted");
Expand Down Expand Up @@ -117,7 +194,7 @@ pub async fn ensure_busted(

/// Ensure dependencies and test dependencies are installed
/// This defaults to the local project tree if cwd is a project root.
pub async fn ensure_dependencies(
async fn ensure_dependencies(
rockspec: &Rockspec,
tree: &Tree,
config: &Config,
Expand Down
16 changes: 2 additions & 14 deletions rocks-lib/tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
use std::path::PathBuf;

use rocks_lib::{
config::ConfigBuilder,
operations::{ensure_busted, run_tests, TestEnv},
progress::MultiProgress,
project::Project,
tree::Tree,
};
use rocks_lib::{config::ConfigBuilder, operations::Test, project::Project};

#[tokio::test]
async fn run_busted_test() {
Expand All @@ -16,11 +10,5 @@ async fn run_busted_test() {
let tree_root = project.root().to_path_buf().join(".rocks");
let _ = std::fs::remove_dir_all(&tree_root);
let config = ConfigBuilder::new().tree(Some(tree_root)).build().unwrap();
let tree = Tree::new(config.tree().clone(), config.lua_version().unwrap().clone()).unwrap();
ensure_busted(&tree, &config, MultiProgress::new_arc())
.await
.unwrap();
run_tests(project, Vec::new(), TestEnv::Pure, config)
.await
.unwrap()
Test::new(project, &config).run().await.unwrap();
}

0 comments on commit f6dfd9a

Please sign in to comment.