mod common;
use common::{create_test_repo, skip_if_no_binary, test_relay::TestRelay, TestEnv, TestServer};
use std::process::{Command, Stdio};
#[test]
fn test_server_coverage_full_upload() {
if skip_if_no_binary() {
return;
}
let relay = TestRelay::new(19210);
println!("Started local nostr relay at: {}", relay.url());
let server_a = match TestServer::new(19211) {
Some(s) => s,
None => {
println!("SKIP: htree binary not found. Run `cargo build --bin htree` first.");
return;
}
};
println!("Started blossom server A at: {}", server_a.base_url());
let server_b = match TestServer::new(19212) {
Some(s) => s,
None => {
println!("SKIP: htree binary not found. Run `cargo build --bin htree` first.");
return;
}
};
println!("Started blossom server B at: {}", server_b.base_url());
println!("\n=== Server Coverage Test (Optional New Server) ===\n");
let test_env = TestEnv::new(Some(&server_a.base_url()), Some(&relay.url()));
println!("Test environment at: {:?}\n", test_env.home_dir);
let env_vars: Vec<_> = test_env.env();
let repo = create_test_repo();
println!("Test repo at: {:?}\n", repo.path());
let remote_url = "htree://self/coverage-test-repo";
Command::new("git")
.args(["remote", "add", "htree", remote_url])
.current_dir(repo.path())
.envs(env_vars.iter().map(|(k, v)| (k.as_str(), v.as_str())))
.output()
.expect("Failed to add remote");
println!("=== First push (to server A only) ===");
let push1 = Command::new("git")
.args(["push", "htree", "master"])
.current_dir(repo.path())
.envs(env_vars.iter().map(|(k, v)| (k.as_str(), v.as_str())))
.output()
.expect("Failed to push");
let stderr1 = String::from_utf8_lossy(&push1.stderr);
println!("First push stderr:\n{}", stderr1);
if !push1.status.success() && !stderr1.contains("-> master") {
panic!("First push failed: {}", stderr1);
}
println!("\n=== Adding server B to config ===");
test_env.update_blossom_servers(&[&server_a.base_url(), &server_b.base_url()], &relay.url());
std::fs::write(
repo.path().join("new-file.txt"),
"Testing server coverage\n",
)
.expect("Failed to write file");
Command::new("git")
.args(["add", "new-file.txt"])
.current_dir(repo.path())
.output()
.expect("Failed to git add");
Command::new("git")
.args(["commit", "-m", "Add new file for coverage test"])
.current_dir(repo.path())
.stdout(Stdio::null())
.output()
.expect("Failed to commit");
println!("\n=== Second push (should keep diffing with optional server B) ===");
let push2 = Command::new("git")
.args(["push", "htree", "master"])
.current_dir(repo.path())
.envs(env_vars.iter().map(|(k, v)| (k.as_str(), v.as_str())))
.output()
.expect("Failed to push");
let stderr2 = String::from_utf8_lossy(&push2.stderr);
println!("Second push stderr:\n{}", stderr2);
if !push2.status.success() && !stderr2.contains("-> master") {
panic!("Second push failed: {}", stderr2);
}
let full_upload_detected = stderr2.contains("Full upload needed")
|| stderr2.contains("not have old tree")
|| stderr2.contains("full upload");
let diff_used = stderr2.contains("unchanged") || stderr2.contains("Computing diff");
println!(
"\nFull upload to new server detected: {}",
full_upload_detected
);
println!("Diff optimization for existing server: {}", diff_used);
assert!(
!full_upload_detected,
"optional write server should not force a full upload:\n{}",
stderr2
);
let server_a_url = server_a.base_url();
let server_b_url = server_b.base_url();
let server_a_host = server_a_url.trim_start_matches("http://");
let server_b_host = server_b_url.trim_start_matches("http://");
assert!(
stderr2.contains(server_a_host)
|| stderr2.contains(server_b_host)
|| stderr2.contains("Blossom")
|| stderr2.contains("Uploading"),
"Push should show blossom server activity"
);
std::fs::write(
repo.path().join("another-file.txt"),
"Testing repeated server coverage\n",
)
.expect("Failed to write follow-up file");
Command::new("git")
.args(["add", "another-file.txt"])
.current_dir(repo.path())
.output()
.expect("Failed to git add follow-up");
Command::new("git")
.args(["commit", "-m", "Add follow-up file for coverage test"])
.current_dir(repo.path())
.stdout(Stdio::null())
.output()
.expect("Failed to commit follow-up");
println!("\n=== Third push (should not need repeated full upload) ===");
let push3 = Command::new("git")
.args(["push", "htree", "master"])
.current_dir(repo.path())
.envs(env_vars.iter().map(|(k, v)| (k.as_str(), v.as_str())))
.output()
.expect("Failed to push follow-up");
let stderr3 = String::from_utf8_lossy(&push3.stderr);
println!("Third push stderr:\n{}", stderr3);
if !push3.status.success() && !stderr3.contains("-> master") {
panic!("Third push failed: {}", stderr3);
}
assert!(
!stderr3.contains("Full upload needed"),
"follow-up push should not repeatedly fall back to a full upload:\n{}",
stderr3
);
println!("\n=== SUCCESS: Server coverage test passed! ===");
}