mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-22 22:20:02 +00:00
refactor(fuzz-tests): generate ts value separately (#4056)
refactor: generate ts value separately
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user