refactor(fuzz-tests): generate ts value separately (#4056)

refactor: generate ts value separately
This commit is contained in:
Weny Xu
2024-05-27 23:07:32 +09:00
committed by GitHub
parent 048368fd87
commit 097f62f459
5 changed files with 55 additions and 36 deletions

View File

@@ -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;
@@ -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;

View File

@@ -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)]
@@ -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>,
}
@@ -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);

View File

@@ -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};
@@ -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),
/// 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));
_ => unimplemented!("unsupported type: {datatype}"),
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);
@@ -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;
@@ -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

View File

@@ -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;
@@ -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)

View File

@@ -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;
@@ -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)