()
| 530 | |
| 531 | #[test] |
| 532 | fn encryption_persists_across_segments() { |
| 533 | // Rewritten: actually decrypts across a simulated restart. |
| 534 | // |
| 535 | // Lifecycle: |
| 536 | // 1. Write 10 records with encryption, forcing segment rollover. |
| 537 | // 2. Drop the WAL (simulating process exit). |
| 538 | // 3. Reopen a new reader and replay — records are marked encrypted. |
| 539 | // 4. For each segment, open the reader, read its preamble epoch, and |
| 540 | // decrypt each record using that epoch. Verify payloads match. |
| 541 | let dir = tempfile::tempdir().unwrap(); |
| 542 | let wal_dir = dir.path().join("wal"); |
| 543 | let key_bytes = [42u8; 32]; |
| 544 | |
| 545 | let config = SegmentedWalConfig { |
| 546 | wal_dir: wal_dir.clone(), |
| 547 | segment_target_size: 100, |
| 548 | writer_config: WalWriterConfig { |
| 549 | use_direct_io: false, |
| 550 | ..Default::default() |
| 551 | }, |
| 552 | }; |
| 553 | |
| 554 | // Step 1 & 2: write and drop. |
| 555 | { |
| 556 | let key = crate::crypto::WalEncryptionKey::from_bytes(&key_bytes).unwrap(); |
| 557 | let ring = crate::crypto::KeyRing::new(key); |
| 558 | let mut wal = SegmentedWal::open(config.clone()).unwrap(); |
| 559 | wal.set_encryption_ring(ring).unwrap(); |
| 560 | |
| 561 | for i in 0..10u32 { |
| 562 | wal.append( |
| 563 | RecordType::Put as u32, |
| 564 | 1, |
| 565 | 0, |
| 566 | 0, |
| 567 | format!("enc-{i}").as_bytes(), |
| 568 | ) |
| 569 | .unwrap(); |
| 570 | wal.sync().unwrap(); |
| 571 | } |
| 572 | assert!(wal.list_segments().unwrap().len() > 1); |
| 573 | } |
| 574 | |
| 575 | // Step 3: reopen WAL (new in-memory epoch, simulates restart). |
| 576 | let segments = crate::segment::discover_segments(&wal_dir).unwrap(); |
| 577 | assert!( |
| 578 | segments.len() > 1, |
| 579 | "expected multiple segments after rollover" |
| 580 | ); |
| 581 | |
| 582 | let key_for_read = crate::crypto::WalEncryptionKey::from_bytes(&key_bytes).unwrap(); |
| 583 | let ring_for_read = crate::crypto::KeyRing::new(key_for_read); |
| 584 | |
| 585 | let mut all_payloads = Vec::new(); |
| 586 | |
| 587 | // Step 4: per-segment read + decrypt. |
| 588 | for seg in &segments { |
| 589 | let reader = crate::reader::WalReader::open(&seg.path).unwrap(); |
nothing calls this directly
no test coverage detected