Files

201 lines
7.9 KiB
Rust

// file: crates/knowledge-git-lib/tests/git_read_path.rs
// version: 2
//! Integration tests for the real generic Git read path using local temporary repositories.
fn test_root(label: &str) -> std::path::PathBuf {
let nanos_result = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH);
let nanos = match nanos_result {
Ok(value) => value.as_nanos(),
Err(_) => 0,
};
let mut path = std::env::temp_dir();
path.push(format!("sasedev-knowledge-git-integration-{label}-{}-{nanos}", std::process::id()));
let _ = std::fs::remove_dir_all(&path);
return path;
}
fn run_git(repository: &std::path::Path, arguments: &[&str]) -> bool {
let mut command = std::process::Command::new("git");
command.current_dir(repository);
command.args(arguments);
command.env("GIT_TERMINAL_PROMPT", "0");
let status_result = command.status();
match status_result {
Ok(status) => return status.success(),
Err(_) => return false,
}
}
fn prepare_source(root: &std::path::Path) -> Option<std::path::PathBuf> {
let source = root.join("source");
if std::fs::create_dir_all(&source).is_err() {
return None;
}
if !run_git(&source, &["init", "-b", "main"]) {
return None;
}
if !run_git(&source, &["config", "user.name", "Knowledge Test"]) {
return None;
}
if !run_git(&source, &["config", "user.email", "knowledge@example.invalid"]) {
return None;
}
if !run_git(&source, &["config", "commit.gpgsign", "false"]) {
return None;
}
if std::fs::write(source.join("content.txt"), "first\n").is_err() {
return None;
}
if !run_git(&source, &["add", "content.txt"]) {
return None;
}
if !run_git(&source, &["commit", "-m", "first"]) {
return None;
}
return Some(source);
}
fn source_id() -> Option<knowledge_domain_lib::SourceId> {
let result = knowledge_domain_lib::SourceId::new("integration-source");
match result {
Ok(value) => return Some(value),
Err(_) => return None,
}
}
fn configured_backend(root: &std::path::Path, source: &std::path::Path) -> Option<(knowledge_git_lib::GitBackend, knowledge_domain_lib::SourceId)> {
let source_id_result = source_id();
let source_id = match source_id_result {
Some(value) => value,
None => return None,
};
let config_result = knowledge_git_lib::GitBackendConfig::new(root.join("state"));
let config = match config_result {
Ok(value) => value,
Err(_) => return None,
};
let source_result = knowledge_git_lib::GitSourceConfig::local(source_id.clone(), source.to_path_buf());
let source_config = match source_result {
Ok(value) => value,
Err(_) => return None,
};
let mut backend = knowledge_git_lib::GitBackend::new(config);
if backend.register_source(source_config).is_err() {
return None;
}
return Some((backend, source_id));
}
#[test]
fn real_local_repository_refreshes_resolves_and_materializes_revision_snapshots() {
let root = test_root("refresh-resolve-snapshot");
let source_result = prepare_source(&root);
assert!(source_result.is_some());
let source = match source_result {
Some(value) => value,
None => return,
};
let backend_result = configured_backend(&root, &source);
assert!(backend_result.is_some());
let (mut backend, source_id) = match backend_result {
Some(value) => value,
None => return,
};
let reference = knowledge_git_api::GitReference::new("refs/heads/main");
assert!(knowledge_git_api::GitRepository::refresh(&mut backend, &source_id).is_ok());
let first_revision_result = knowledge_git_api::GitRepository::resolve_revision(&backend, &source_id, &reference);
assert!(first_revision_result.is_ok());
let first_revision = match first_revision_result {
Ok(value) => value,
Err(_) => return,
};
let first_snapshot_result = knowledge_git_api::GitRepository::prepare_snapshot(&backend, &source_id, &first_revision);
assert!(first_snapshot_result.is_ok());
let first_snapshot = match first_snapshot_result {
Ok(value) => value,
Err(_) => return,
};
assert!(first_snapshot.path().is_dir());
let first_content_result = std::fs::read_to_string(first_snapshot.path().join("content.txt"));
assert!(first_content_result.is_ok());
let first_content = match first_content_result {
Ok(value) => value,
Err(_) => return,
};
assert_eq!(first_content, "first\n");
let repeated_snapshot_result = knowledge_git_api::GitRepository::prepare_snapshot(&backend, &source_id, &first_revision);
assert!(repeated_snapshot_result.is_ok());
let repeated_snapshot = match repeated_snapshot_result {
Ok(value) => value,
Err(_) => return,
};
assert_eq!(first_snapshot.path(), repeated_snapshot.path());
assert!(std::fs::write(source.join("content.txt"), "second\n").is_ok());
assert!(run_git(&source, &["add", "content.txt"]));
assert!(run_git(&source, &["commit", "-m", "second"]));
assert!(knowledge_git_api::GitRepository::refresh(&mut backend, &source_id).is_ok());
let second_revision_result = knowledge_git_api::GitRepository::resolve_revision(&backend, &source_id, &reference);
assert!(second_revision_result.is_ok());
let second_revision = match second_revision_result {
Ok(value) => value,
Err(_) => return,
};
assert_ne!(first_revision, second_revision);
let second_snapshot_result = knowledge_git_api::GitRepository::prepare_snapshot(&backend, &source_id, &second_revision);
assert!(second_snapshot_result.is_ok());
let second_snapshot = match second_snapshot_result {
Ok(value) => value,
Err(_) => return,
};
assert_ne!(first_snapshot.path(), second_snapshot.path());
let second_content_result = std::fs::read_to_string(second_snapshot.path().join("content.txt"));
assert!(second_content_result.is_ok());
let second_content = match second_content_result {
Ok(value) => value,
Err(_) => return,
};
assert_eq!(second_content, "second\n");
let _ = std::fs::remove_dir_all(&root);
return;
}
#[test]
fn invalid_reference_and_dirty_existing_snapshot_are_rejected() {
let root = test_root("invalid-and-dirty");
let source_result = prepare_source(&root);
assert!(source_result.is_some());
let source = match source_result {
Some(value) => value,
None => return,
};
let backend_result = configured_backend(&root, &source);
assert!(backend_result.is_some());
let (mut backend, source_id) = match backend_result {
Some(value) => value,
None => return,
};
assert!(knowledge_git_api::GitRepository::refresh(&mut backend, &source_id).is_ok());
let missing_reference = knowledge_git_api::GitReference::new("refs/heads/does-not-exist");
let missing_result = knowledge_git_api::GitRepository::resolve_revision(&backend, &source_id, &missing_reference);
assert!(missing_result.is_err());
let reference = knowledge_git_api::GitReference::new("refs/heads/main");
let revision_result = knowledge_git_api::GitRepository::resolve_revision(&backend, &source_id, &reference);
assert!(revision_result.is_ok());
let revision = match revision_result {
Ok(value) => value,
Err(_) => return,
};
let snapshot_result = knowledge_git_api::GitRepository::prepare_snapshot(&backend, &source_id, &revision);
assert!(snapshot_result.is_ok());
let snapshot = match snapshot_result {
Ok(value) => value,
Err(_) => return,
};
assert!(std::fs::write(snapshot.path().join("content.txt"), "dirty\n").is_ok());
let repeated_result = knowledge_git_api::GitRepository::prepare_snapshot(&backend, &source_id, &revision);
assert_eq!(repeated_result, Err(knowledge_git_lib::GitBackendError::InvalidSnapshot));
let _ = std::fs::remove_dir_all(&root);
return;
}