use heroforge_core::{Repository, Result};
use std::fs;
use std::path::Path;
use std::time::Instant;
struct TestResult {
name: String,
passed: bool,
details: String,
duration_ms: u128,
}
fn main() -> Result<()> {
let test_dir = Path::new("/tmp/fossil_stress_test");
if test_dir.exists() {
fs::remove_dir_all(test_dir).expect("Failed to clean up");
}
fs::create_dir_all(test_dir).expect("Failed to create test dir");
let mut results: Vec<TestResult> = Vec::new();
println!("=== heroforge Stress Test Suite ===\n");
results.push(test_many_commits(test_dir));
results.push(test_identical_content(test_dir));
results.push(test_unchanged_commits(test_dir));
results.push(test_long_paths(test_dir));
results.push(test_special_filenames(test_dir));
results.push(test_incremental_changes(test_dir));
results.push(test_historical_reads(test_dir));
results.push(test_cli_full_verification(test_dir));
results.push(test_concurrent_repos(test_dir));
results.push(test_large_commit_messages(test_dir));
println!("\n=== Test Summary ===\n");
let mut passed = 0;
let mut failed = 0;
for result in &results {
let status = if result.passed { "PASS" } else { "FAIL" };
println!("[{}] {} ({} ms)", status, result.name, result.duration_ms);
if !result.passed {
println!(" {}", result.details);
failed += 1;
} else {
passed += 1;
}
}
println!("\nTotal: {} passed, {} failed", passed, failed);
if failed > 0 {
std::process::exit(1);
}
Ok(())
}
fn test_many_commits(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "200 sequential commits".to_string();
let repo_path = base_dir.join("test_many_commits.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let mut parent = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
for i in 1..=200 {
let content = format!("Commit number {}\nLine 2\nLine 3", i);
let hash = repo
.commit_builder()
.message(&format!("Commit {}", i))
.author("testuser")
.parent(&parent)
.branch("trunk")
.file("counter.txt", content.as_bytes())
.execute()?;
parent = hash;
}
let checkins = repo.history().recent(250)?;
if checkins.len() != 201 {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Expected 201, got {}",
checkins.len()
)));
}
let content = repo.files().at_commit(&parent).read_string("counter.txt")?;
if !content.contains("Commit number 200") {
return Err(heroforge_core::FossilError::InvalidArtifact(
"Last commit content wrong".into(),
));
}
Ok("200 commits created and verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_identical_content(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Identical content in multiple files".to_string();
let repo_path = base_dir.join("test_identical.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let content = b"This exact content appears in 20 different files";
let mut files_data: Vec<(String, &[u8])> = Vec::new();
for i in 0..20 {
files_data.push((format!("same_content_{}.txt", i), content));
}
let files: Vec<(&str, &[u8])> = files_data.iter().map(|(n, c)| (n.as_str(), *c)).collect();
let hash = repo
.commit_builder()
.message("Add identical files")
.author("testuser")
.parent(&initial)
.branch("trunk")
.files(&files)
.execute()?;
for i in 0..20 {
let name = format!("same_content_{}.txt", i);
let read_content = repo.files().at_commit(&hash).read(&name)?;
if read_content != content {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Content mismatch for {}",
name
)));
}
}
Ok("20 identical files verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_unchanged_commits(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Commits with unchanged files".to_string();
let repo_path = base_dir.join("test_unchanged.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let content = b"This content never changes";
let hash1 = repo
.commit_builder()
.message("First commit")
.author("testuser")
.parent(&initial)
.branch("trunk")
.file("stable.txt", content)
.execute()?;
let hash2 = repo
.commit_builder()
.message("Second commit same content")
.author("testuser")
.parent(&hash1)
.branch("trunk")
.file("stable.txt", content)
.execute()?;
let hash3 = repo
.commit_builder()
.message("Third commit same content")
.author("testuser")
.parent(&hash2)
.branch("trunk")
.file("stable.txt", content)
.execute()?;
for hash in [&hash1, &hash2, &hash3] {
let read_content = repo.files().at_commit(hash).read("stable.txt")?;
if read_content != content {
return Err(heroforge_core::FossilError::InvalidArtifact(
"Content mismatch".into(),
));
}
}
let checkins = repo.history().recent(10)?;
if checkins.len() != 4 {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Expected 4 checkins, got {}",
checkins.len()
)));
}
Ok("3 commits with same content verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_long_paths(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Very long file paths".to_string();
let repo_path = base_dir.join("test_long_paths.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let deep_path = "a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/file.txt";
let long_names = "this_is_a_very_long_directory_name/another_really_long_directory_name_here/yet_another_long_name/file_with_long_name_that_goes_on_and_on.txt";
let hash = repo
.commit_builder()
.message("Add files with long paths")
.author("testuser")
.parent(&initial)
.branch("trunk")
.file(deep_path, b"Deep file content")
.file(long_names, b"Long names content")
.execute()?;
let content1 = repo.files().at_commit(&hash).read(deep_path)?;
if content1 != b"Deep file content" {
return Err(heroforge_core::FossilError::InvalidArtifact(
"Deep path mismatch".into(),
));
}
let content2 = repo.files().at_commit(&hash).read(long_names)?;
if content2 != b"Long names content" {
return Err(heroforge_core::FossilError::InvalidArtifact(
"Long names mismatch".into(),
));
}
Ok("Long paths verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_special_filenames(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Special characters in filenames".to_string();
let repo_path = base_dir.join("test_special_names.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let hash = repo
.commit_builder()
.message("Add special filenames")
.author("testuser")
.parent(&initial)
.branch("trunk")
.file("file with spaces.txt", b"spaces")
.file("file-with-dashes.txt", b"dashes")
.file("file_with_underscores.txt", b"underscores")
.file("file.multiple.dots.txt", b"dots")
.file("UPPERCASE.TXT", b"upper")
.file("MixedCase.Txt", b"mixed")
.file("file123numbers456.txt", b"numbers")
.file(".hidden_file", b"hidden")
.file("file.tar.gz", b"double ext")
.execute()?;
let files = [
("file with spaces.txt", b"spaces".as_slice()),
("file-with-dashes.txt", b"dashes"),
("file_with_underscores.txt", b"underscores"),
("file.multiple.dots.txt", b"dots"),
("UPPERCASE.TXT", b"upper"),
("MixedCase.Txt", b"mixed"),
("file123numbers456.txt", b"numbers"),
(".hidden_file", b"hidden"),
("file.tar.gz", b"double ext"),
];
for (name, expected) in &files {
let content = repo.files().at_commit(&hash).read(name)?;
if &content != expected {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Mismatch for '{}'",
name
)));
}
}
Ok(format!("{} special filenames verified", files.len()))
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_incremental_changes(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Incremental small changes".to_string();
let repo_path = base_dir.join("test_incremental.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let mut parent = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let mut hashes: Vec<String> = Vec::new();
let mut content = String::from("Line 1\nLine 2\nLine 3\n");
for i in 1..=30 {
content.push_str(&format!("Line {} added\n", i + 3));
let hash = repo
.commit_builder()
.message(&format!("Add line {}", i + 3))
.author("testuser")
.parent(&parent)
.branch("trunk")
.file("growing.txt", content.as_bytes())
.execute()?;
hashes.push(hash.clone());
parent = hash;
}
for (i, hash) in hashes.iter().enumerate() {
let content = repo.files().at_commit(hash).read("growing.txt")?;
let line_count = content.iter().filter(|&&b| b == b'\n').count();
let expected = 3 + i + 1;
if line_count != expected {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Version {} has {} lines, expected {}",
i + 1,
line_count,
expected
)));
}
}
Ok("30 incremental changes verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_historical_reads(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Historical reads during commits".to_string();
let repo_path = base_dir.join("test_historical.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let mut parent = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let mut all_hashes: Vec<(String, String)> = Vec::new();
for i in 1..=20 {
let content = format!("Version {} content", i);
let hash = repo
.commit_builder()
.message(&format!("Version {}", i))
.author("testuser")
.parent(&parent)
.branch("trunk")
.file("data.txt", content.as_bytes())
.execute()?;
all_hashes.push((hash.clone(), content));
parent = hash;
if i % 5 == 0 {
for (old_hash, expected) in &all_hashes {
let content = repo.files().at_commit(old_hash).read_string("data.txt")?;
if content != *expected {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Historical read failed at commit {}",
i
)));
}
}
}
}
for (hash, expected) in &all_hashes {
let content = repo.files().at_commit(hash).read_string("data.txt")?;
if content != *expected {
return Err(heroforge_core::FossilError::InvalidArtifact(
"Final verification failed".into(),
));
}
}
Ok("20 versions with historical reads verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_cli_full_verification(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Diverse file types verification".to_string();
let repo_path = base_dir.join("test_diverse_files.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let binary_content = vec![0u8, 1, 2, 255, 254, 253];
let unicode_content = "Hello 世界 🌍".as_bytes();
let hash = repo
.commit_builder()
.message("Test commit with diverse files")
.author("testuser")
.parent(&initial)
.branch("trunk")
.file("text.txt", b"Plain text content")
.file("binary.bin", &binary_content)
.file("dir/nested.txt", b"Nested file")
.file("unicode.txt", unicode_content)
.file("empty.txt", b"")
.file("deep/path/to/file.txt", b"Deep nested")
.execute()?;
let files = [
("text.txt", b"Plain text content".to_vec()),
("binary.bin", binary_content.clone()),
("dir/nested.txt", b"Nested file".to_vec()),
("unicode.txt", unicode_content.to_vec()),
("empty.txt", Vec::new()),
("deep/path/to/file.txt", b"Deep nested".to_vec()),
];
for (name, expected) in &files {
let content = repo.files().at_commit(&hash).read(name)?;
if content != *expected {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Content mismatch for '{}': expected {} bytes, got {} bytes",
name,
expected.len(),
content.len()
)));
}
}
let file_list = repo.files().at_commit(&hash).list()?;
if file_list.len() != files.len() {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Expected {} files, got {}",
files.len(),
file_list.len()
)));
}
Ok(format!("{} diverse files verified", files.len()))
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_concurrent_repos(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Multiple concurrent repositories".to_string();
let result = (|| -> Result<String> {
let mut repos: Vec<(Repository, String)> = Vec::new();
for i in 0..5 {
let repo_path = base_dir.join(format!("concurrent_repo_{}.forge", i));
let repo = Repository::init(&repo_path)?;
let initial = repo
.commit_builder()
.message("initial empty check-in")
.author(&format!("user{}", i))
.initial()
.execute()?;
repos.push((repo, initial));
}
for round in 1..=10 {
for (i, (repo, parent)) in repos.iter_mut().enumerate() {
let content = format!("Repo {} round {}", i, round);
let hash = repo
.commit_builder()
.message(&format!("Round {}", round))
.author(&format!("user{}", i))
.parent(parent)
.branch("trunk")
.file("data.txt", content.as_bytes())
.execute()?;
*parent = hash;
}
}
for (i, (repo, last_hash)) in repos.iter().enumerate() {
let content = repo.files().at_commit(last_hash).read_string("data.txt")?;
let expected = format!("Repo {} round 10", i);
if content != expected {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Repo {} verification failed",
i
)));
}
let checkins = repo.history().recent(15)?;
if checkins.len() != 11 {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Repo {} has {} checkins, expected 11",
i,
checkins.len()
)));
}
}
Ok("5 concurrent repos with 10 commits each verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}
fn test_large_commit_messages(base_dir: &Path) -> TestResult {
let start = Instant::now();
let name = "Large commit messages".to_string();
let repo_path = base_dir.join("test_large_messages.forge");
let result = (|| -> Result<String> {
let repo = Repository::init(&repo_path)?;
let mut parent = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
let msg1 = "Short message".to_string();
let msg2 =
"A longer message with more details about the changes made in this commit.".to_string();
let msg3 = "x".repeat(1000); let msg4 = format!(
"Multi-line message\nLine 2\nLine 3\nLine 4\n{}",
"more ".repeat(100)
);
let msg5 = format!("Unicode message: 你好世界 🎉 {}", "test ".repeat(50));
let messages: Vec<&str> = vec![&msg1, &msg2, &msg3, &msg4, &msg5];
for (i, msg) in messages.iter().enumerate() {
let content = format!("Commit {}", i);
let hash = repo
.commit_builder()
.message(msg)
.author("testuser")
.parent(&parent)
.branch("trunk")
.file("file.txt", content.as_bytes())
.execute()?;
parent = hash;
}
let checkins = repo.history().recent(10)?;
if checkins.len() != 6 {
return Err(heroforge_core::FossilError::InvalidArtifact(format!(
"Expected 6 checkins, got {}",
checkins.len()
)));
}
Ok("Large commit messages verified".into())
})();
TestResult {
name,
passed: result.is_ok(),
details: result.unwrap_or_else(|e| e.to_string()),
duration_ms: start.elapsed().as_millis(),
}
}