Skip to content

Commit

Permalink
refactor: generate ts value separately
Browse files Browse the repository at this point in the history
  • Loading branch information
WenyXu committed May 27, 2024
1 parent 048368f commit 932c03f
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 37 deletions.
3 changes: 3 additions & 0 deletions tests-fuzz/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod select_expr;
use std::fmt;

use datatypes::data_type::ConcreteDataType;
use datatypes::types::TimestampType;
use datatypes::value::Value;
use rand::Rng;

Expand All @@ -40,6 +41,8 @@ pub type ConcreteDataTypeGenerator<R> = Box<dyn Random<ConcreteDataType, R>>;
pub type ValueGenerator<R> =
Box<dyn Fn(&mut R, &ConcreteDataType, Option<&dyn Random<Ident, R>>) -> Value>;

pub type TsValueGenerator<R> = Box<dyn Fn(&mut R, TimestampType) -> Value>;

pub trait Generator<T, R: Rng> {
type Error: Sync + Send + fmt::Debug;

Expand Down
23 changes: 16 additions & 7 deletions tests-fuzz/src/generator/insert_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ use derive_builder::Builder;
use rand::seq::SliceRandom;
use rand::Rng;

use super::TsValueGenerator;
use crate::context::TableContextRef;
use crate::error::{Error, Result};
use crate::fake::WordGenerator;
use crate::generator::{Generator, Random, ValueGenerator};
use crate::ir::insert_expr::{InsertIntoExpr, RowValue};
use crate::ir::{generate_random_value, Ident};
use crate::ir::{generate_random_timestamp, generate_random_value, Ident};

/// Generates [InsertIntoExpr].
#[derive(Builder)]
Expand All @@ -39,6 +40,8 @@ pub struct InsertExprGenerator<R: Rng + 'static> {
word_generator: Box<dyn Random<Ident, R>>,
#[builder(default = "Box::new(generate_random_value)")]
value_generator: ValueGenerator<R>,
#[builder(default = "Box::new(generate_random_timestamp)")]
ts_value_generator: TsValueGenerator<R>,
#[builder(default)]
_phantom: PhantomData<R>,
}
Expand Down Expand Up @@ -82,12 +85,18 @@ impl<R: Rng + 'static> Generator<InsertIntoExpr, R> for InsertExprGenerator<R> {
row.push(RowValue::Default);
continue;
}

row.push(RowValue::Value((self.value_generator)(
rng,
&column.column_type,
Some(self.word_generator.as_ref()),
)));
if column.is_time_index() {
row.push(RowValue::Value((self.ts_value_generator)(
rng,
column.timestamp_type().unwrap(),
)));
} else {
row.push(RowValue::Value((self.value_generator)(
rng,
&column.column_type,
Some(self.word_generator.as_ref()),
)));
}
}

values_list.push(row);
Expand Down
54 changes: 29 additions & 25 deletions tests-fuzz/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub(crate) mod select_expr;

use core::fmt;
use std::collections::HashMap;
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;

pub use alter_expr::AlterTableExpr;
use common_time::{Date, DateTime, Timestamp};
Expand Down Expand Up @@ -119,38 +121,31 @@ pub fn generate_random_value<R: Rng>(
},
ConcreteDataType::Date(_) => generate_random_date(rng),
ConcreteDataType::DateTime(_) => generate_random_datetime(rng),
&ConcreteDataType::Timestamp(ts_type) => generate_random_timestamp(rng, ts_type),

_ => unimplemented!("unsupported type: {datatype}"),
}
}

