forked from kemitix/git-next
test: add some tests
This commit is contained in:
parent
a7e7d12928
commit
ac3e1be261
14 changed files with 206 additions and 47 deletions
|
@ -56,10 +56,10 @@ derive_more = { 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 }
|
||||||
# pretty_assertions = { workspace = true }
|
pretty_assertions = { workspace = true }
|
||||||
# test-log = { workspace = true }
|
# test-log = { workspace = true }
|
||||||
# anyhow = { workspace = true }
|
# anyhow = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User};
|
use crate::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub struct ForgeConfig {
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
pub user: String,
|
pub user: String,
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub repos: HashMap<String, ServerRepoConfig>,
|
pub repos: BTreeMap<String, ServerRepoConfig>,
|
||||||
}
|
}
|
||||||
impl ForgeConfig {
|
impl ForgeConfig {
|
||||||
pub const fn forge_type(&self) -> ForgeType {
|
pub const fn forge_type(&self) -> ForgeType {
|
||||||
|
@ -19,7 +19,7 @@ impl ForgeConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hostname(&self) -> Hostname {
|
pub fn hostname(&self) -> Hostname {
|
||||||
Hostname(self.hostname.clone())
|
Hostname::new(&self.hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user(&self) -> User {
|
pub fn user(&self) -> User {
|
||||||
|
@ -33,6 +33,6 @@ impl ForgeConfig {
|
||||||
pub fn repos(&self) -> impl Iterator<Item = (RepoAlias, &ServerRepoConfig)> {
|
pub fn repos(&self) -> impl Iterator<Item = (RepoAlias, &ServerRepoConfig)> {
|
||||||
self.repos
|
self.repos
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, repo)| (RepoAlias(name.clone()), repo))
|
.map(|(name, repo)| (RepoAlias::new(name), repo))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
/// The hostname of a forge
|
/// The hostname of a forge
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
|
#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
|
||||||
pub struct Hostname(pub String);
|
pub struct Hostname(String);
|
||||||
|
impl Hostname {
|
||||||
|
pub fn new(str: impl Into<String>) -> Self {
|
||||||
|
Self(str.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ mod repo_path;
|
||||||
mod server_repo_config;
|
mod server_repo_config;
|
||||||
mod user;
|
mod user;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
pub use api_token::ApiToken;
|
pub use api_token::ApiToken;
|
||||||
pub use branch_name::BranchName;
|
pub use branch_name::BranchName;
|
||||||
pub use forge_config::ForgeConfig;
|
pub use forge_config::ForgeConfig;
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
/// The alias of a repo
|
/// The alias of a repo
|
||||||
/// This is the alias for the repo within `git-next-server.toml`
|
/// This is the alias for the repo within `git-next-server.toml`
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, derive_more::Display)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, derive_more::Display)]
|
||||||
pub struct RepoAlias(pub String);
|
pub struct RepoAlias(String);
|
||||||
|
impl RepoAlias {
|
||||||
|
pub fn new(str: impl Into<String>) -> Self {
|
||||||
|
Self(str.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
132
crates/config/src/tests.rs
Normal file
132
crates/config/src/tests.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
mod server_repo_config {
|
||||||
|
use assert2::let_assert;
|
||||||
|
|
||||||
|
use crate::{RepoBranches, RepoConfig, RepoConfigSource};
|
||||||
|
|
||||||
|
use super::super::server_repo_config::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_not_return_repo_config_when_no_branches() {
|
||||||
|
let src = ServerRepoConfig {
|
||||||
|
repo: "".to_string(),
|
||||||
|
branch: "".to_string(),
|
||||||
|
gitdir: None,
|
||||||
|
main: None,
|
||||||
|
next: None,
|
||||||
|
dev: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let_assert!(None = src.repo_config());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_repo_config_when_branches() {
|
||||||
|
let src = ServerRepoConfig {
|
||||||
|
repo: "".to_string(),
|
||||||
|
branch: "".to_string(),
|
||||||
|
gitdir: None,
|
||||||
|
main: Some("main".to_string()),
|
||||||
|
next: Some("next".to_string()),
|
||||||
|
dev: Some("dev".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let_assert!(Some(rc) = src.repo_config());
|
||||||
|
assert_eq!(
|
||||||
|
rc,
|
||||||
|
RepoConfig {
|
||||||
|
branches: RepoBranches {
|
||||||
|
main: "main".to_string(),
|
||||||
|
next: "next".to_string(),
|
||||||
|
dev: "dev".to_string()
|
||||||
|
},
|
||||||
|
source: RepoConfigSource::Server
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod repo_config {
|
||||||
|
use crate::{RepoBranches, RepoConfigSource};
|
||||||
|
|
||||||
|
use super::super::repo_config::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_toml() -> TestResult {
|
||||||
|
let toml = r#"
|
||||||
|
[branches]
|
||||||
|
main = "main"
|
||||||
|
next = "next"
|
||||||
|
dev = "dev"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let rc = RepoConfig::load(toml)?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
rc,
|
||||||
|
RepoConfig {
|
||||||
|
branches: RepoBranches {
|
||||||
|
main: "main".to_string(),
|
||||||
|
next: "next".to_string(),
|
||||||
|
dev: "dev".to_string(),
|
||||||
|
},
|
||||||
|
source: RepoConfigSource::Repo // reading from repo is the default
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod forge_config {
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::{ForgeConfig, ForgeType, RepoAlias, ServerRepoConfig};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn should_return_repos() -> TestResult {
|
||||||
|
let forge_type = ForgeType::MockForge;
|
||||||
|
let hostname = "localhost".to_string();
|
||||||
|
let user = "bob".to_string();
|
||||||
|
let token = "alpha".to_string();
|
||||||
|
let red = ServerRepoConfig {
|
||||||
|
repo: "red".to_string(),
|
||||||
|
branch: "main".to_string(),
|
||||||
|
main: None,
|
||||||
|
next: None,
|
||||||
|
dev: None,
|
||||||
|
gitdir: None,
|
||||||
|
};
|
||||||
|
let blue = ServerRepoConfig {
|
||||||
|
repo: "blue".to_string(),
|
||||||
|
branch: "main".to_string(),
|
||||||
|
main: None,
|
||||||
|
next: None,
|
||||||
|
dev: None,
|
||||||
|
gitdir: None,
|
||||||
|
};
|
||||||
|
let mut repos = BTreeMap::new();
|
||||||
|
repos.insert("red".to_string(), red.clone());
|
||||||
|
repos.insert("blue".to_string(), blue.clone());
|
||||||
|
let fc = ForgeConfig {
|
||||||
|
forge_type,
|
||||||
|
hostname,
|
||||||
|
user,
|
||||||
|
token,
|
||||||
|
repos,
|
||||||
|
};
|
||||||
|
|
||||||
|
let returned_repos = fc.repos().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
returned_repos,
|
||||||
|
vec![
|
||||||
|
// alphabetical order by key
|
||||||
|
(RepoAlias::new("blue"), &blue),
|
||||||
|
(RepoAlias::new("red"), &red),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ pub fn find_default_remote(
|
||||||
let path = path.strip_suffix(".git").map_or(path, |path| path);
|
let path = path.strip_suffix(".git").map_or(path, |path| path);
|
||||||
info!(%host, %path, "found");
|
info!(%host, %path, "found");
|
||||||
Ok(GitRemote::new(
|
Ok(GitRemote::new(
|
||||||
Hostname(host.to_string()),
|
Hostname::new(host),
|
||||||
RepoPath(path.to_string()),
|
RepoPath(path.to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ fn validate_commit_message(message: &git::commit::Message) -> Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_next_commit_on_dev(
|
pub fn find_next_commit_on_dev(
|
||||||
next: git::Commit,
|
next: git::Commit,
|
||||||
dev_commit_history: Vec<git::Commit>,
|
dev_commit_history: Vec<git::Commit>,
|
||||||
) -> Option<git::Commit> {
|
) -> Option<git::Commit> {
|
||||||
|
@ -100,22 +100,3 @@ pub async fn advance_main(
|
||||||
RepoConfigSource::Server => addr.do_send(ValidateRepo { message_token }),
|
RepoConfigSource::Server => addr.do_send(ValidateRepo { message_token }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn test_find_next_commit_on_dev() {
|
|
||||||
let next = git::Commit::new("current-next", "foo");
|
|
||||||
let expected = git::Commit::new("dev-next", "next-should-go-here");
|
|
||||||
let dev_commit_history = vec![
|
|
||||||
git::Commit::new("dev", "future"),
|
|
||||||
expected.clone(),
|
|
||||||
next.clone(),
|
|
||||||
git::Commit::new("current-main", "history"),
|
|
||||||
];
|
|
||||||
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
|
||||||
assert_eq!(next_commit, Some(expected));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ mod config;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod webhook;
|
pub mod webhook;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
use git_next_config::{ForgeType, RepoConfig};
|
use git_next_config::{ForgeType, RepoConfig};
|
||||||
use git_next_git::{self as git, Generation, RepoDetails};
|
use git_next_git::{self as git, Generation, RepoDetails};
|
||||||
|
|
31
crates/server/src/actors/repo/tests.rs
Normal file
31
crates/server/src/actors/repo/tests.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
use super::*;
|
||||||
|
mod branch {
|
||||||
|
use super::super::branch::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_find_next_commit_on_dev() {
|
||||||
|
let next = git::Commit::new("current-next", "foo");
|
||||||
|
let expected = git::Commit::new("dev-next", "next-should-go-here");
|
||||||
|
let dev_commit_history = vec![
|
||||||
|
git::Commit::new("dev", "future"),
|
||||||
|
expected.clone(),
|
||||||
|
next.clone(),
|
||||||
|
git::Commit::new("current-main", "history"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
||||||
|
|
||||||
|
assert_eq!(next_commit, Some(expected), "Found the wrong commit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod webhook {
|
||||||
|
use super::super::webhook::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_split_ref() {
|
||||||
|
assert_eq!(split_ref("refs/heads/next"), ("refs/heads/", "next"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -285,7 +285,7 @@ impl Push {
|
||||||
warn!(r#ref = self.reference, "Unexpected ref");
|
warn!(r#ref = self.reference, "Unexpected ref");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (_, branch) = self.reference.split_at(11);
|
let (_, branch) = split_ref(&self.reference);
|
||||||
let branch = BranchName::new(branch);
|
let branch = BranchName::new(branch);
|
||||||
if branch == repo_branches.main() {
|
if branch == repo_branches.main() {
|
||||||
return Some(Branch::Main);
|
return Some(Branch::Main);
|
||||||
|
@ -299,11 +299,16 @@ impl Push {
|
||||||
warn!(%branch, "Unexpected branch");
|
warn!(%branch, "Unexpected branch");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&self) -> git::Commit {
|
pub fn commit(&self) -> git::Commit {
|
||||||
git::Commit::new(&self.after, &self.head_commit.message)
|
git::Commit::new(&self.after, &self.head_commit.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_ref(reference: &str) -> (&str, &str) {
|
||||||
|
reference.split_at(11)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Branch {
|
enum Branch {
|
||||||
Main,
|
Main,
|
||||||
|
@ -315,11 +320,3 @@ enum Branch {
|
||||||
struct HeadCommit {
|
struct HeadCommit {
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn splt_ref() {
|
|
||||||
assert_eq!("refs/heads/next".split_at(11), ("refs/heads/", "next"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl Handler<WebhookMessage> for WebhookRouter {
|
||||||
|
|
||||||
fn handle(&mut self, msg: WebhookMessage, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: WebhookMessage, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
let _gaurd = self.span.enter();
|
let _gaurd = self.span.enter();
|
||||||
let repo_alias = RepoAlias(msg.path().clone());
|
let repo_alias = RepoAlias::new(msg.path());
|
||||||
debug!(repo = %repo_alias, "Router...");
|
debug!(repo = %repo_alias, "Router...");
|
||||||
if let Some(recipient) = self.repos.get(&repo_alias) {
|
if let Some(recipient) = self.repos.get(&repo_alias) {
|
||||||
info!(repo = %repo_alias, "Sending to Recipient");
|
info!(repo = %repo_alias, "Sending to Recipient");
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
use git_next_config::{
|
use git_next_config::{
|
||||||
ForgeType, GitDir, Hostname, RepoBranches, RepoConfig, RepoConfigSource, RepoPath,
|
ForgeType, GitDir, Hostname, RepoBranches, RepoConfig, RepoConfigSource, RepoPath,
|
||||||
|
@ -68,7 +70,7 @@ fn load_should_parse_server_config() -> Result<()> {
|
||||||
hostname: "git.example.net".to_string(),
|
hostname: "git.example.net".to_string(),
|
||||||
user: "Bob".to_string(),
|
user: "Bob".to_string(),
|
||||||
token: "API-Token".to_string(),
|
token: "API-Token".to_string(),
|
||||||
repos: HashMap::from([
|
repos: BTreeMap::from([
|
||||||
(
|
(
|
||||||
"hello".to_string(),
|
"hello".to_string(),
|
||||||
ServerRepoConfig {
|
ServerRepoConfig {
|
||||||
|
@ -176,7 +178,7 @@ fn repo_details_find_default_push_remote_finds_correct_remote() -> Result<()> {
|
||||||
None,
|
None,
|
||||||
GitDir::new(root), // Server GitDir - should be ignored
|
GitDir::new(root), // Server GitDir - should be ignored
|
||||||
);
|
);
|
||||||
repo_details.forge.hostname = Hostname("git.kemitix.net".to_string());
|
repo_details.forge.hostname = Hostname::new("git.kemitix.net");
|
||||||
repo_details.repo_path = RepoPath("kemitix/git-next".to_string());
|
repo_details.repo_path = RepoPath("kemitix/git-next".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = Repository::open(gitdir)?;
|
let repository = Repository::open(gitdir)?;
|
||||||
|
@ -202,7 +204,7 @@ fn gitdir_validate_should_pass_a_valid_git_repo() -> Result<()> {
|
||||||
None,
|
None,
|
||||||
GitDir::new(root), // Server GitDir - should be ignored
|
GitDir::new(root), // Server GitDir - should be ignored
|
||||||
);
|
);
|
||||||
repo_details.forge.hostname = Hostname("git.kemitix.net".to_string());
|
repo_details.forge.hostname = Hostname::new("git.kemitix.net");
|
||||||
repo_details.repo_path = RepoPath("kemitix/git-next".to_string());
|
repo_details.repo_path = RepoPath("kemitix/git-next".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = Repository::open(gitdir)?;
|
let repository = Repository::open(gitdir)?;
|
||||||
|
@ -222,7 +224,7 @@ fn gitdir_validate_should_fail_a_git_repo_with_wrong_remote() -> Result<()> {
|
||||||
None,
|
None,
|
||||||
GitDir::new(root), // Server GitDir - should be ignored
|
GitDir::new(root), // Server GitDir - should be ignored
|
||||||
);
|
);
|
||||||
repo_details.forge.hostname = Hostname("localhost".to_string());
|
repo_details.forge.hostname = Hostname::new("localhost");
|
||||||
repo_details.repo_path = RepoPath("hello/world".to_string());
|
repo_details.repo_path = RepoPath("hello/world".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = Repository::open(gitdir)?;
|
let repository = Repository::open(gitdir)?;
|
||||||
|
@ -233,7 +235,7 @@ fn gitdir_validate_should_fail_a_git_repo_with_wrong_remote() -> Result<()> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn git_remote_to_string_is_as_expected() {
|
fn git_remote_to_string_is_as_expected() {
|
||||||
let git_remote = GitRemote::new(Hostname("foo".to_string()), RepoPath("bar".to_string()));
|
let git_remote = GitRemote::new(Hostname::new("foo"), RepoPath("bar".to_string()));
|
||||||
let as_string = git_remote.to_string();
|
let as_string = git_remote.to_string();
|
||||||
|
|
||||||
assert_eq!(as_string, "foo:bar");
|
assert_eq!(as_string, "foo:bar");
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn user(n: u32) -> User {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hostname(n: u32) -> Hostname {
|
pub fn hostname(n: u32) -> Hostname {
|
||||||
Hostname(format!("hostname-{}", n))
|
Hostname::new(format!("hostname-{}", n))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forge_name(n: u32) -> ForgeName {
|
pub fn forge_name(n: u32) -> ForgeName {
|
||||||
|
@ -57,7 +57,7 @@ pub fn repo_path(n: u32) -> RepoPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repo_alias(n: u32) -> RepoAlias {
|
pub fn repo_alias(n: u32) -> RepoAlias {
|
||||||
RepoAlias(format!("repo-alias-{}", n))
|
RepoAlias::new(format!("repo-alias-{}", n))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repo_config(n: u32, source: RepoConfigSource) -> RepoConfig {
|
pub fn repo_config(n: u32, source: RepoConfigSource) -> RepoConfig {
|
||||||
|
|
Loading…
Reference in a new issue