tests: make TestRepository from git crate available to other crates

This commit is contained in:
Paul Campbell 2024-06-14 09:05:11 +01:00
parent 2acc43d3d6
commit be78597331
4 changed files with 51 additions and 44 deletions

View file

@ -50,7 +50,7 @@ thiserror = { workspace = true }
actix = { workspace = true } actix = { workspace = true }
# actix-rt = { workspace = true } # actix-rt = { workspace = true }
# tokio = { workspace = true } # tokio = { workspace = true }
#
[dev-dependencies] [dev-dependencies]
# Testing # Testing
assert2 = { workspace = true } assert2 = { workspace = true }

View file

@ -1,9 +1,13 @@
// //
#[cfg(test)] #[cfg(test)]
mod mock; mod mock;
#[cfg(test)]
pub use mock::MockRepository;
#[cfg(test)]
pub use open::MockOpenRepository;
mod open; mod open;
mod real; mod real;
#[cfg(test)]
mod test; mod test;
#[cfg(test)] #[cfg(test)]
@ -12,21 +16,15 @@ mod tests;
use git_next_config as config; use git_next_config as config;
use git_next_config::GitDir; use git_next_config::GitDir;
#[cfg(test)]
pub use mock::MockRepository;
#[cfg(test)]
pub use open::otest::OnFetch; pub use open::otest::OnFetch;
#[cfg(test)]
pub use open::otest::OnPush; pub use open::otest::OnPush;
#[cfg(test)]
pub use open::MockOpenRepository;
pub use open::OpenRepository; pub use open::OpenRepository;
pub use open::OpenRepositoryLike; pub use open::OpenRepositoryLike;
pub use open::RealOpenRepository; pub use open::RealOpenRepository;
pub use real::RealRepository; pub use real::RealRepository;
use tracing::info; use tracing::info;
#[cfg(test)]
use crate::repository::test::TestRepository; use crate::repository::test::TestRepository;
use crate::validation::repo::validate_repo; use crate::validation::repo::validate_repo;
@ -39,7 +37,6 @@ pub enum Repository {
Real, Real,
#[cfg(test)] #[cfg(test)]
Mock(MockRepository), Mock(MockRepository),
#[cfg(test)]
Test(TestRepository), Test(TestRepository),
} }
@ -52,7 +49,6 @@ pub fn mock() -> MockRepository {
MockRepository::new() MockRepository::new()
} }
#[cfg(test)]
pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository { pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository {
TestRepository::new(false, fs, vec![], vec![]) TestRepository::new(false, fs, vec![], vec![])
} }
@ -92,10 +88,10 @@ impl std::ops::Deref for Repository {
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
Self::Real => &real::RealRepository, Self::Real => &real::RealRepository,
Self::Test(test_repository) => test_repository,
#[cfg(test)] #[cfg(test)]
Self::Mock(mock_repository) => mock_repository, Self::Mock(mock_repository) => mock_repository,
#[cfg(test)]
Self::Test(test_repository) => test_repository,
} }
} }
} }

View file

@ -5,7 +5,6 @@ mod tests;
pub mod oreal; pub mod oreal;
#[cfg(test)]
pub mod otest; pub mod otest;
#[cfg(test)] #[cfg(test)]
@ -22,7 +21,6 @@ use git_next_config as config;
#[cfg(test)] #[cfg(test)]
pub use omock::MockOpenRepository; pub use omock::MockOpenRepository;
pub use oreal::RealOpenRepository; pub use oreal::RealOpenRepository;
#[cfg(test)]
pub use otest::TestOpenRepository; pub use otest::TestOpenRepository;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -31,6 +29,15 @@ pub enum OpenRepository {
/// ///
/// This variant is the normal implementation for use in production code. /// This variant is the normal implementation for use in production code.
Real(RealOpenRepository), Real(RealOpenRepository),
/// A real git repository, but with preprogrammed responses to network access.
///
/// This variant is for use only in testing. Requests to methods
/// that would require network access, such as to the git remote
/// server will result in an error, unless a predefined change
/// has been scheduled for that request.
Test(TestOpenRepository),
/// A fake git repository. /// A fake git repository.
/// ///
/// This variant has no on-disk presense, and only fakes some of /// This variant has no on-disk presense, and only fakes some of
@ -39,14 +46,6 @@ pub enum OpenRepository {
/// that instead. /// that instead.
#[cfg(test)] #[cfg(test)]
Mock(git::repository::MockOpenRepository), // TODO: (#38) contain a mock model of a repo Mock(git::repository::MockOpenRepository), // TODO: (#38) contain a mock model of a repo
/// A real git repository, but with preprogrammed responses to network access.
///
/// This variant is for use only in testing. Requests to methods
/// that would require network access, such as to the git remote
/// server will result in an error, unless a predefined change
/// has been scheduled for that request.
#[cfg(test)]
Test(TestOpenRepository),
} }
pub fn real(gix_repo: gix::Repository) -> OpenRepository { pub fn real(gix_repo: gix::Repository) -> OpenRepository {
@ -56,7 +55,6 @@ pub fn real(gix_repo: gix::Repository) -> OpenRepository {
} }
#[cfg(not(tarpaulin_include))] // don't test mocks #[cfg(not(tarpaulin_include))] // don't test mocks
#[cfg(test)]
pub fn test( pub fn test(
gitdir: &config::GitDir, gitdir: &config::GitDir,
fs: kxio::fs::FileSystem, fs: kxio::fs::FileSystem,
@ -67,7 +65,6 @@ pub fn test(
} }
#[cfg(not(tarpaulin_include))] // don't test mocks #[cfg(not(tarpaulin_include))] // don't test mocks
#[cfg(test)]
pub fn test_bare( pub fn test_bare(
gitdir: &config::GitDir, gitdir: &config::GitDir,
fs: kxio::fs::FileSystem, fs: kxio::fs::FileSystem,
@ -111,10 +108,10 @@ impl std::ops::Deref for OpenRepository {
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
Self::Real(real) => real, Self::Real(real) => real,
Self::Test(test) => test,
#[cfg(test)] #[cfg(test)]
Self::Mock(mock) => mock, Self::Mock(mock) => mock,
#[cfg(test)]
Self::Test(test) => test,
} }
} }
} }

