use rand::prelude::*;
use rand_chacha::ChaCha8Rng;
pub const DEFAULT_TABLE_SIZE: usize = 10_000;
pub struct SysbenchData {
rng: ChaCha8Rng,
table_size: usize,
next_id: i64,
}
impl SysbenchData {
pub fn new(table_size: usize) -> Self {
Self {
rng: ChaCha8Rng::seed_from_u64(42), table_size,
next_id: 1,
}
}
pub fn table_size(&self) -> usize {
self.table_size
}
pub fn next_row(&mut self) -> Option<(i64, i64, String, String)> {
if self.next_id as usize > self.table_size {
return None;
}
let id = self.next_id;
self.next_id += 1;
let k = self.rng.random_range(1..=self.table_size as i64);
let c = self.generate_c_string();
let pad = self.generate_pad_string();
Some((id, k, c, pad))
}
fn generate_c_string(&mut self) -> String {
let mut s = String::with_capacity(120);
for i in 0..11 {
for _ in 0..10 {
s.push((b'0' + self.rng.random_range(0..10)) as char);
}
if i < 10 {
s.push('-');
}
}
s
}
fn generate_pad_string(&mut self) -> String {
let mut s = String::with_capacity(60);
for i in 0..5 {
for _ in 0..10 {
s.push((b'0' + self.rng.random_range(0..10)) as char);
}
if i < 4 {
s.push('-');
}
}
while s.len() < 60 {
s.push(' ');
}
s
}
pub fn random_id(&mut self) -> i64 {
self.rng.random_range(1..=self.table_size as i64)
}
pub fn random_k(&mut self) -> i64 {
self.rng.random_range(1..=self.table_size as i64)
}
pub fn random_ids(&mut self, count: usize) -> Vec<i64> {
(0..count).map(|_| self.rng.random_range(1..=self.table_size as i64)).collect()
}
pub fn random_range(&mut self, range_size: usize) -> (i64, i64) {
let effective_range = range_size.min(self.table_size);
let max_start = self.table_size.saturating_sub(effective_range).saturating_add(1).max(1);
let start = self.rng.random_range(1..=max_start as i64);
(start, start + effective_range as i64 - 1)
}
pub fn reset(&mut self) {
self.rng = ChaCha8Rng::seed_from_u64(42);
self.next_id = 1;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_generation() {
let mut data = SysbenchData::new(100);
let row = data.next_row().unwrap();
assert_eq!(row.0, 1); assert!(row.1 >= 1 && row.1 <= 100); assert_eq!(row.2.len(), 120); assert_eq!(row.3.len(), 60); }
#[test]
fn test_deterministic() {
let mut data1 = SysbenchData::new(100);
let mut data2 = SysbenchData::new(100);
let row1 = data1.next_row().unwrap();
let row2 = data2.next_row().unwrap();
assert_eq!(row1, row2);
}
#[test]
fn test_table_size() {
let mut data = SysbenchData::new(10);
for i in 1..=10 {
let row = data.next_row();
assert!(row.is_some());
assert_eq!(row.unwrap().0, i);
}
assert!(data.next_row().is_none());
}
#[test]
fn test_random_ids() {
let mut data = SysbenchData::new(100);
let ids = data.random_ids(5);
assert_eq!(ids.len(), 5);
for id in ids {
assert!(id >= 1 && id <= 100);
}
}
#[test]
fn test_random_range() {
let mut data = SysbenchData::new(100);
let (start, end) = data.random_range(10);
assert!(start >= 1);
assert!(end <= 100);
assert_eq!(end - start + 1, 10);
}
}