mirror of
https://github.com/qdrant/qdrant.git
synced 2026-07-30 22:51:00 -05:00
* [ai] Replace manual into mappings with Into::into * Reformat * [ai] Use implicit .iter * Don't iterate over keys too * [ai] Replace unwrap_or * Reformat * [ai] Use as_deref and then_some * [ai] Use more to_string * [ai] Use explicitly typed into conversions * Reformat * [ai] More explicit into conversions * Reformat
70 lines
2.2 KiB
Rust
70 lines
2.2 KiB
Rust
//! Simulates a process crash while writing to a write ahead log segment.
|
|
//!
|
|
//! Steps:
|
|
//!
|
|
//! 1. The test process creates a seed and a temporary directory
|
|
//! 2. The test process creates a subprocess with the seed and directory as
|
|
//! arguments.
|
|
//! 3. The subprocess creates a segment in the directory, and appends entries to
|
|
//! the segment based on the seed.
|
|
//! 4. The subprocess aborts without closing resources or cleaning up state.
|
|
//! 5. The test process reads the entries from the segment, ensuring that no
|
|
//! corruption or data loss has occurred.
|
|
|
|
use std::collections::HashMap;
|
|
use std::{env, process};
|
|
|
|
use rand::Rng;
|
|
use tempfile::Builder;
|
|
use wal::test_utils::EntryGenerator;
|
|
|
|
const SEGMENT_CAPACITY: usize = 32 * 1024 * 1024;
|
|
const EXIT_CODE: i32 = 42;
|
|
|
|
#[test]
|
|
fn process_crash() {
|
|
let vars: HashMap<String, String> = env::vars().collect();
|
|
if vars.contains_key("SEED") && vars.contains_key("SEGMENT_PATH") {
|
|
let seed: usize = vars["SEED"].parse().unwrap();
|
|
let path = vars["SEGMENT_PATH"].clone();
|
|
subprocess(path, seed);
|
|
} else {
|
|
test()
|
|
}
|
|
}
|
|
|
|
fn test() {
|
|
let tempdir = Builder::new().prefix("segment").tempdir().unwrap();
|
|
let seed: usize = rand::rng().next_u32() as usize;
|
|
let path = tempdir.path().join("segment");
|
|
|
|
println!("Spawning subprocess; path: {path:?}; seed: {seed}");
|
|
|
|
let exit_code = process::Command::new(env::current_exe().unwrap())
|
|
.env("SEED", seed.to_string())
|
|
.env("SEGMENT_PATH", format!("{}", path.display()))
|
|
.status()
|
|
.unwrap()
|
|
.code()
|
|
.unwrap();
|
|
|
|
assert_eq!(EXIT_CODE, exit_code);
|
|
|
|
let segment = wal::Segment::open(path).unwrap();
|
|
let entries = EntryGenerator::with_seed_and_segment_capacity(seed, SEGMENT_CAPACITY);
|
|
|
|
for (i, entry) in entries.into_iter().enumerate() {
|
|
assert_eq!(&entry[..], &*segment.entry(i).unwrap());
|
|
}
|
|
}
|
|
|
|
fn subprocess(path: String, seed: usize) {
|
|
let mut segment = wal::Segment::create(path, SEGMENT_CAPACITY).unwrap();
|
|
|
|
for entry in EntryGenerator::with_seed_and_segment_capacity(seed, SEGMENT_CAPACITY) {
|
|
segment.append(&entry).expect("segment capacity exhausted");
|
|
}
|
|
|
|
process::exit(EXIT_CODE);
|
|
}
|