feat(fuzz): add validator for inserted rows (#3932)

* feat(fuzz): add validator for inserted rows

* fix: compatibility with mysql types

* feat(fuzz): add datetime and date type in mysql for row validator
This commit is contained in:
Yohan Wal
2024-05-15 15:05:51 +08:00
committed by GitHub
parent 09129a911e
commit cfae276d37
11 changed files with 373 additions and 14 deletions

View File

@@ -32,11 +32,14 @@ use tests_fuzz::fake::{
use tests_fuzz::generator::create_expr::CreateTableExprGeneratorBuilder;
use tests_fuzz::generator::insert_expr::InsertExprGeneratorBuilder;
use tests_fuzz::generator::Generator;
use tests_fuzz::ir::{CreateTableExpr, InsertIntoExpr};
use tests_fuzz::ir::{
generate_random_value_for_mysql, CreateTableExpr, InsertIntoExpr, MySQLTsColumnTypeGenerator,
};
use tests_fuzz::translator::mysql::create_expr::CreateTableExprTranslator;
use tests_fuzz::translator::mysql::insert_expr::InsertIntoExprTranslator;
use tests_fuzz::translator::DslTranslator;
use tests_fuzz::utils::{init_greptime_connections_via_env, Connections};
use tests_fuzz::validator;
struct FuzzContext {
greptime: Pool<MySql>,
@@ -80,6 +83,7 @@ fn generate_create_expr<R: Rng + 'static>(
)))
.columns(input.columns)
.engine("mito")
.ts_column_type_generator(Box::new(MySQLTsColumnTypeGenerator))
.build()
.unwrap();
create_table_generator.generate(rng)
@@ -96,6 +100,7 @@ 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))
.build()
.unwrap();
insert_generator.generate(rng)
@@ -135,7 +140,37 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
}
);
// TODO: Validate inserted rows
// Validate inserted rows
let ts_column_idx = create_expr
.columns
.iter()
.position(|c| c.is_time_index())
.unwrap();
let ts_column_name = create_expr.columns[ts_column_idx].name.clone();
let ts_column_idx_in_insert = insert_expr
.columns
.iter()
.position(|c| c.name == ts_column_name)
.unwrap();
let column_list = insert_expr
.columns
.iter()
.map(|c| c.name.to_string())
.collect::<Vec<_>>()
.join(", ")
.to_string();
let select_sql = format!(
"SELECT {} FROM {} ORDER BY {}",
column_list, create_expr.table_name, ts_column_name
);
let fetched_rows = validator::row::fetch_values(&ctx.greptime, select_sql.as_str()).await?;
let mut expected_rows = insert_expr.values_list;
expected_rows.sort_by(|a, b| {
a[ts_column_idx_in_insert]
.cmp(&b[ts_column_idx_in_insert])
.unwrap()
});
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
// Cleans up
let sql = format!("DROP TABLE {}", create_expr.table_name);

View File

@@ -34,11 +34,12 @@ use tests_fuzz::generator::create_expr::{
};
use tests_fuzz::generator::insert_expr::InsertExprGeneratorBuilder;
use tests_fuzz::generator::Generator;
use tests_fuzz::ir::{CreateTableExpr, InsertIntoExpr};
use tests_fuzz::ir::{generate_random_value_for_mysql, CreateTableExpr, InsertIntoExpr};
use tests_fuzz::translator::mysql::create_expr::CreateTableExprTranslator;
use tests_fuzz::translator::mysql::insert_expr::InsertIntoExprTranslator;
use tests_fuzz::translator::DslTranslator;
use tests_fuzz::utils::{init_greptime_connections_via_env, Connections};
use tests_fuzz::validator;
struct FuzzContext {
greptime: Pool<MySql>,
@@ -107,6 +108,7 @@ fn generate_insert_expr<R: Rng + 'static>(
.omit_column_list(false)
.table_ctx(table_ctx)
.rows(input.rows)
.value_generator(Box::new(generate_random_value_for_mysql))
.build()
.unwrap();
insert_generator.generate(rng)
@@ -160,7 +162,39 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
}
);
// TODO: Validate inserted rows
// Validate inserted rows
let ts_column_idx = create_logical_table_expr
.columns
.iter()
.position(|c| c.is_time_index())
.unwrap();
let ts_column_name = create_logical_table_expr.columns[ts_column_idx]
.name
.clone();
let ts_column_idx_in_insert = insert_expr
.columns
.iter()
.position(|c| c.name == ts_column_name)
.unwrap();
let column_list = insert_expr
.columns
.iter()
.map(|c| c.name.to_string())
.collect::<Vec<_>>()
.join(", ")
.to_string();
let select_sql = format!(
"SELECT {} FROM {} ORDER BY {}",
column_list, create_logical_table_expr.table_name, ts_column_name
);
let fetched_rows = validator::row::fetch_values(&ctx.greptime, select_sql.as_str()).await?;
let mut expected_rows = insert_expr.values_list;
expected_rows.sort_by(|a, b| {
a[ts_column_idx_in_insert]
.cmp(&b[ts_column_idx_in_insert])
.unwrap()
});
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
// Clean up logical table
let sql = format!("DROP TABLE {}", create_logical_table_expr.table_name);