use jj_cz::{CommitMessageError, DescriptionError, Error, ScopeError};
#[test]
fn test_all_error_variants() {
let invalid_scope = Error::InvalidScope("test".to_string());
let _invalid_desc = Error::InvalidDescription("test".to_string());
let _invalid_msg = Error::InvalidCommitMessage("test".to_string());
let not_repo = Error::NotARepository;
let _jj_op = Error::JjOperation {
context: "test".to_string(),
};
let _repo_locked = Error::RepositoryLocked;
let _failed_dir = Error::FailedGettingCurrentDir;
let _failed_config = Error::FailedReadingConfig {
context: "test".to_string(),
};
let cancelled = Error::Cancelled;
let _non_interactive = Error::NonInteractive;
assert_eq!(format!("{}", invalid_scope), "Invalid scope: test");
assert_eq!(format!("{}", not_repo), "Not a Jujutsu repository");
assert_eq!(format!("{}", cancelled), "Operation cancelled by user");
}
#[test]
fn test_error_conversions() {
let scope_err = ScopeError::TooLong {
actual: 31,
max: 30,
};
let error: Error = scope_err.into();
assert!(matches!(error, Error::InvalidScope(_)));
let desc_err = DescriptionError::Empty;
let error: Error = desc_err.into();
assert!(matches!(error, Error::InvalidDescription(_)));
let msg_err = CommitMessageError::FirstLineTooLong {
actual: 73,
max: 72,
};
let error: Error = msg_err.into();
assert!(matches!(error, Error::InvalidCommitMessage(_)));
}
#[test]
fn test_error_equality() {
let err1 = Error::NotARepository;
let err2 = Error::NotARepository;
assert_eq!(err1, err2);
let err3 = Error::Cancelled;
assert_ne!(err1, err3);
}
#[test]
fn test_error_debug() {
let error = Error::JjOperation {
context: "test operation".to_string(),
};
let debug_str = format!("{:?}", error);
assert!(debug_str.contains("JjOperation"));
assert!(debug_str.contains("test operation"));
}
#[test]
fn test_error_clone() {
let original = Error::JjOperation {
context: "original".to_string(),
};
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_error_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
let _error = Error::NotARepository;
assert_send::<Error>();
assert_sync::<Error>();
let _owned_error = Error::JjOperation {
context: "test".to_string(),
};
assert_send::<Error>();
assert_sync::<Error>();
}
#[test]
fn test_error_matching() {
let error = Error::Cancelled;
match error {
Error::Cancelled => {}
Error::NotARepository => panic!("Should not match"),
Error::JjOperation { context } => panic!("Should not match: {}", context),
_ => panic!("Should not match other variants"),
}
}
#[test]
fn test_jj_operation_context() {
let error = Error::JjOperation {
context: "repository locked".to_string(),
};
if let Error::JjOperation { context } = error {
assert_eq!(context, "repository locked");
} else {
panic!("Expected JjOperation variant");
}
}
#[test]
fn test_from_io_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let error: Error = io_err.into();
assert!(matches!(error, Error::FailedGettingCurrentDir));
}
#[test]
fn test_from_poison_error() {
let mutex = std::sync::Mutex::new(());
let poison_err = std::panic::catch_unwind(|| {
let _guard = mutex.lock().unwrap();
panic!("deliberate panic");
});
assert!(poison_err.is_err());
let result = mutex.lock();
assert!(result.is_err());
let error: Error = result.unwrap_err().into();
assert!(matches!(error, Error::JjOperation { .. }));
assert_eq!(
format!("{}", error),
"Repository operation failed: internal lock poisoned"
);
}
#[test]
fn test_from_revset_evaluation_error() {
let underlying = std::io::Error::other("store failure");
let eval_err = jj_lib::revset::RevsetEvaluationError::Other(Box::new(underlying));
let error = Error::from_revset_evaluation_error("@", eval_err);
assert!(matches!(error, Error::RevsetResolutionError { .. }));
let description = format!("{}", error);
assert!(description.contains("@"));
assert!(description.contains("store failure"));
}
#[test]
fn test_from_revset_resolution_error() {
let resolution_err = jj_lib::revset::RevsetResolutionError::NoSuchRevision {
name: "nonexistent".to_string(),
candidates: Vec::new(),
};
let error = Error::from_revset_resolution_error("@", resolution_err);
assert!(matches!(error, Error::RevsetResolutionError { .. }));
let description = format!("{}", error);
assert!(description.contains("@"));
assert!(description.contains("nonexistent"));
}
#[test]
fn test_new_flag_with_multiple_revisions() {
let error = Error::NewFlagWithMultipleRevisions;
assert_eq!(
format!("{}", error),
"--new cannot be used with multiple revisions"
);
}
#[test]
fn test_non_interactive() {
let error = Error::NonInteractive;
assert_eq!(format!("{}", error), "Non-interactive terminal detected");
}
#[test]
fn test_failed_reading_config() {
let error = Error::FailedReadingConfig {
context: "config parse error".to_string(),
};
let description = format!("{}", error);
assert!(description.contains("config parse error"));
}
#[test]
fn test_multiple_revisions() {
let error = Error::MultipleRevisions {
revset: "abc | def".to_string(),
};
let description = format!("{}", error);
assert!(description.contains("abc | def"));
assert!(description.contains("multiple commits"));
}
#[test]
fn test_repository_locked() {
let error = Error::RepositoryLocked;
assert_eq!(
format!("{}", error),
"Repository is locked by another process"
);
}
#[test]
fn test_failed_getting_current_dir() {
let error = Error::FailedGettingCurrentDir;
assert_eq!(format!("{}", error), "Could not get current directory");
}
#[test]
fn test_error_matching_all_variants() {
let variants: Vec<Error> = vec![
Error::InvalidScope("s".into()),
Error::InvalidDescription("d".into()),
Error::InvalidCommitMessage("m".into()),
Error::NotARepository,
Error::JjOperation {
context: "c".into(),
},
Error::RepositoryLocked,
Error::FailedGettingCurrentDir,
Error::FailedReadingConfig {
context: "c".into(),
},
Error::Cancelled,
Error::NonInteractive,
Error::RevsetResolutionError {
revset: "@".into(),
context: "c".into(),
},
Error::MultipleRevisions { revset: "@".into() },
Error::NewFlagWithMultipleRevisions,
];
for variant in &variants {
let _ = format!("{}", variant);
let _ = format!("{:?}", variant);
}
let cloned: Vec<Error> = variants.to_vec();
assert_eq!(variants.len(), cloned.len());
for (original, clone) in variants.iter().zip(cloned.iter()) {
assert_eq!(original, clone);
}
}