// benches/common/data_generator.rs use rand::{Rng, SeedableRng}; use rand::rngs::StdRng; /// Deterministic data generator for benchmarks pub struct DataGenerator { rng: StdRng, } impl DataGenerator { /// Create a new data generator with a fixed seed for reproducibility pub fn new(seed: u64) -> Self { Self { rng: StdRng::seed_from_u64(seed), } } /// Generate a single key with the given prefix and ID pub fn generate_key(&self, prefix: &str, id: usize) -> String { format!("{}:{:08}", prefix, id) } /// Generate a random string value of the specified size pub fn generate_value(&mut self, size: usize) -> String { const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; (0..size) .map(|_| { let idx = self.rng.gen_range(0..CHARSET.len()); CHARSET[idx] as char }) .collect() } /// Generate a batch of key-value pairs pub fn generate_string_pairs(&mut self, count: usize, value_size: usize) -> Vec<(String, String)> { (0..count) .map(|i| { let key = self.generate_key("bench:key", i); let value = self.generate_value(value_size); (key, value) }) .collect() } /// Generate hash data (key -> field-value pairs) pub fn generate_hash_data(&mut self, num_hashes: usize, fields_per_hash: usize, value_size: usize) -> Vec<(String, Vec<(String, String)>)> { (0..num_hashes) .map(|i| { let hash_key = self.generate_key("bench:hash", i); let fields: Vec<(String, String)> = (0..fields_per_hash) .map(|j| { let field = format!("field{}", j); let value = self.generate_value(value_size); (field, value) }) .collect(); (hash_key, fields) }) .collect() } /// Generate list data (key -> list of elements) pub fn generate_list_data(&mut self, num_lists: usize, elements_per_list: usize, element_size: usize) -> Vec<(String, Vec)> { (0..num_lists) .map(|i| { let list_key = self.generate_key("bench:list", i); let elements: Vec = (0..elements_per_list) .map(|_| self.generate_value(element_size)) .collect(); (list_key, elements) }) .collect() } /// Generate keys for pattern matching tests pub fn generate_pattern_keys(&mut self, count: usize) -> Vec { let mut keys = Vec::new(); // Generate keys with different patterns for i in 0..count / 3 { keys.push(format!("user:{}:profile", i)); } for i in 0..count / 3 { keys.push(format!("session:{}:data", i)); } for i in 0..count / 3 { keys.push(format!("cache:{}:value", i)); } keys } } #[cfg(test)] mod tests { use super::*; #[test] fn test_deterministic_generation() { let mut generator1 = DataGenerator::new(42); let mut generator2 = DataGenerator::new(42); let pairs1 = generator1.generate_string_pairs(10, 50); let pairs2 = generator2.generate_string_pairs(10, 50); assert_eq!(pairs1, pairs2, "Same seed should produce same data"); } #[test] fn test_value_size() { let mut generator = DataGenerator::new(42); let value = generator.generate_value(100); assert_eq!(value.len(), 100); } #[test] fn test_hash_generation() { let mut generator = DataGenerator::new(42); let hashes = generator.generate_hash_data(5, 10, 50); assert_eq!(hashes.len(), 5); for (_, fields) in hashes { assert_eq!(fields.len(), 10); for (_, value) in fields { assert_eq!(value.len(), 50); } } } }