diff options
Diffstat (limited to 'tests/archive_read_only.rs')
| -rw-r--r-- | tests/archive_read_only.rs | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/tests/archive_read_only.rs b/tests/archive_read_only.rs index be6959b..e39b4b2 100644 --- a/tests/archive_read_only.rs +++ b/tests/archive_read_only.rs | |||
| @@ -165,6 +165,7 @@ async fn test_archive_read_only_creates_bare_repo() { | |||
| 165 | // c) Put state event in purgatory (git data missing on archive relay) | 165 | // c) Put state event in purgatory (git data missing on archive relay) |
| 166 | // d) Fetch git data from source relay's clone URL | 166 | // d) Fetch git data from source relay's clone URL |
| 167 | // e) Release the state event from purgatory | 167 | // e) Release the state event from purgatory |
| 168 | |||
| 168 | let found = wait_for_event_served( | 169 | let found = wait_for_event_served( |
| 169 | archive_relay.url(), | 170 | archive_relay.url(), |
| 170 | &state_event_id, | 171 | &state_event_id, |
| @@ -267,11 +268,13 @@ async fn test_archive_read_only_creates_bare_repo() { | |||
| 267 | /// This verifies the security model: archive mode only syncs git data | 268 | /// This verifies the security model: archive mode only syncs git data |
| 268 | /// when there are state events to validate against. | 269 | /// when there are state events to validate against. |
| 269 | /// | 270 | /// |
| 270 | /// Scenario: | 271 | /// With announcement purgatory, the flow is: |
| 271 | /// 1. Start source relay with announcement only (no state events) | 272 | /// 1. Send announcement to source relay (goes to purgatory) |
| 272 | /// 2. Start archive relay syncing from source | 273 | /// 2. Send state event to source relay (goes to purgatory) |
| 273 | /// 3. Archive relay syncs announcement (creates bare repo) | 274 | /// 3. Push git data to source relay (promotes announcement and state event) |
| 274 | /// 4. Verify git data is NOT synced (no state events to trigger purgatory sync) | 275 | /// 4. Start archive relay with sync from source |
| 276 | /// 5. Archive relay syncs the promoted announcement | ||
| 277 | /// 6. Verify git data is NOT synced (archive has no state event to authorize git fetch) | ||
| 275 | #[tokio::test] | 278 | #[tokio::test] |
| 276 | async fn test_archive_without_state_events_does_not_sync_git() { | 279 | async fn test_archive_without_state_events_does_not_sync_git() { |
| 277 | // 1. Start source relay | 280 | // 1. Start source relay |
| @@ -290,7 +293,7 @@ async fn test_archive_without_state_events_does_not_sync_git() { | |||
| 290 | 293 | ||
| 291 | let npub = keys.public_key().to_bech32().expect("Failed to get npub"); | 294 | let npub = keys.public_key().to_bech32().expect("Failed to get npub"); |
| 292 | 295 | ||
| 293 | // 3. Create and send announcement listing BOTH relays (but NO state event) | 296 | // 3. Create and send announcement listing BOTH relays |
| 294 | let announcement = create_repo_announcement( | 297 | let announcement = create_repo_announcement( |
| 295 | &keys, | 298 | &keys, |
| 296 | &[&source_relay.domain(), &archive_domain], | 299 | &[&source_relay.domain(), &archive_domain], |
| @@ -306,7 +309,7 @@ async fn test_archive_without_state_events_does_not_sync_git() { | |||
| 306 | 309 | ||
| 307 | tokio::time::sleep(Duration::from_millis(500)).await; | 310 | tokio::time::sleep(Duration::from_millis(500)).await; |
| 308 | 311 | ||
| 309 | // Send announcement to source relay | 312 | // Send announcement to source relay (goes to purgatory) |
| 310 | source_client | 313 | source_client |
| 311 | .send_event(&announcement) | 314 | .send_event(&announcement) |
| 312 | .await | 315 | .await |
| @@ -314,11 +317,39 @@ async fn test_archive_without_state_events_does_not_sync_git() { | |||
| 314 | 317 | ||
| 315 | tokio::time::sleep(Duration::from_millis(200)).await; | 318 | tokio::time::sleep(Duration::from_millis(200)).await; |
| 316 | 319 | ||
| 317 | // 4. Push git data to source relay (but no state event to authorize it) | 320 | // 4. Create and send state event to source relay (goes to purgatory) |
| 318 | // This push will fail because there's no state event in purgatory | 321 | let clone_url = format!( |
| 319 | // That's expected - we're testing that archive mode doesn't blindly fetch git data | 322 | "http://{}/{}/{}.git", |
| 323 | source_relay.domain(), | ||
| 324 | npub, | ||
| 325 | identifier | ||
| 326 | ); | ||
| 327 | let relay_url = source_relay.url().to_string(); | ||
| 328 | |||
| 329 | let state_event = create_state_event( | ||
| 330 | &keys, | ||
| 331 | identifier, | ||
| 332 | &[("main", &commit_hash)], | ||
| 333 | &[], | ||
| 334 | &[&clone_url], | ||
| 335 | &[&relay_url], | ||
| 336 | ) | ||
| 337 | .expect("Failed to create state event"); | ||
| 338 | |||
| 339 | source_client | ||
| 340 | .send_event(&state_event) | ||
| 341 | .await | ||
| 342 | .expect("Failed to send state event to source"); | ||
| 343 | |||
| 344 | tokio::time::sleep(Duration::from_millis(200)).await; | ||
| 345 | |||
| 346 | // 5. Push git data to source relay (promotes announcement and state event) | ||
| 347 | push_to_relay(temp_dir.path(), &source_relay.domain(), &npub, identifier) | ||
| 348 | .expect("Push to source should succeed"); | ||
| 349 | |||
| 350 | tokio::time::sleep(Duration::from_millis(500)).await; | ||
| 320 | 351 | ||
| 321 | // 5. Start archive relay | 352 | // 6. Start archive relay (without state event - we don't send state event to archive) |
| 322 | let archive_relay = TestRelay::start_with_archive_and_sync( | 353 | let archive_relay = TestRelay::start_with_archive_and_sync( |
| 323 | archive_port, | 354 | archive_port, |
| 324 | Some(source_relay.url().to_string()), | 355 | Some(source_relay.url().to_string()), |
| @@ -333,10 +364,10 @@ async fn test_archive_without_state_events_does_not_sync_git() { | |||
| 333 | .await | 364 | .await |
| 334 | .expect("Sync connection should establish"); | 365 | .expect("Sync connection should establish"); |
| 335 | 366 | ||
| 336 | // Give time for any potential git sync to happen | 367 | // Give time for sync to fetch announcement |
| 337 | tokio::time::sleep(Duration::from_secs(3)).await; | 368 | tokio::time::sleep(Duration::from_secs(3)).await; |
| 338 | 369 | ||
| 339 | // 6. Verify bare repository was created (announcement was accepted) | 370 | // 7. Verify bare repository was created (announcement was synced and accepted to purgatory) |
| 340 | let repo_path = archive_relay | 371 | let repo_path = archive_relay |
| 341 | .git_data_path() | 372 | .git_data_path() |
| 342 | .join(format!("{}/{}.git", npub, identifier)); | 373 | .join(format!("{}/{}.git", npub, identifier)); |
| @@ -346,7 +377,7 @@ async fn test_archive_without_state_events_does_not_sync_git() { | |||
| 346 | "Bare repository should be created for archive announcement" | 377 | "Bare repository should be created for archive announcement" |
| 347 | ); | 378 | ); |
| 348 | 379 | ||
| 349 | // 7. Verify git data was NOT synced (no state events to trigger purgatory sync) | 380 | // 8. Verify git data was NOT synced (no state events on archive to trigger git fetch) |
| 350 | // Check that the commit does NOT exist in the archive relay's repo | 381 | // Check that the commit does NOT exist in the archive relay's repo |
| 351 | let output = tokio::process::Command::new("git") | 382 | let output = tokio::process::Command::new("git") |
| 352 | .args(["cat-file", "-t", &commit_hash]) | 383 | .args(["cat-file", "-t", &commit_hash]) |