1pub mod cluster_info;
16pub mod config;
17pub mod crd;
18pub mod csv_dump_writer;
20pub mod health;
21pub mod migration;
22pub mod network_chaos;
23pub mod partition;
24pub mod pod_failure;
25pub mod procedure;
26#[cfg(feature = "unstable")]
27pub mod process;
28pub mod retry;
29pub mod sql_dump_writer;
31pub mod wait;
32
33use std::env;
34use std::str::FromStr;
35
36use common_base::readable_size::ReadableSize;
37use common_telemetry::info;
38use common_telemetry::tracing::log::LevelFilter;
39use paste::paste;
40use snafu::ResultExt;
41use sqlx::mysql::{MySqlConnectOptions, MySqlPoolOptions};
42use sqlx::{ConnectOptions, MySql, Pool};
43
44use crate::error::{self, Result};
45use crate::ir::Ident;
46
47pub struct Connections {
49 pub mysql: Option<Pool<MySql>>,
50}
51
52const GT_MYSQL_ADDR: &str = "GT_MYSQL_ADDR";
53
54pub async fn init_greptime_connections_via_env() -> Connections {
56 crate::install_rustls_crypto_provider();
57
58 let _ = dotenv::dotenv();
59 let mysql = if let Ok(addr) = env::var(GT_MYSQL_ADDR) {
60 Some(addr)
61 } else {
62 info!("GT_MYSQL_ADDR is empty, ignores test");
63 None
64 };
65
66 init_greptime_connections(mysql).await
67}
68
69pub async fn init_greptime_connections(mysql: Option<String>) -> Connections {
71 let mysql = if let Some(addr) = mysql {
72 let opts = format!("mysql://{addr}/public")
73 .parse::<MySqlConnectOptions>()
74 .unwrap()
75 .log_statements(LevelFilter::Off);
76
77 Some(MySqlPoolOptions::new().connect_with(opts).await.unwrap())
78 } else {
79 None
80 };
81
82 Connections { mysql }
83}
84
85const GT_FUZZ_BINARY_PATH: &str = "GT_FUZZ_BINARY_PATH";
86const GT_FUZZ_INSTANCE_ROOT_DIR: &str = "GT_FUZZ_INSTANCE_ROOT_DIR";
87
88pub struct UnstableTestVariables {
90 pub binary_path: String,
91 pub root_dir: Option<String>,
92}
93
94pub fn load_unstable_test_env_variables() -> UnstableTestVariables {
96 let _ = dotenv::dotenv();
97 let binary_path = env::var(GT_FUZZ_BINARY_PATH).expect("GT_FUZZ_BINARY_PATH not found");
98 let root_dir = env::var(GT_FUZZ_INSTANCE_ROOT_DIR).ok();
99
100 UnstableTestVariables {
101 binary_path,
102 root_dir,
103 }
104}
105
106pub const GT_FUZZ_CLUSTER_NAMESPACE: &str = "GT_FUZZ_CLUSTER_NAMESPACE";
107pub const GT_FUZZ_CLUSTER_NAME: &str = "GT_FUZZ_CLUSTER_NAME";
108
109pub async fn flush_memtable(e: &Pool<MySql>, table_name: &Ident) -> Result<()> {
111 let sql = format!("admin flush_table(\"{}\")", table_name);
112 let result = sqlx::query(&sql)
113 .execute(e)
114 .await
115 .context(error::ExecuteQuerySnafu { sql })?;
116 info!("Flush table: {}\n\nResult: {result:?}\n\n", table_name);
117
118 Ok(())
119}
120
121pub async fn compact_table(e: &Pool<MySql>, table_name: &Ident) -> Result<()> {
123 let sql = format!("admin compact_table(\"{}\")", table_name);
124 let result = sqlx::query(&sql)
125 .execute(e)
126 .await
127 .context(error::ExecuteQuerySnafu { sql })?;
128 info!("Compact table: {}\n\nResult: {result:?}\n\n", table_name);
129
130 Ok(())
131}
132
133pub const GT_FUZZ_INPUT_MAX_ROWS: &str = "GT_FUZZ_INPUT_MAX_ROWS";
134pub const GT_FUZZ_INPUT_MAX_TABLES: &str = "GT_FUZZ_INPUT_MAX_TABLES";
135pub const GT_FUZZ_INPUT_MAX_COLUMNS: &str = "GT_FUZZ_INPUT_MAX_COLUMNS";
136pub const GT_FUZZ_INPUT_MAX_ALTER_ACTIONS: &str = "GT_FUZZ_INPUT_MAX_ALTER_ACTIONS";
137pub const GT_FUZZ_INPUT_MAX_INSERT_ACTIONS: &str = "GT_FUZZ_INPUT_MAX_INSERT_ACTIONS";
138pub const FUZZ_OVERRIDE_PREFIX: &str = "GT_FUZZ_OVERRIDE_";
139pub const GT_FUZZ_DUMP_TABLE_CSV: &str = "GT_FUZZ_DUMP_TABLE_CSV";
141pub const GT_FUZZ_DUMP_DIR: &str = "GT_FUZZ_DUMP_DIR";
143pub const GT_FUZZ_DUMP_SUFFIX: &str = "GT_FUZZ_DUMP_SUFFIX";
145pub const GT_FUZZ_DUMP_BUFFER_MAX_BYTES: &str = "GT_FUZZ_DUMP_BUFFER_MAX_BYTES";
147
148pub fn get_fuzz_override<T>(name: &str) -> Option<T>
150where
151 T: std::str::FromStr,
152{
153 let _ = dotenv::dotenv();
154 let key = format!("{}{}", FUZZ_OVERRIDE_PREFIX, name.to_ascii_uppercase());
155 env::var(&key).ok().and_then(|v| v.parse().ok())
156}
157
158pub fn get_gt_fuzz_dump_dir() -> String {
160 let _ = dotenv::dotenv();
161 env::var(GT_FUZZ_DUMP_DIR).unwrap_or_else(|_| "/tmp/greptime-fuzz-dumps".to_string())
162}
163
164pub fn get_gt_fuzz_dump_suffix() -> String {
166 let _ = dotenv::dotenv();
167 env::var(GT_FUZZ_DUMP_SUFFIX).unwrap_or_else(|_| ".repartition-metric-csv".to_string())
168}
169
170pub fn get_gt_fuzz_dump_buffer_max_bytes() -> usize {
172 let _ = dotenv::dotenv();
173 env::var(GT_FUZZ_DUMP_BUFFER_MAX_BYTES)
174 .ok()
175 .and_then(|value| {
176 value.parse::<usize>().ok().or_else(|| {
177 ReadableSize::from_str(&value)
178 .ok()
179 .map(|size| size.as_bytes() as usize)
180 })
181 })
182 .unwrap_or(8 * 1024 * 1024)
183}
184
185macro_rules! make_get_from_env_helper {
186 ($key:expr, $default: expr) => {
187 paste! {
188 #[doc = "Retrieves `" $key "` environment variable \
189 or returns a default value (`" $default "`) if the environment variable is not set.
190 "]
191 pub fn [<get_ $key:lower>]() -> usize {
192 get_from_env_or_default_value($key, $default)
193 }
194 }
195 };
196}
197
198make_get_from_env_helper!(GT_FUZZ_INPUT_MAX_ALTER_ACTIONS, 256);
199make_get_from_env_helper!(GT_FUZZ_INPUT_MAX_INSERT_ACTIONS, 4);
200make_get_from_env_helper!(GT_FUZZ_INPUT_MAX_ROWS, 512);
201make_get_from_env_helper!(GT_FUZZ_INPUT_MAX_TABLES, 32);
202make_get_from_env_helper!(GT_FUZZ_INPUT_MAX_COLUMNS, 16);
203
204fn get_from_env_or_default_value(key: &str, default_value: usize) -> usize {
207 let _ = dotenv::dotenv();
208 if let Ok(value) = env::var(key) {
209 value.parse().unwrap()
210 } else {
211 default_value
212 }
213}