Skip to content

Commit

Permalink
feat(tests-fuzz): add CreateTableExprGenerator & AlterTableExprGenera…
Browse files Browse the repository at this point in the history
…tor (#3182)

* feat(tests-fuzz): add CreateTableExprGenerator

* refactor: move Column to root of ir mod

* feat: add AlterTableExprGenerator

* feat: add Serialize and Deserialize derive

* chore: refactor the AlterExprGenerator
  • Loading branch information
WenyXu authored Jan 19, 2024
1 parent 5e89472 commit 440cd00
Show file tree
Hide file tree
Showing 12 changed files with 777 additions and 3 deletions.
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/partition/src/partition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub enum PartitionBound {
MaxValue,
}

#[derive(Debug)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PartitionDef {
partition_columns: Vec<String>,
partition_bounds: Vec<PartitionBound>,
Expand Down
12 changes: 12 additions & 0 deletions tests-fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ license.workspace = true

[dependencies]
async-trait = { workspace = true }
common-error = { workspace = true }
common-macro = { workspace = true }
common-query = { workspace = true }
datatypes = { workspace = true }
derive_builder = { workspace = true }
faker_rand = "0.1"
lazy_static = { workspace = true }
partition = { workspace = true }
rand = { workspace = true }
serde = { workspace = true }
snafu = { workspace = true }
sql = { workspace = true }
37 changes: 37 additions & 0 deletions tests-fuzz/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,40 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;

use partition::partition::PartitionDef;

use crate::ir::{Column, CreateTableExpr};

pub type TableContextRef = Arc<TableContext>;

/// TableContext stores table info.
pub struct TableContext {
pub name: String,
pub columns: Vec<Column>,

// GreptimeDB specific options
pub partitions: Vec<PartitionDef>,
pub primary_keys: Vec<usize>,
}

impl From<&CreateTableExpr> for TableContext {
fn from(
CreateTableExpr {
name,
columns,
partitions,
primary_keys,
..
}: &CreateTableExpr,
) -> Self {
Self {
name: name.to_string(),
columns: columns.clone(),
partitions: partitions.clone(),
primary_keys: primary_keys.clone(),
}
}
}
41 changes: 41 additions & 0 deletions tests-fuzz/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use common_macro::stack_trace_debug;
use snafu::{Location, Snafu};

use crate::ir::create_expr::CreateTableExprBuilderError;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Snafu)]
#[snafu(visibility(pub))]
#[stack_trace_debug]
pub enum Error {
#[snafu(display("Unexpected, violated: {violated}"))]
Unexpected {
violated: String,
location: Location,
},

#[snafu(display("Failed to build create table expr"))]
BuildCreateTableExpr {
#[snafu(source)]
error: CreateTableExprBuilderError,
location: Location,
},

#[snafu(display("No droppable columns"))]
DroppableColumns { location: Location },
}
14 changes: 12 additions & 2 deletions tests-fuzz/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod alter_expr;
pub mod create_expr;

use std::fmt;

#[async_trait::async_trait]
use crate::error::Error;
use crate::ir::{AlterTableExpr, CreateTableExpr};

pub type CreateTableExprGenerator =
Box<dyn Generator<CreateTableExpr, Error = Error> + Sync + Send>;

pub type AlterTableExprGenerator = Box<dyn Generator<AlterTableExpr, Error = Error> + Sync + Send>;

pub(crate) trait Generator<T> {
type Error: Sync + Send + fmt::Debug;

async fn generate(&self) -> Result<T, Self::Error>;
fn generate(&self) -> Result<T, Self::Error>;
}
168 changes: 168 additions & 0 deletions tests-fuzz/src/generator/alter_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::f64::consts::E;
use std::sync::Arc;

use common_query::AddColumnLocation;
use faker_rand::lorem::Word;
use rand::{random, Rng};
use snafu::ensure;

use crate::context::TableContextRef;
use crate::error::{self, Error, Result};
use crate::generator::Generator;
use crate::ir::alter_expr::{AlterTableExpr, AlterTableOperation};
use crate::ir::{droppable_columns, Column};