/// Generates a random [Value] for MySQL.
pub fn generate_random_value_for_mysql<R: Rng>(
rng: &mut R,
datatype: &ConcreteDataType,
random_str: Option<&dyn Random<Ident, R>>,
) -> Value {
match datatype {
&ConcreteDataType::Boolean(_) => Value::from(rng.gen::<bool>()),
ConcreteDataType::Int16(_) => Value::from(rng.gen::<i16>()),
ConcreteDataType::Int32(_) => Value::from(rng.gen::<i32>()),
ConcreteDataType::Int64(_) => Value::from(rng.gen::<i64>()),
ConcreteDataType::Float32(_) => Value::from(rng.gen::<f32>()),
ConcreteDataType::Float64(_) => Value::from(rng.gen::<f64>()),
ConcreteDataType::String(_) => match random_str {
Some(random) => Value::from(random.gen(rng).value),
None => Value::from(rng.gen::<char>().to_string()),
},
ConcreteDataType::Date(_) => generate_random_date(rng),
ConcreteDataType::DateTime(_) => generate_random_datetime(rng),
&ConcreteDataType::Timestamp(ts_type) => generate_random_timestamp_for_mysql(rng, ts_type),

_ => unimplemented!("unsupported type: {datatype}"),
/// Generate monotonically increasing timestamps for MySQL.
pub fn generate_unique_timestamp_for_mysql<R: Rng>(
base: i64,
) -> impl Fn(&mut R, TimestampType) -> Value {
let base = Arc::new(AtomicI64::new(base));

move |_rng, ts_type| -> Value {
let value = base.fetch_add(1, Ordering::Relaxed);
let v = match ts_type {
TimestampType::Second(_) => Timestamp::new_second(1 + value),
TimestampType::Millisecond(_) => Timestamp::new_millisecond(1000 + value),
TimestampType::Microsecond(_) => Timestamp::new_microsecond(1_000_000 + value),
TimestampType::Nanosecond(_) => Timestamp::new_nanosecond(1_000_000_000 + value),
};
Value::from(v)
}
}

fn generate_random_timestamp<R: Rng>(rng: &mut R, ts_type: TimestampType) -> Value {
/// Generate random timestamps.
pub fn generate_random_timestamp<R: Rng>(rng: &mut R, ts_type: TimestampType) -> Value {
let v = match ts_type {
TimestampType::Second(_) => {
let min = i64::from(Timestamp::MIN_SECOND);
Expand Down Expand Up @@ -181,7 +176,7 @@ fn generate_random_timestamp<R: Rng>(rng: &mut R, ts_type: TimestampType) -> Val
}

// MySQL supports timestamp from '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.499999'
fn generate_random_timestamp_for_mysql<R: Rng>(rng: &mut R, ts_type: TimestampType) -> Value {
pub fn generate_random_timestamp_for_mysql<R: Rng>(rng: &mut R, ts_type: TimestampType) -> Value {
let v = match ts_type {
TimestampType::Second(_) => {
let min = 1;
Expand Down Expand Up @@ -298,6 +293,15 @@ pub struct Column {
}

impl Column {
/// Returns [TimestampType] if it's [ColumnOption::TimeIndex] [Column].
pub fn timestamp_type(&self) -> Option<TimestampType> {
if let ConcreteDataType::Timestamp(ts_type) = self.column_type {
Some(ts_type)
} else {
None
}
}

/// Returns true if it's [ColumnOption::TimeIndex] [Column].
pub fn is_time_index(&self) -> bool {
self.options
Expand Down
7 changes: 4 additions & 3 deletions tests-fuzz/targets/fuzz_insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use tests_fuzz::generator::create_expr::CreateTableExprGeneratorBuilder;
use tests_fuzz::generator::insert_expr::InsertExprGeneratorBuilder;
use tests_fuzz::generator::Generator;
use tests_fuzz::ir::{
generate_random_value_for_mysql, replace_default, CreateTableExpr, InsertIntoExpr,
MySQLTsColumnTypeGenerator,
generate_random_timestamp_for_mysql, generate_random_value, replace_default, CreateTableExpr,
InsertIntoExpr, MySQLTsColumnTypeGenerator,
};
use tests_fuzz::translator::mysql::create_expr::CreateTableExprTranslator;
use tests_fuzz::translator::mysql::insert_expr::InsertIntoExprTranslator;
Expand Down Expand Up @@ -101,7 +101,8 @@ fn generate_insert_expr<R: Rng + 'static>(
.table_ctx(table_ctx)
.omit_column_list(omit_column_list)
.rows(input.rows)
.value_generator(Box::new(generate_random_value_for_mysql))
.value_generator(Box::new(generate_random_value))
.ts_value_generator(Box::new(generate_random_timestamp_for_mysql))
.build()
.unwrap();
insert_generator.generate(rng)
Expand Down
6 changes: 4 additions & 2 deletions tests-fuzz/targets/fuzz_insert_logical_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use tests_fuzz::generator::create_expr::{
use tests_fuzz::generator::insert_expr::InsertExprGeneratorBuilder;
use tests_fuzz::generator::Generator;
use tests_fuzz::ir::{
generate_random_value_for_mysql, replace_default, CreateTableExpr, InsertIntoExpr,
generate_random_timestamp_for_mysql, generate_random_value, replace_default, CreateTableExpr,
InsertIntoExpr,
};
use tests_fuzz::translator::mysql::create_expr::CreateTableExprTranslator;
use tests_fuzz::translator::mysql::insert_expr::InsertIntoExprTranslator;
Expand Down Expand Up @@ -112,7 +113,8 @@ fn generate_insert_expr<R: Rng + 'static>(
.omit_column_list(false)
.table_ctx(table_ctx)
.rows(rows)
.value_generator(Box::new(generate_random_value_for_mysql))
.value_generator(Box::new(generate_random_value))
.ts_value_generator(Box::new(generate_random_timestamp_for_mysql))
.build()
.unwrap();
insert_generator.generate(rng)
Expand Down

0 comments on commit 932c03f

Please sign in to comment.