View file

@ -1,16 +1,13 @@
// //
use crate as git; use crate as git;
use derive_more::Constructor; use derive_more::{Constructor, Deref};
use git_next_config as config; use git_next_config as config;
use std::{ use std::{
cell::Cell,
path::Path, path::Path,
sync::{Arc, Mutex}, sync::{Arc, Mutex, RwLock},
}; };
use assert2::let_assert;
pub type OnFetchFn = pub type OnFetchFn =
fn(&config::RepoBranches, &config::GitDir, &kxio::fs::FileSystem) -> git::fetch::Result<()>; fn(&config::RepoBranches, &config::GitDir, &kxio::fs::FileSystem) -> git::fetch::Result<()>;
#[derive(Clone, Debug, Constructor)] #[derive(Clone, Debug, Constructor)]
@ -65,9 +62,9 @@ impl OnPush {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TestOpenRepository { pub struct TestOpenRepository {
on_fetch: Vec<OnFetch>, on_fetch: Vec<OnFetch>,
fetch_counter: Cell<usize>, fetch_counter: Arc<RwLock<usize>>,
on_push: Vec<OnPush>, on_push: Vec<OnPush>,
push_counter: Cell<usize>, push_counter: Arc<RwLock<usize>>,
real: git::repository::RealOpenRepository, real: git::repository::RealOpenRepository,
} }
impl git::repository::OpenRepositoryLike for TestOpenRepository { impl git::repository::OpenRepositoryLike for TestOpenRepository {
@ -80,9 +77,16 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
} }
fn fetch(&self) -> Result<(), git::fetch::Error> { fn fetch(&self) -> Result<(), git::fetch::Error> {
let i = self.fetch_counter.get(); let i: usize = *self
.fetch_counter
.read()
.map_err(|_| git::fetch::Error::Lock)?
.deref();
eprintln!("Fetch: {i}"); eprintln!("Fetch: {i}");
self.fetch_counter.set(i + 1); self.fetch_counter
.write()
.map_err(|_| git::fetch::Error::Lock)
.map(|mut c| *c += 1)?;
self.on_fetch.get(i).map(|f| f.invoke()).unwrap_or_else(|| { self.on_fetch.get(i).map(|f| f.invoke()).unwrap_or_else(|| {
unimplemented!("Unexpected fetch"); unimplemented!("Unexpected fetch");
}) })
@ -95,8 +99,16 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
to_commit: &git::GitRef, to_commit: &git::GitRef,
force: &git::push::Force, force: &git::push::Force,
) -> git::push::Result<()> { ) -> git::push::Result<()> {
let i = self.push_counter.get(); let i: usize = *self
self.push_counter.set(i + 1); .push_counter
.read()
.map_err(|_| git::fetch::Error::Lock)?
.deref();
eprintln!("Push: {i}");
self.push_counter
.write()
.map_err(|_| git::fetch::Error::Lock)
.map(|mut c| *c += 1)?;
self.on_push self.on_push
.get(i) .get(i)
.map(|f| f.invoke(repo_details, branch_name, to_commit, force)) .map(|f| f.invoke(repo_details, branch_name, to_commit, force))
@ -129,13 +141,14 @@ impl TestOpenRepository {
on_push: Vec<OnPush>, on_push: Vec<OnPush>,
) -> Self { ) -> Self {
let pathbuf = fs.base().join(gitdir.to_path_buf()); let pathbuf = fs.base().join(gitdir.to_path_buf());
let_assert!(Ok(gix) = gix::init(pathbuf), "git init"); #[allow(clippy::expect_used)]
let gix = gix::init(pathbuf).expect("git init");
Self::write_origin(gitdir, &fs); Self::write_origin(gitdir, &fs);
Self { Self {
on_fetch, on_fetch,
fetch_counter: Cell::new(0), fetch_counter: Arc::new(RwLock::new(0)),
on_push, on_push,
push_counter: Cell::new(0), push_counter: Arc::new(RwLock::new(0)),
real: git::repository::RealOpenRepository::new(Arc::new(Mutex::new(gix))), real: git::repository::RealOpenRepository::new(Arc::new(Mutex::new(gix))),
} }
} }
@ -146,13 +159,14 @@ impl TestOpenRepository {
on_push: Vec<OnPush>, on_push: Vec<OnPush>,
) -> Self { ) -> Self {
let pathbuf = fs.base().join(gitdir.to_path_buf()); let pathbuf = fs.base().join(gitdir.to_path_buf());
let_assert!(Ok(gix) = gix::init_bare(pathbuf), "git init bare"); #[allow(clippy::expect_used)]
let gix = gix::init_bare(pathbuf).expect("git init bare");
Self::write_origin(gitdir, &fs); Self::write_origin(gitdir, &fs);
Self { Self {
on_fetch, on_fetch,
fetch_counter: Cell::new(0), fetch_counter: Arc::new(RwLock::new(0)),
on_push, on_push,
push_counter: Cell::new(0), push_counter: Arc::new(RwLock::new(0)),
real: git::repository::RealOpenRepository::new(Arc::new(Mutex::new(gix))), real: git::repository::RealOpenRepository::new(Arc::new(Mutex::new(gix))),
} }
} }