/// Generates the [AlterTableOperation::AddColumn] of [AlterTableExpr].
pub struct AlterExprAddColumnGenerator {
table_ctx: TableContextRef,
location: bool,
}

impl AlterExprAddColumnGenerator {
/// Returns an [AlterExprAddColumnGenerator].
pub fn new(table_ctx: &TableContextRef) -> Self {
Self {
table_ctx: table_ctx.clone(),
location: false,
}
}

/// Sets true to generate alter expr with a specific location.
pub fn with_location(mut self, v: bool) -> Self {
self.location = v;
self
}
}

impl Generator<AlterTableExpr> for AlterExprAddColumnGenerator {
type Error = Error;

fn generate(&self) -> Result<AlterTableExpr> {
let mut rng = rand::thread_rng();
let with_location = self.location && rng.gen::<bool>();
let location = if with_location {
let use_first = rng.gen::<bool>();
let location = if use_first {
AddColumnLocation::First
} else {
AddColumnLocation::After {
column_name: self.table_ctx.columns
[rng.gen_range(0..self.table_ctx.columns.len())]
.name
.to_string(),
}
};
Some(location)
} else {
None
};

let column = rng.gen::<Column>();
Ok(AlterTableExpr {
name: self.table_ctx.name.to_string(),
alter_options: AlterTableOperation::AddColumn { column, location },
})
}
}

/// Generates the [AlterTableOperation::DropColumn] of [AlterTableExpr].
pub struct AlterExprDropColumnGenerator {
table_ctx: TableContextRef,
}

impl AlterExprDropColumnGenerator {
/// Returns an [AlterExprDropColumnGenerator].
pub fn new(table_ctx: &TableContextRef) -> Self {
Self {
table_ctx: table_ctx.clone(),
}
}
}

impl Generator<AlterTableExpr> for AlterExprDropColumnGenerator {
type Error = Error;

fn generate(&self) -> Result<AlterTableExpr> {
let mut rng = rand::thread_rng();
let droppable = droppable_columns(&self.table_ctx.columns);
ensure!(!droppable.is_empty(), error::DroppableColumnsSnafu);
let name = droppable[rng.gen_range(0..droppable.len())]
.name
.to_string();
Ok(AlterTableExpr {
name: self.table_ctx.name.to_string(),
alter_options: AlterTableOperation::DropColumn { name },
})
}
}

pub struct AlterExprRenameGenerator {
table_ctx: TableContextRef,
}

impl AlterExprRenameGenerator {
/// Returns an [AlterExprRenameGenerator].
pub fn new(table_ctx: &TableContextRef) -> Self {
Self {
table_ctx: table_ctx.clone(),
}
}
}

impl Generator<AlterTableExpr> for AlterExprRenameGenerator {
type Error = Error;

fn generate(&self) -> Result<AlterTableExpr> {
let mut rng = rand::thread_rng();
let mut new_table_name = rng.gen::<Word>().to_string();
Ok(AlterTableExpr {
name: self.table_ctx.name.to_string(),
alter_options: AlterTableOperation::RenameTable { new_table_name },
})
}
}

#[cfg(test)]
mod tests {
use std::sync::Arc;

use super::*;
use crate::context::TableContext;
use crate::generator::create_expr::CreateTableExprGenerator;
use crate::generator::Generator;

#[test]
fn test_alter_table_expr_generator() {
let create_expr = CreateTableExprGenerator::default()
.columns(10)
.generate()
.unwrap();
let table_ctx = Arc::new(TableContext::from(&create_expr));

let alter_expr = AlterExprAddColumnGenerator::new(&table_ctx)
.generate()
.unwrap();

let alter_expr = AlterExprRenameGenerator::new(&table_ctx)
.generate()
.unwrap();

let alter_expr = AlterExprDropColumnGenerator::new(&table_ctx)
.generate()
.unwrap();
}
}
Loading

0 comments on commit 440cd00

Please sign in to comment.