use semver::Version;
use std::path::Path;
pub fn assert_version_eq(actual: &str, expected: &str) {
let actual_ver =
Version::parse(actual).unwrap_or_else(|_| panic!("Invalid actual version: {}", actual));
let expected_ver = Version::parse(expected)
.unwrap_or_else(|_| panic!("Invalid expected version: {}", expected));
assert_eq!(actual_ver, expected_ver, "Version mismatch: expected {}, got {}", expected, actual);
}
pub fn assert_version_gt(actual: &str, expected_min: &str) {
let actual_ver =
Version::parse(actual).unwrap_or_else(|_| panic!("Invalid actual version: {}", actual));
let min_ver = Version::parse(expected_min)
.unwrap_or_else(|_| panic!("Invalid expected version: {}", expected_min));
assert!(actual_ver > min_ver, "Version {} is not greater than {}", actual, expected_min);
}
pub fn assert_version_gte(actual: &str, expected_min: &str) {
let actual_ver =
Version::parse(actual).unwrap_or_else(|_| panic!("Invalid actual version: {}", actual));
let min_ver = Version::parse(expected_min)
.unwrap_or_else(|_| panic!("Invalid expected version: {}", expected_min));
assert!(
actual_ver >= min_ver,
"Version {} is not greater than or equal to {}",
actual,
expected_min
);
}
#[allow(dead_code)]
pub fn assert_path_exists(path: &Path) {
assert!(path.exists(), "Path does not exist: {}", path.display());
}
#[allow(dead_code)]
pub fn assert_path_not_exists(path: &Path) {
assert!(!path.exists(), "Path exists but should not: {}", path.display());
}
#[allow(dead_code)]
pub fn assert_is_file(path: &Path) {
assert!(path.exists(), "Path does not exist: {}", path.display());
assert!(path.is_file(), "Path is not a file: {}", path.display());
}
#[allow(dead_code)]
pub fn assert_is_dir(path: &Path) {
assert!(path.exists(), "Path does not exist: {}", path.display());
assert!(path.is_dir(), "Path is not a directory: {}", path.display());
}
pub fn assert_contains(haystack: &str, needle: &str) {
assert!(
haystack.contains(needle),
"String does not contain expected substring.\nHaystack: {}\nNeedle: {}",
haystack,
needle
);
}
pub fn assert_not_contains(haystack: &str, needle: &str) {
assert!(
!haystack.contains(needle),
"String contains unexpected substring.\nHaystack: {}\nNeedle: {}",
haystack,
needle
);
}
pub fn assert_json_field(json_str: &str, field: &str, expected: &str) {
let value: serde_json::Value =
serde_json::from_str(json_str).unwrap_or_else(|e| panic!("Invalid JSON: {}", e));
let actual = field.split('.').try_fold(&value, |acc, key| acc.get(key));
match actual {
Some(actual_value) => {
let actual_str = match actual_value {
serde_json::Value::String(s) => s.clone(),
other => other.to_string().trim_matches('"').to_string(),
};
assert_eq!(
actual_str, expected,
"JSON field '{}' has unexpected value: expected '{}', got '{}'",
field, expected, actual_str
);
}
None => panic!("JSON field '{}' not found in: {}", field, json_str),
}
}
pub fn assert_len<T>(collection: &[T], expected_len: usize) {
assert_eq!(
collection.len(),
expected_len,
"Collection length mismatch: expected {}, got {}",
expected_len,
collection.len()
);
}
pub fn assert_empty<T>(collection: &[T]) {
assert!(collection.is_empty(), "Collection is not empty: contains {} items", collection.len());
}
pub fn assert_not_empty<T>(collection: &[T]) {
assert!(!collection.is_empty(), "Collection is empty but should not be");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_assert_version_eq_success() {
assert_version_eq("1.2.3", "1.2.3");
}
#[test]
#[should_panic(expected = "Version mismatch")]
fn test_assert_version_eq_failure() {
assert_version_eq("1.2.3", "1.2.4");
}
#[test]
fn test_assert_version_gt_success() {
assert_version_gt("1.2.3", "1.2.2");
assert_version_gt("2.0.0", "1.9.9");
}
#[test]
#[should_panic(expected = "is not greater than")]
fn test_assert_version_gt_failure() {
assert_version_gt("1.2.3", "1.2.3");
}
#[test]
fn test_assert_version_gte_success() {
assert_version_gte("1.2.3", "1.2.3");
assert_version_gte("1.2.3", "1.2.2");
}
#[test]
#[should_panic(expected = "is not greater than or equal to")]
fn test_assert_version_gte_failure() {
assert_version_gte("1.2.2", "1.2.3");
}
#[test]
fn test_assert_contains_success() {
assert_contains("hello world", "world");
assert_contains("hello world", "hello");
}
#[test]
#[should_panic(expected = "does not contain")]
fn test_assert_contains_failure() {
assert_contains("hello world", "goodbye");
}
#[test]
fn test_assert_not_contains_success() {
assert_not_contains("hello world", "goodbye");
}
#[test]
#[should_panic(expected = "contains unexpected")]
fn test_assert_not_contains_failure() {
assert_not_contains("hello world", "world");
}
#[test]
fn test_assert_json_field_success() {
let json = r#"{"name": "test", "version": "1.0.0"}"#;
assert_json_field(json, "name", "test");
assert_json_field(json, "version", "1.0.0");
}
#[test]
#[should_panic(expected = "has unexpected value")]
fn test_assert_json_field_wrong_value() {
let json = r#"{"name": "test"}"#;
assert_json_field(json, "name", "other");
}
#[test]
#[should_panic(expected = "not found")]
fn test_assert_json_field_missing() {
let json = r#"{"name": "test"}"#;
assert_json_field(json, "missing", "value");
}
#[test]
fn test_assert_len_success() {
let vec = vec![1, 2, 3];
assert_len(&vec, 3);
}
#[test]
#[should_panic(expected = "length mismatch")]
fn test_assert_len_failure() {
let vec = vec![1, 2, 3];
assert_len(&vec, 4);
}
#[test]
fn test_assert_empty_success() {
let vec: Vec<i32> = vec![];
assert_empty(&vec);
}
#[test]
#[should_panic(expected = "not empty")]
fn test_assert_empty_failure() {
let vec = vec![1, 2, 3];
assert_empty(&vec);
}
#[test]
fn test_assert_not_empty_success() {
let vec = vec![1, 2, 3];
assert_not_empty(&vec);
}
#[test]
#[should_panic(expected = "is empty")]
fn test_assert_not_empty_failure() {
let vec: Vec<i32> = vec![];
assert_not_empty(&vec);
}
}