tests: add more tests to config crate
All checks were successful
Rust / build (push) Successful in 1m5s
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
ci/woodpecker/cron/cron-docker-builder Pipeline was successful
ci/woodpecker/cron/push-next Pipeline was successful
ci/woodpecker/cron/tag-created Pipeline was successful

This commit is contained in:
Paul Campbell 2024-06-01 11:15:04 +01:00
parent 9462957c5e
commit 1010eaec64
5 changed files with 269 additions and 74 deletions

View file

@ -93,3 +93,4 @@ tokio = { version = "1.37" }
# Testing
assert2 = "0.3"
pretty_assertions = "1.4"

View file

@ -56,6 +56,7 @@ actix = { workspace = true }
[dev-dependencies]
# # Testing
assert2 = { workspace = true }
pretty_assertions = { workspace = true }
[lints.clippy]
nursery = { level = "warn", priority = -1 }

View file

@ -459,19 +459,103 @@ mod server {
mod load {
//
use std::collections::{BTreeMap, HashMap};
use std::{
collections::{BTreeMap, HashMap},
net::SocketAddr,
str::FromStr as _,
};
use assert2::let_assert;
use pretty_assertions::assert_eq;
use crate::{
server::{Http, ServerConfig, ServerStorage, Webhook},
tests::TestResult,
ForgeConfig, ForgeType, RepoBranches, RepoConfig, RepoConfigSource, ServerRepoConfig,
ForgeAlias, ForgeConfig, ForgeType, RepoAlias, RepoBranches, RepoConfig,
RepoConfigSource, ServerRepoConfig,
};
#[test]
fn load_should_parse_server_config() -> TestResult {
let fs = kxio::fs::temp()?;
given_server_config(&fs)?;
let_assert!(Ok(config) = ServerConfig::load(&fs));
let expected = ServerConfig::new(
Http::new("0.0.0.0".to_string(), 8080),
expected_webhook(),
expected_storage(),
HashMap::from([("default".to_string(), expected_forge_config())]),
);
assert_eq!(config, expected, "ServerConfig");
if let Some(forge) = config.forge.get("world") {
if let Some(repo) = forge.get_repo("sam") {
let repo_config = repo.repo_config();
let expected = Some(RepoConfig::new(
RepoBranches::new(
"master".to_string(),
"upcoming".to_string(),
"sam-dev".to_string(),
),
RepoConfigSource::Server,
));
assert_eq!(repo_config, expected, "RepoConfig");
}
}
Ok(())
}
#[test]
fn should_return_forges() -> TestResult {
let fs = kxio::fs::temp()?;
given_server_config(&fs)?;
let config = ServerConfig::load(&fs)?;
let forges = config.forges().collect::<Vec<_>>();
let forge_config = expected_forge_config();
let expected = vec![(ForgeAlias::new("default".to_string()), &forge_config)];
assert_eq!(forges, expected);
Ok(())
}
#[test]
fn should_return_storage() -> TestResult {
let fs = kxio::fs::temp()?;
given_server_config(&fs)?;
let config = ServerConfig::load(&fs)?;
let storage = config.storage();
assert_eq!(storage, &expected_storage());
assert_eq!(storage.path(), std::path::Path::new("/opt/git-next/data"));
Ok(())
}
#[test]
fn should_return_webhook() -> TestResult {
let fs = kxio::fs::temp()?;
given_server_config(&fs)?;
let config = ServerConfig::load(&fs)?;
let webhook = config.webhook();
assert_eq!(webhook, &expected_webhook());
assert_eq!(
webhook
.url(&ForgeAlias::new("a".to_string()), &RepoAlias::new("b"))
.as_ref(),
"http://localhost:9909/a/b"
);
Ok(())
}
#[test]
fn should_return_http() -> TestResult {
let fs = kxio::fs::temp()?;
given_server_config(&fs)?;
let config = ServerConfig::load(&fs)?;
let_assert!(Ok(http) = config.http());
assert_eq!(http, expected_http());
Ok(())
}
fn given_server_config(fs: &kxio::fs::FileSystem) -> Result<(), kxio::fs::Error> {
fs.file_write(
&fs.base().join("git-next-server.toml"),
r#"
@ -480,7 +564,7 @@ mod server {
port = 8080
[webhook]
url = "http://localhost:9909/webhook"
url = "http://localhost:9909"
[storage]
path = "/opt/git-next/data"
@ -502,76 +586,186 @@ mod server {
next = "upcoming"
dev = "sam-dev"
"#,
)
?;
let_assert!(Ok(config) = ServerConfig::load(&fs));
let expected = ServerConfig::new(
Http::new("0.0.0.0".to_string(), 8080),
Webhook::new("http://localhost:9909/webhook".to_string()),
ServerStorage::new("/opt/git-next/data".into()),
HashMap::from([(
"default".to_string(),
ForgeConfig::new(
ForgeType::MockForge,
"git.example.net".to_string(),
"Bob".to_string(),
"API-Token".to_string(),
BTreeMap::from([
(
"hello".to_string(),
ServerRepoConfig::new(
"user/hello".to_string(),
"main".to_string(),
Some("/opt/git/user/hello.git".into()),
None,
None,
None,
),
),
(
"world".to_string(),
ServerRepoConfig::new(
"user/world".to_string(),
"master".to_string(),
None,
Some("main".to_string()),
Some("next".to_string()),
Some("dev".to_string()),
),
),
(
"sam".to_string(),
ServerRepoConfig::new(
"user/sam".to_string(),
"main".to_string(),
None,
Some("master".to_string()),
Some("upcoming".to_string()),
Some("sam-dev".to_string()),
),
),
]),
),
)]),
);
assert_eq!(config, expected, "ServerConfig");
)
}
if let Some(forge) = config.forge.get("world") {
if let Some(repo) = forge.get_repo("sam") {
let repo_config = repo.repo_config();
let expected = Some(RepoConfig::new(
RepoBranches::new(
"master".to_string(),
"upcoming".to_string(),
"sam-dev".to_string(),
fn expected_storage() -> ServerStorage {
ServerStorage::new("/opt/git-next/data".into())
}
fn expected_webhook() -> Webhook {
Webhook::new("http://localhost:9909".to_string())
}
fn expected_http() -> SocketAddr {
SocketAddr::from_str("0.0.0.0:8080").unwrap_or_else(|_| panic!())
}
fn expected_forge_config() -> ForgeConfig {
ForgeConfig::new(
ForgeType::MockForge,
"git.example.net".to_string(),
"Bob".to_string(),
"API-Token".to_string(),
BTreeMap::from([
(
"hello".to_string(),
ServerRepoConfig::new(
"user/hello".to_string(),
"main".to_string(),
Some("/opt/git/user/hello.git".into()),
None,
None,
None,
),
RepoConfigSource::Server,
));
assert_eq!(repo_config, expected, "RepoConfig");
}
}
Ok(())
),
(
"world".to_string(),
ServerRepoConfig::new(
"user/world".to_string(),
"master".to_string(),
None,
Some("main".to_string()),
Some("next".to_string()),
Some("dev".to_string()),
),
),
(
"sam".to_string(),
ServerRepoConfig::new(
"user/sam".to_string(),
"main".to_string(),
None,
Some("master".to_string()),
Some("upcoming".to_string()),
Some("sam-dev".to_string()),
),
),
]),
)
}
}
}
mod registered_webhook {
use crate::{RegisteredWebhook, WebhookAuth, WebhookId};
#[test]
fn should_return_id() {
let id = WebhookId::new("a".to_string());
let auth = WebhookAuth::generate();
let rw = RegisteredWebhook::new(id.clone(), auth);
assert_eq!(rw.id(), &id);
}
#[test]
fn should_return_auth() {
let id = WebhookId::new("a".to_string());
let auth = WebhookAuth::generate();
let rw = RegisteredWebhook::new(id, auth.clone());
assert_eq!(rw.auth(), &auth);
}
}
mod webhook {
mod message {
use crate::{webhook::message::Body, ForgeAlias, RepoAlias, WebhookMessage};
#[test]
fn should_return_forge_alias() {
let message = given_message();
assert_eq!(message.forge_alias(), &expected_forge_alias());
}
#[test]
fn should_return_repo_alias() {
let message = given_message();
assert_eq!(message.repo_alias(), &expected_repo_alias());
}
#[test]
fn should_return_body() {
let message = given_message();
assert_eq!(message.body().as_bytes(), expected_body().as_bytes());
}
#[test]
fn should_return_header() {
let message = given_message();
assert_eq!(message.header("c"), Some("d".to_string()));
}
fn given_message() -> WebhookMessage {
WebhookMessage::new(
expected_forge_alias(),
expected_repo_alias(),
expected_headers(),
expected_body(),
)
}
fn expected_forge_alias() -> ForgeAlias {
ForgeAlias::new("a".to_string())
}
fn expected_repo_alias() -> RepoAlias {
RepoAlias::new("b")
}
fn expected_headers() -> std::collections::HashMap<String, String> {
[("c", "d"), ("e", "f")]
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect()
}
fn expected_body() -> Body {
Body::new("g".to_string())
}
}
}
mod push {
use crate::{
webhook::{push::Branch, Push},
BranchName, RepoBranches,
};
#[test]
fn should_return_main_branch() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(repo_branches.main());
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Main));
}
#[test]
fn should_return_next_branch() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(repo_branches.next());
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Next));
}
#[test]
fn should_return_dev_branch() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(repo_branches.dev());
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Dev));
}
#[test]
fn should_not_return_other_branches() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(BranchName::new("foo"));
assert_eq!(push_event.branch(&repo_branches), None);
}
#[test]
fn should_return_sha() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(repo_branches.main());
assert_eq!(push_event.sha(), "sha");
}
#[test]
fn should_return_message() {
let repo_branches = given_repo_branches();
let push_event = given_push_event(repo_branches.main());
assert_eq!(push_event.message(), "message");
}
fn given_push_event(branch_name: BranchName) -> Push {
Push::new(branch_name, "sha".to_string(), "message".to_string())
}
fn given_repo_branches() -> RepoBranches {
RepoBranches::new(
"a-main".to_string(),
"b-next".to_string(),
"c-dev".to_string(),
)
}
}

View file

@ -31,7 +31,7 @@ impl Push {
}
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum Branch {
Main,
Next,

View file

@ -3,7 +3,7 @@ addr = "0.0.0.0"
port = 8080
[webhook]
url = "https://localhost:8080"
url = "https://localhost:8080" # don't include any query path or a trailing slash
[storage]
path = "./data"
@ -15,7 +15,6 @@ forge_type = "ForgeJo"
hostname = "git.example.net"
user = "git-next" # the user to perform actions as
token = "API-Token"
# path to private SSH key for user?
[forge.default.repos]
hello = { repo = "user/hello", branch = "main", gitdir = "/opt/git/projects/user/hello.git" } # maps to https://git.example.net/user/hello on the branch 'main'