diff --git a/crates/konvoy-config/src/lockfile.rs b/crates/konvoy-config/src/lockfile.rs index 786725c..de1e3ad 100644 --- a/crates/konvoy-config/src/lockfile.rs +++ b/crates/konvoy-config/src/lockfile.rs @@ -1167,4 +1167,35 @@ url = "https://example.com/plugin.jar" } } } + + #[test] + fn has_maven_entry_finds_maven_dep() { + let mut lockfile = Lockfile::default(); + lockfile.dependencies.push(DependencyLock { + name: "kotlinx-coroutines".to_owned(), + source: DepSource::Maven { + version: "1.8.0".to_owned(), + maven: "org.jetbrains.kotlinx:kotlinx-coroutines-core".to_owned(), + targets: std::collections::BTreeMap::new(), + required_by: Vec::new(), + classifier: None, + }, + source_hash: "abc".to_owned(), + }); + assert!(lockfile.has_maven_entry("kotlinx-coroutines")); + assert!(!lockfile.has_maven_entry("nonexistent")); + } + + #[test] + fn has_maven_entry_ignores_path_deps() { + let mut lockfile = Lockfile::default(); + lockfile.dependencies.push(DependencyLock { + name: "my-lib".to_owned(), + source: DepSource::Path { + path: "../my-lib".to_owned(), + }, + source_hash: "abc".to_owned(), + }); + assert!(!lockfile.has_maven_entry("my-lib")); + } } diff --git a/crates/konvoy-config/src/manifest.rs b/crates/konvoy-config/src/manifest.rs index ef55470..6ea0e5c 100644 --- a/crates/konvoy-config/src/manifest.rs +++ b/crates/konvoy-config/src/manifest.rs @@ -1667,4 +1667,44 @@ version = "1.0" } } } + + #[test] + fn is_maven_true_when_both_set() { + let spec = DependencySpec { + path: None, + maven: Some("org.example:lib".to_owned()), + version: Some("1.0.0".to_owned()), + }; + assert!(spec.is_maven()); + } + + #[test] + fn is_maven_false_when_maven_only() { + let spec = DependencySpec { + path: None, + maven: Some("org.example:lib".to_owned()), + version: None, + }; + assert!(!spec.is_maven()); + } + + #[test] + fn is_maven_false_when_version_only() { + let spec = DependencySpec { + path: None, + maven: None, + version: Some("1.0.0".to_owned()), + }; + assert!(!spec.is_maven()); + } + + #[test] + fn is_maven_false_for_path_dep() { + let spec = DependencySpec { + path: Some("../lib".to_owned()), + maven: None, + version: None, + }; + assert!(!spec.is_maven()); + } } diff --git a/crates/konvoy-engine/src/error.rs b/crates/konvoy-engine/src/error.rs index 833e0be..e76caff 100644 --- a/crates/konvoy-engine/src/error.rs +++ b/crates/konvoy-engine/src/error.rs @@ -201,3 +201,24 @@ pub(crate) fn map_artifact_download_err( other => EngineError::Util(other), } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn map_artifact_download_err_passes_through_other_errors() { + let err = konvoy_util::error::UtilError::NoHomeDir; + let result = map_artifact_download_err( + "test", + err, + |_, _| panic!("download_err should not be called"), + |_, _, _| panic!("hash_err should not be called"), + ); + let msg = result.to_string(); + assert!( + msg.contains("home directory"), + "other errors should pass through: {msg}" + ); + } +} diff --git a/crates/konvoy-engine/src/plugin.rs b/crates/konvoy-engine/src/plugin.rs index 46e5633..af8f5ac 100644 --- a/crates/konvoy-engine/src/plugin.rs +++ b/crates/konvoy-engine/src/plugin.rs @@ -771,4 +771,24 @@ mod tests { plugins, } } + + #[test] + fn ensure_plugin_artifacts_locked_mode_requires_hash() { + // In --locked mode, a plugin without a lockfile hash should fail. + let manifest = make_manifest_with_plugin( + "kotlin-serialization", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin", + "2.1.0", + ); + let artifacts = resolve_plugin_artifacts(&manifest).unwrap(); + let lockfile = Lockfile::default(); // no plugin hashes + + let result = ensure_plugin_artifacts(&artifacts, &lockfile, true); + assert!( + result.is_err(), + "expected error in locked mode without hash" + ); + let err = result.unwrap_err().to_string(); + assert!(err.contains("lockfile is out of date"), "error was: {err}"); + } } diff --git a/crates/konvoy-targets/src/lib.rs b/crates/konvoy-targets/src/lib.rs index bca6c30..4137218 100644 --- a/crates/konvoy-targets/src/lib.rs +++ b/crates/konvoy-targets/src/lib.rs @@ -333,4 +333,42 @@ mod tests { } } } + + #[test] + fn is_host_returns_true_for_host_target() { + // host_target() succeeds on all supported CI platforms. + if let Ok(host) = host_target() { + assert!( + host.is_host().unwrap_or(false), + "host target should match itself" + ); + } + } + + #[test] + fn is_host_returns_false_for_other_target() { + // Pick a target that's not the current host. + let host = match host_target() { + Ok(h) => h, + Err(_) => return, // skip on unsupported platforms + }; + let other_name = if host.to_konanc_arg() == "linux_x64" { + "macos_arm64" + } else { + "linux_x64" + }; + let other: Target = other_name.parse().unwrap(); + assert!( + !other.is_host().unwrap_or(true), + "non-host target should not match host" + ); + } + + #[test] + fn display_matches_konanc_arg() { + for &name in KNOWN_TARGETS { + let target: Target = name.parse().unwrap(); + assert_eq!(target.to_string(), target.to_konanc_arg()); + } + } } diff --git a/crates/konvoy-util/src/maven.rs b/crates/konvoy-util/src/maven.rs index 5c71e55..52fc5c7 100644 --- a/crates/konvoy-util/src/maven.rs +++ b/crates/konvoy-util/src/maven.rs @@ -385,4 +385,65 @@ mod tests { "new() should default classifier to None" ); } + + #[test] + fn parse_rejects_empty_group_id() { + let result = MavenCoordinate::parse(":artifact:1.0.0"); + assert!(result.is_err()); + let err = result.unwrap_err().to_string(); + assert!(err.contains("group_id is empty"), "error was: {err}"); + } + + #[test] + fn parse_rejects_empty_artifact_id() { + let result = MavenCoordinate::parse("group::1.0.0"); + assert!(result.is_err()); + let err = result.unwrap_err().to_string(); + assert!(err.contains("artifact_id is empty"), "error was: {err}"); + } + + #[test] + fn parse_rejects_empty_version() { + let result = MavenCoordinate::parse("group:artifact:"); + assert!(result.is_err()); + let err = result.unwrap_err().to_string(); + assert!(err.contains("version is empty"), "error was: {err}"); + } + + #[test] + fn parse_rejects_empty_packaging() { + let result = MavenCoordinate::parse("group:artifact:1.0.0:"); + assert!(result.is_err()); + let err = result.unwrap_err().to_string(); + assert!(err.contains("packaging is empty"), "error was: {err}"); + } + + #[test] + fn maven_artifact_url_format() { + let url = super::maven_artifact_url( + "org.jetbrains.kotlinx", + "kotlinx-coroutines-core", + "1.8.0", + "pom", + ); + assert_eq!( + url, + "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.8.0/kotlinx-coroutines-core-1.8.0.pom" + ); + } + + #[test] + fn maven_artifact_url_module_extension() { + let url = super::maven_artifact_url("org.example", "lib", "2.0.0", "module"); + assert!(url.ends_with("lib-2.0.0.module"), "url was: {url}"); + } + + #[test] + fn cache_path_matches_repository_path() { + let coord = MavenCoordinate::new("org.example", "lib", "1.0.0"); + let cache_root = Path::new("/cache"); + let cache_path = coord.cache_path(cache_root); + let expected = cache_root.join(coord.repository_path()); + assert_eq!(cache_path, expected); + } }