1use std::env;
16use std::fmt::Display;
17use std::net::SocketAddr;
18use std::sync::Arc;
19
20use auth::{DefaultPermissionChecker, PermissionCheckerRef, UserProviderRef};
21use axum::Router;
22use catalog::kvbackend::KvBackendCatalogManager;
23use common_base::Plugins;
24use common_config::Configurable;
25use common_meta::key::catalog_name::CatalogNameKey;
26use common_meta::key::schema_name::SchemaNameKey;
27use common_query::Output;
28use common_runtime::runtime::BuilderBuild;
29use common_runtime::{Builder as RuntimeBuilder, Runtime};
30use common_test_util::ports;
31use common_test_util::temp_dir::{TempDir, create_temp_dir};
32use common_wal::config::DatanodeWalConfig;
33use datanode::config::{DatanodeOptions, StorageConfig};
34use frontend::instance::Instance;
35use frontend::service_config::{MysqlOptions, PostgresOptions};
36use mito2::gc::GcConfig;
37use object_store::config::{
38 AzblobConfig, FileConfig, GcsConfig, ObjectStoreConfig, OssConfig, S3Config,
39};
40use object_store::services::{Azblob, Gcs, Oss, S3};
41use object_store::test_util::TempFolder;
42use object_store::{AzblobConnection, GcsConnection, ObjectStore, OssConnection, S3Connection};
43use servers::grpc::builder::GrpcServerBuilder;
44use servers::grpc::greptime_handler::GreptimeRequestHandler;
45use servers::grpc::{FlightCompression, GrpcOptions, GrpcServer, GrpcServerConfig};
46use servers::http::{HttpOptions, HttpServerBuilder};
47use servers::metrics_handler::MetricsHandler;
48use servers::mysql::server::{MysqlServer, MysqlSpawnConfig, MysqlSpawnRef};
49use servers::otel_arrow::OtelArrowServiceHandler;
50use servers::postgres::PostgresServer;
51use servers::prom_remote_write::validation::PromValidationMode;
52use servers::query_handler::sql::SqlQueryHandler;
53use servers::request_memory_limiter::ServerMemoryLimiter;
54use servers::server::Server;
55use servers::tls::ReloadableTlsServerConfig;
56use session::context::QueryContext;
57
58use crate::standalone::{GreptimeDbStandalone, GreptimeDbStandaloneBuilder};
59
60pub const PEER_PLACEHOLDER_ADDR: &str = "127.0.0.1:3001";
61
62#[derive(Debug, Clone, Copy, Eq, PartialEq)]
63pub enum StorageType {
64 S3,
65 S3WithCache,
66 File,
67 Oss,
68 Azblob,
69 Gcs,
70}
71
72impl Display for StorageType {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self {
75 StorageType::S3 => write!(f, "S3"),
76 StorageType::S3WithCache => write!(f, "S3"),
77 StorageType::File => write!(f, "File"),
78 StorageType::Oss => write!(f, "Oss"),
79 StorageType::Azblob => write!(f, "Azblob"),
80 StorageType::Gcs => write!(f, "Gcs"),
81 }
82 }
83}
84
85impl StorageType {
86 pub fn build_storage_types_based_on_env() -> Vec<StorageType> {
87 let mut storage_types = Vec::with_capacity(4);
88 storage_types.push(StorageType::File);
89 if let Ok(bucket) = env::var("GT_S3_BUCKET")
90 && !bucket.is_empty()
91 {
92 storage_types.push(StorageType::S3);
93 }
94 if env::var("GT_OSS_BUCKET").is_ok() {
95 storage_types.push(StorageType::Oss);
96 }
97 if env::var("GT_AZBLOB_CONTAINER").is_ok() {
98 storage_types.push(StorageType::Azblob);
99 }
100 if env::var("GT_GCS_BUCKET").is_ok() {
101 storage_types.push(StorageType::Gcs);
102 }
103 storage_types
104 }
105
106 pub fn test_on(&self) -> bool {
107 let _ = dotenv::dotenv();
108
109 match self {
110 StorageType::File => true, StorageType::S3 | StorageType::S3WithCache => {
112 if let Ok(b) = env::var("GT_S3_BUCKET") {
113 !b.is_empty()
114 } else {
115 false
116 }
117 }
118 StorageType::Oss => {
119 if let Ok(b) = env::var("GT_OSS_BUCKET") {
120 !b.is_empty()
121 } else {
122 false
123 }
124 }
125 StorageType::Azblob => {
126 if let Ok(b) = env::var("GT_AZBLOB_CONTAINER") {
127 !b.is_empty()
128 } else {
129 false
130 }
131 }
132 StorageType::Gcs => {
133 if let Ok(b) = env::var("GT_GCS_BUCKET") {
134 !b.is_empty()
135 } else {
136 false
137 }
138 }
139 }
140 }
141}
142
143fn s3_test_config() -> S3Config {
144 S3Config {
145 connection: S3Connection {
146 root: uuid::Uuid::new_v4().to_string(),
147 access_key_id: env::var("GT_S3_ACCESS_KEY_ID").unwrap().into(),
148 secret_access_key: env::var("GT_S3_ACCESS_KEY").unwrap().into(),
149 bucket: env::var("GT_S3_BUCKET").unwrap(),
150 region: Some(env::var("GT_S3_REGION").unwrap()),
151 endpoint: env::var("GT_S3_ENDPOINT_URL").ok(),
152 ..Default::default()
153 },
154 ..Default::default()
155 }
156}
157
158pub fn get_test_store_config(store_type: &StorageType) -> (ObjectStoreConfig, TempDirGuard) {
159 let _ = dotenv::dotenv();
160
161 match store_type {
162 StorageType::Gcs => {
163 let gcs_config = GcsConfig {
164 connection: GcsConnection {
165 root: uuid::Uuid::new_v4().to_string(),
166 bucket: env::var("GT_GCS_BUCKET").unwrap(),
167 scope: env::var("GT_GCS_SCOPE").unwrap(),
168 credential_path: env::var("GT_GCS_CREDENTIAL_PATH").unwrap().into(),
169 credential: env::var("GT_GCS_CREDENTIAL").unwrap().into(),
170 endpoint: env::var("GT_GCS_ENDPOINT").unwrap_or_default(),
171 },
172 ..Default::default()
173 };
174
175 let builder = Gcs::from(&gcs_config.connection);
176 let config = ObjectStoreConfig::Gcs(gcs_config);
177 let store = ObjectStore::new(builder).unwrap().finish();
178 (config, TempDirGuard::Gcs(TempFolder::new(&store, "/")))
179 }
180 StorageType::Azblob => {
181 let azblob_config = AzblobConfig {
182 connection: AzblobConnection {
183 root: uuid::Uuid::new_v4().to_string(),
184 container: env::var("GT_AZBLOB_CONTAINER").unwrap(),
185 account_name: env::var("GT_AZBLOB_ACCOUNT_NAME").unwrap().into(),
186 account_key: env::var("GT_AZBLOB_ACCOUNT_KEY").unwrap().into(),
187 endpoint: env::var("GT_AZBLOB_ENDPOINT").unwrap(),
188 ..Default::default()
189 },
190 ..Default::default()
191 };
192
193 let builder = Azblob::from(&azblob_config.connection);
194 let config = ObjectStoreConfig::Azblob(azblob_config);
195 let store = ObjectStore::new(builder).unwrap().finish();
196 (config, TempDirGuard::Azblob(TempFolder::new(&store, "/")))
197 }
198 StorageType::Oss => {
199 let oss_config = OssConfig {
200 connection: OssConnection {
201 root: uuid::Uuid::new_v4().to_string(),
202 access_key_id: env::var("GT_OSS_ACCESS_KEY_ID").unwrap().into(),
203 access_key_secret: env::var("GT_OSS_ACCESS_KEY").unwrap().into(),
204 bucket: env::var("GT_OSS_BUCKET").unwrap(),
205 endpoint: env::var("GT_OSS_ENDPOINT").unwrap(),
206 },
207 ..Default::default()
208 };
209
210 let builder = Oss::from(&oss_config.connection);
211 let config = ObjectStoreConfig::Oss(oss_config);
212 let store = ObjectStore::new(builder).unwrap().finish();
213 (config, TempDirGuard::Oss(TempFolder::new(&store, "/")))
214 }
215 StorageType::S3 | StorageType::S3WithCache => {
216 let mut s3_config = s3_test_config();
217
218 if *store_type == StorageType::S3WithCache {
219 s3_config.cache.cache_path = "/tmp/greptimedb_cache".to_string();
220 } else {
221 s3_config.cache.enable_read_cache = false;
222 }
223
224 let builder = S3::from(&s3_config.connection);
225 let config = ObjectStoreConfig::S3(s3_config);
226 let store = ObjectStore::new(builder).unwrap().finish();
227 (config, TempDirGuard::S3(TempFolder::new(&store, "/")))
228 }
229 StorageType::File => (ObjectStoreConfig::File(FileConfig {}), TempDirGuard::None),
230 }
231}
232
233pub enum TempDirGuard {
234 None,
235 S3(TempFolder),
236 Oss(TempFolder),
237 Azblob(TempFolder),
238 Gcs(TempFolder),
239}
240
241pub struct TestGuard {
242 pub home_guard: FileDirGuard,
243 pub storage_guards: Vec<StorageGuard>,
244}
245
246pub struct FileDirGuard {
247 pub temp_dir: TempDir,
248}
249
250impl FileDirGuard {
251 pub fn new(temp_dir: TempDir) -> Self {
252 Self { temp_dir }
253 }
254}
255
256pub struct StorageGuard(pub TempDirGuard);
257
258impl TestGuard {
259 pub async fn remove_all(&mut self) {
260 for storage_guard in self.storage_guards.iter_mut() {
261 if let TempDirGuard::S3(guard)
262 | TempDirGuard::Oss(guard)
263 | TempDirGuard::Azblob(guard)
264 | TempDirGuard::Gcs(guard) = &mut storage_guard.0
265 {
266 guard.remove_all().await.unwrap()
267 }
268 }
269 }
270}
271
272impl Drop for TestGuard {
273 fn drop(&mut self) {
274 let (tx, rx) = std::sync::mpsc::channel();
275
276 let guards = std::mem::take(&mut self.storage_guards);
277 common_runtime::spawn_global(async move {
278 let mut errors = vec![];
279 for guard in guards {
280 if let TempDirGuard::S3(guard)
281 | TempDirGuard::Oss(guard)
282 | TempDirGuard::Azblob(guard)
283 | TempDirGuard::Gcs(guard) = guard.0
284 && let Err(e) = guard.remove_all().await
285 {
286 errors.push(e);
287 }
288 }
289 if errors.is_empty() {
290 tx.send(Ok(())).unwrap();
291 } else {
292 tx.send(Err(errors)).unwrap();
293 }
294 });
295 rx.recv().unwrap().unwrap_or_else(|e| panic!("{:?}", e));
296 }
297}
298
299pub fn create_tmp_dir_and_datanode_opts(
300 default_store_type: StorageType,
301 store_provider_types: Vec<StorageType>,
302 name: &str,
303 wal_config: DatanodeWalConfig,
304 gc_config: GcConfig,
305) -> (DatanodeOptions, TestGuard) {
306 let home_tmp_dir = create_temp_dir(&format!("gt_data_{name}"));
307 let home_dir = home_tmp_dir.path().to_str().unwrap().to_string();
308
309 let mut store_providers = Vec::with_capacity(store_provider_types.len());
311 let mut storage_guards = Vec::with_capacity(store_provider_types.len() + 1);
313
314 let (default_store, data_tmp_dir) = get_test_store_config(&default_store_type);
315 storage_guards.push(StorageGuard(data_tmp_dir));
316
317 for store_type in store_provider_types {
318 let (store, data_tmp_dir) = get_test_store_config(&store_type);
319 store_providers.push(store);
320 storage_guards.push(StorageGuard(data_tmp_dir))
321 }
322 let opts = create_datanode_opts(
323 default_store,
324 store_providers,
325 home_dir,
326 wal_config,
327 gc_config,
328 );
329
330 (
331 opts,
332 TestGuard {
333 home_guard: FileDirGuard::new(home_tmp_dir),
334 storage_guards,
335 },
336 )
337}
338
339pub(crate) fn create_datanode_opts(
340 default_store: ObjectStoreConfig,
341 providers: Vec<ObjectStoreConfig>,
342 home_dir: String,
343 wal_config: DatanodeWalConfig,
344 gc_config: GcConfig,
345) -> DatanodeOptions {
346 let region_engine = DatanodeOptions::default()
347 .region_engine
348 .into_iter()
349 .map(|mut v| {
350 if let datanode::config::RegionEngineConfig::Mito(mito_config) = &mut v {
351 mito_config.gc = gc_config.clone();
352 }
353 v
354 })
355 .collect();
356 DatanodeOptions {
357 node_id: Some(0),
358 require_lease_before_startup: true,
359 storage: StorageConfig {
360 data_home: home_dir,
361 providers,
362 store: default_store,
363 },
364 grpc: GrpcOptions::default()
365 .with_bind_addr(PEER_PLACEHOLDER_ADDR)
366 .with_server_addr(PEER_PLACEHOLDER_ADDR),
367 wal: wal_config,
368 region_engine,
369 ..Default::default()
370 }
371}
372
373pub(crate) async fn create_test_table(instance: &Instance, table_name: &str) {
374 let sql = format!(
375 r#"
376CREATE TABLE IF NOT EXISTS {table_name} (
377 host String NOT NULL PRIMARY KEY,
378 cpu DOUBLE NULL,
379 memory DOUBLE NULL,
380 ts TIMESTAMP NOT NULL TIME INDEX,
381)
382"#
383 );
384
385 let result = instance.do_query(&sql, QueryContext::arc()).await;
386 let _ = result.first().unwrap().as_ref().unwrap();
387}
388
389async fn setup_standalone_instance(
390 test_name: &str,
391 store_type: StorageType,
392) -> GreptimeDbStandalone {
393 GreptimeDbStandaloneBuilder::new(test_name)
394 .with_default_store_type(store_type)
395 .build()
396 .await
397}
398
399async fn setup_standalone_instance_with_slow_query_threshold(
400 test_name: &str,
401 store_type: StorageType,
402 slow_query_threshold: std::time::Duration,
403) -> GreptimeDbStandalone {
404 GreptimeDbStandaloneBuilder::new(test_name)
405 .with_default_store_type(store_type)
406 .with_slow_query_threshold(slow_query_threshold)
407 .build()
408 .await
409}
410
411async fn setup_standalone_instance_with_plugins(
412 test_name: &str,
413 store_type: StorageType,
414 plugins: Plugins,
415) -> GreptimeDbStandalone {
416 GreptimeDbStandaloneBuilder::new(test_name)
417 .with_default_store_type(store_type)
418 .with_plugin(plugins)
419 .build()
420 .await
421}
422
423async fn setup_standalone_instance_with_plugins_and_slow_query_threshold(
424 test_name: &str,
425 store_type: StorageType,
426 plugins: Plugins,
427 slow_query_threshold: std::time::Duration,
428) -> GreptimeDbStandalone {
429 GreptimeDbStandaloneBuilder::new(test_name)
430 .with_default_store_type(store_type)
431 .with_plugin(plugins)
432 .with_slow_query_threshold(slow_query_threshold)
433 .build()
434 .await
435}
436
437pub async fn setup_test_http_app(store_type: StorageType, name: &str) -> (Router, TestGuard) {
438 let instance = setup_standalone_instance(name, store_type).await;
439
440 let http_opts = HttpOptions {
441 addr: format!("127.0.0.1:{}", ports::get_port()),
442 ..Default::default()
443 };
444 let http_server = HttpServerBuilder::new(http_opts)
445 .with_sql_handler(instance.fe_instance().clone())
446 .with_logs_handler(instance.fe_instance().clone())
447 .with_metrics_handler(MetricsHandler)
448 .with_greptime_config_options(instance.opts.datanode_options().to_toml().unwrap())
449 .build();
450 (
451 http_server.build(http_server.make_app()).unwrap(),
452 instance.guard,
453 )
454}
455
456pub async fn setup_test_http_app_with_frontend(
457 store_type: StorageType,
458 name: &str,
459) -> (Router, TestGuard) {
460 setup_test_http_app_with_frontend_and_user_provider(store_type, name, None).await
461}
462
463pub async fn setup_test_http_app_with_frontend_and_slow_query_threshold(
464 store_type: StorageType,
465 name: &str,
466 slow_query_threshold: std::time::Duration,
467) -> (Router, TestGuard) {
468 let instance =
469 setup_standalone_instance_with_slow_query_threshold(name, store_type, slow_query_threshold)
470 .await;
471
472 create_test_table(instance.fe_instance(), "demo").await;
473
474 let http_opts = HttpOptions {
475 addr: format!("127.0.0.1:{}", ports::get_port()),
476 ..Default::default()
477 };
478
479 let http_server = HttpServerBuilder::new(http_opts)
480 .with_sql_handler(instance.fe_instance().clone())
481 .with_log_ingest_handler(instance.fe_instance().clone(), None, None)
482 .with_logs_handler(instance.fe_instance().clone())
483 .with_influxdb_handler(instance.fe_instance().clone())
484 .with_otlp_handler(instance.fe_instance().clone(), true)
485 .with_jaeger_handler(instance.fe_instance().clone())
486 .with_greptime_config_options(instance.opts.to_toml().unwrap())
487 .build();
488
489 let app = http_server.build(http_server.make_app()).unwrap();
490 (app, instance.guard)
491}
492
493pub async fn setup_test_http_app_with_frontend_and_user_provider(
494 store_type: StorageType,
495 name: &str,
496 user_provider: Option<UserProviderRef>,
497) -> (Router, TestGuard) {
498 setup_test_http_app_with_frontend_and_custom_options(
499 store_type,
500 name,
501 user_provider,
502 None,
503 None,
504 )
505 .await
506}
507
508pub async fn setup_test_http_app_with_frontend_and_custom_options(
509 store_type: StorageType,
510 name: &str,
511 user_provider: Option<UserProviderRef>,
512 http_opts: Option<HttpOptions>,
513 memory_limiter: Option<ServerMemoryLimiter>,
514) -> (Router, TestGuard) {
515 let plugins = Plugins::new();
516 if let Some(user_provider) = user_provider.clone() {
517 plugins.insert::<UserProviderRef>(user_provider.clone());
518 plugins.insert::<PermissionCheckerRef>(DefaultPermissionChecker::arc());
519 }
520
521 let instance = setup_standalone_instance_with_plugins(name, store_type, plugins).await;
522
523 create_test_table(instance.fe_instance(), "demo").await;
524
525 let http_opts = http_opts.unwrap_or_else(|| HttpOptions {
526 addr: format!("127.0.0.1:{}", ports::get_port()),
527 ..Default::default()
528 });
529
530 let mut http_server = HttpServerBuilder::new(http_opts)
531 .with_sql_handler(instance.fe_instance().clone())
532 .with_log_ingest_handler(instance.fe_instance().clone(), None, None)
533 .with_logs_handler(instance.fe_instance().clone())
534 .with_influxdb_handler(instance.fe_instance().clone())
535 .with_otlp_handler(instance.fe_instance().clone(), true)
536 .with_jaeger_handler(instance.fe_instance().clone())
537 .with_dashboard_handler(instance.fe_instance().clone())
538 .with_greptime_config_options(instance.opts.to_toml().unwrap());
539
540 if let Some(user_provider) = user_provider {
541 http_server = http_server.with_user_provider(user_provider);
542 }
543
544 if let Some(limiter) = memory_limiter {
545 http_server = http_server.with_memory_limiter(limiter);
546 }
547
548 let http_server = http_server.build();
549
550 let app = http_server.build(http_server.make_app()).unwrap();
551 (app, instance.guard)
552}
553
554async fn run_sql(sql: &str, instance: &GreptimeDbStandalone) {
555 let result = instance
556 .fe_instance()
557 .do_query(sql, QueryContext::arc())
558 .await;
559 let _ = result.first().unwrap().as_ref().unwrap();
560}
561
562pub async fn setup_test_prom_app_with_frontend(
563 store_type: StorageType,
564 name: &str,
565) -> (Router, TestGuard) {
566 unsafe {
567 std::env::set_var("TZ", "UTC");
568 }
569
570 let instance = setup_standalone_instance(name, store_type).await;
571
572 let sql = "CREATE TABLE phy (ts timestamp time index, val double, host string primary key) engine=metric with ('physical_metric_table' = '')";
574 run_sql(sql, &instance).await;
575 let sql = "CREATE TABLE phy_ns (ts timestamp(0) time index, val double, host string primary key) engine=metric with ('physical_metric_table' = '')";
576 run_sql(sql, &instance).await;
577 let sql = "CREATE TABLE demo (ts timestamp time index, val double, host string primary key) engine=metric with ('on_physical_table' = 'phy')";
579 run_sql(sql, &instance).await;
580 let sql = "CREATE TABLE demo_metrics (ts timestamp time index, val double, idc string primary key) engine=metric with ('on_physical_table' = 'phy')";
581 run_sql(sql, &instance).await;
582 let sql = "CREATE TABLE multi_labels (ts timestamp(0) time index, val double, idc string, env string, host string, primary key (idc, env, host)) engine=metric with ('on_physical_table' = 'phy_ns')";
583 run_sql(sql, &instance).await;
584
585 let sql = "INSERT INTO demo(host, val, ts) VALUES ('host1', 1.1, 0), ('host2', 2.1, 600000)";
587 run_sql(sql, &instance).await;
588 let sql =
589 "INSERT INTO demo_metrics(idc, val, ts) VALUES ('idc1', 1.1, 0), ('idc2', 2.1, 600000)";
590 run_sql(sql, &instance).await;
591 let sql = "INSERT INTO demo_metrics(val, ts) VALUES (1.1, 0)";
593 run_sql(sql, &instance).await;
594
595 let sql = "INSERT INTO multi_labels(idc, env, host, val, ts) VALUES ('idc1', 'dev', 'host1', 1.1, 0), ('idc1', 'dev', 'host2', 2.1, 0), ('idc2', 'dev', 'host1', 1.1, 0), ('idc2', 'test', 'host3', 2.1, 0)";
597 run_sql(sql, &instance).await;
598
599 let sql = "CREATE TABLE phy2 (ts timestamp(9) time index, val double, host string primary key) engine=metric with ('physical_metric_table' = '')";
601 run_sql(sql, &instance).await;
602 let sql = "CREATE TABLE demo_metrics_with_nanos(ts timestamp(9) time index, val double, idc string primary key) engine=metric with ('on_physical_table' = 'phy2')";
603 run_sql(sql, &instance).await;
604 let sql = "INSERT INTO demo_metrics_with_nanos(idc, val, ts) VALUES ('idc1', 1.1, 0)";
605 run_sql(sql, &instance).await;
606
607 let sql = "CREATE TABLE mito (ts timestamp(9) time index, val double, host bigint primary key) engine=mito";
609 run_sql(sql, &instance).await;
610 let sql = "INSERT INTO mito(host, val, ts) VALUES (1, 1.1, 0)";
611 run_sql(sql, &instance).await;
612
613 let http_opts = HttpOptions {
614 addr: format!("127.0.0.1:{}", ports::get_port()),
615 ..Default::default()
616 };
617 let frontend_ref = instance.fe_instance().clone();
618 let http_server = HttpServerBuilder::new(http_opts)
619 .with_sql_handler(frontend_ref.clone())
620 .with_logs_handler(instance.fe_instance().clone())
621 .with_prom_handler(
622 frontend_ref.clone(),
623 Some(frontend_ref.clone()),
624 true,
625 PromValidationMode::Strict,
626 )
627 .with_prometheus_handler(frontend_ref)
628 .with_greptime_config_options(instance.opts.datanode_options().to_toml().unwrap())
629 .build();
630 let app = http_server.build(http_server.make_app()).unwrap();
631 (app, instance.guard)
632}
633
634pub async fn setup_grpc_server(
635 store_type: StorageType,
636 name: &str,
637) -> (GreptimeDbStandalone, Arc<GrpcServer>) {
638 setup_grpc_server_with(store_type, name, None, None, None).await
639}
640
641pub async fn setup_grpc_server_with_user_provider(
642 store_type: StorageType,
643 name: &str,
644 user_provider: Option<UserProviderRef>,
645) -> (GreptimeDbStandalone, Arc<GrpcServer>) {
646 setup_grpc_server_with(store_type, name, user_provider, None, None).await
647}
648
649pub async fn setup_grpc_server_with(
650 store_type: StorageType,
651 name: &str,
652 user_provider: Option<UserProviderRef>,
653 grpc_config: Option<GrpcServerConfig>,
654 memory_limiter: Option<servers::request_memory_limiter::ServerMemoryLimiter>,
655) -> (GreptimeDbStandalone, Arc<GrpcServer>) {
656 let instance = setup_standalone_instance(name, store_type).await;
657
658 let runtime: Runtime = RuntimeBuilder::default()
659 .worker_threads(2)
660 .thread_name("grpc-handlers")
661 .build()
662 .unwrap();
663
664 let fe_instance_ref = instance.fe_instance().clone();
665
666 let greptime_request_handler = GreptimeRequestHandler::new(
667 fe_instance_ref.clone(),
668 user_provider.clone(),
669 Some(runtime.clone()),
670 FlightCompression::default(),
671 );
672
673 let flight_handler = Arc::new(greptime_request_handler.clone());
674
675 let grpc_config = grpc_config.unwrap_or_default();
676 let mut grpc_builder = GrpcServerBuilder::new(grpc_config.clone(), runtime);
677
678 if let Some(limiter) = memory_limiter {
679 grpc_builder = grpc_builder.with_memory_limiter(limiter);
680 }
681
682 let grpc_builder = grpc_builder
683 .database_handler(greptime_request_handler)
684 .flight_handler(flight_handler)
685 .prometheus_handler(fe_instance_ref.clone(), user_provider.clone())
686 .otel_arrow_handler(OtelArrowServiceHandler::new(fe_instance_ref, user_provider))
687 .with_tls_config(grpc_config.tls)
688 .unwrap();
689
690 let mut grpc_server = grpc_builder.build();
691
692 let fe_grpc_addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
693 grpc_server.start(fe_grpc_addr).await.unwrap();
694
695 (instance, Arc::new(grpc_server))
696}
697
698pub async fn setup_mysql_server(
699 store_type: StorageType,
700 name: &str,
701) -> (TestGuard, Arc<Box<dyn Server>>) {
702 setup_mysql_server_with_user_provider(store_type, name, None).await
703}
704
705pub async fn setup_mysql_server_with_slow_query_threshold(
706 store_type: StorageType,
707 name: &str,
708 slow_query_threshold: std::time::Duration,
709) -> (TestGuard, Arc<Box<dyn Server>>) {
710 let plugins = Plugins::new();
711 let instance = setup_standalone_instance_with_plugins_and_slow_query_threshold(
712 name,
713 store_type,
714 plugins,
715 slow_query_threshold,
716 )
717 .await;
718
719 let runtime = RuntimeBuilder::default()
720 .worker_threads(2)
721 .thread_name("mysql-runtime")
722 .build()
723 .unwrap();
724
725 let fe_mysql_addr = format!("127.0.0.1:{}", ports::get_port());
726
727 let fe_instance_ref = instance.fe_instance().clone();
728 let opts = MysqlOptions {
729 addr: fe_mysql_addr.clone(),
730 ..Default::default()
731 };
732 let mut mysql_server = MysqlServer::create_server(
733 runtime,
734 Arc::new(MysqlSpawnRef::new(fe_instance_ref, None)),
735 Arc::new(MysqlSpawnConfig::new(
736 false,
737 Arc::new(
738 ReloadableTlsServerConfig::try_new(opts.tls.clone())
739 .expect("Failed to load certificates and keys"),
740 ),
741 0,
742 opts.reject_no_database.unwrap_or(false),
743 opts.prepared_stmt_cache_size,
744 )),
745 None,
746 );
747
748 mysql_server
749 .start(fe_mysql_addr.parse::<SocketAddr>().unwrap())
750 .await
751 .unwrap();
752
753 (instance.guard, Arc::new(mysql_server))
754}
755
756pub async fn setup_mysql_server_with_user_provider(
757 store_type: StorageType,
758 name: &str,
759 user_provider: Option<UserProviderRef>,
760) -> (TestGuard, Arc<Box<dyn Server>>) {
761 let plugins = Plugins::new();
762 if let Some(user_provider) = user_provider.clone() {
763 plugins.insert::<UserProviderRef>(user_provider.clone());
764 plugins.insert::<PermissionCheckerRef>(DefaultPermissionChecker::arc());
765 }
766
767 let instance = setup_standalone_instance_with_plugins(name, store_type, plugins).await;
768
769 let runtime = RuntimeBuilder::default()
770 .worker_threads(2)
771 .thread_name("mysql-runtime")
772 .build()
773 .unwrap();
774
775 let fe_mysql_addr = format!("127.0.0.1:{}", ports::get_port());
776
777 let fe_instance_ref = instance.fe_instance().clone();
778 let opts = MysqlOptions {
779 addr: fe_mysql_addr.clone(),
780 ..Default::default()
781 };
782 let mut mysql_server = MysqlServer::create_server(
783 runtime,
784 Arc::new(MysqlSpawnRef::new(fe_instance_ref, user_provider)),
785 Arc::new(MysqlSpawnConfig::new(
786 false,
787 Arc::new(
788 ReloadableTlsServerConfig::try_new(opts.tls.clone())
789 .expect("Failed to load certificates and keys"),
790 ),
791 0,
792 opts.reject_no_database.unwrap_or(false),
793 opts.prepared_stmt_cache_size,
794 )),
795 None,
796 );
797
798 mysql_server
799 .start(fe_mysql_addr.parse::<SocketAddr>().unwrap())
800 .await
801 .unwrap();
802
803 (instance.guard, Arc::new(mysql_server))
804}
805
806pub async fn setup_pg_server(
807 store_type: StorageType,
808 name: &str,
809) -> (TestGuard, Arc<Box<dyn Server>>) {
810 setup_pg_server_with_user_provider(store_type, name, None).await
811}
812
813pub async fn setup_pg_server_with_slow_query_threshold(
814 store_type: StorageType,
815 name: &str,
816 slow_query_threshold: std::time::Duration,
817) -> (TestGuard, Arc<Box<dyn Server>>) {
818 let instance =
819 setup_standalone_instance_with_slow_query_threshold(name, store_type, slow_query_threshold)
820 .await;
821
822 let runtime = RuntimeBuilder::default()
823 .worker_threads(2)
824 .thread_name("pg-runtime")
825 .build()
826 .unwrap();
827
828 let fe_pg_addr = format!("127.0.0.1:{}", ports::get_port());
829
830 let fe_instance_ref = instance.fe_instance().clone();
831 let opts = PostgresOptions {
832 addr: fe_pg_addr.clone(),
833 ..Default::default()
834 };
835 let tls_server_config = Arc::new(
836 ReloadableTlsServerConfig::try_new(opts.tls.clone())
837 .expect("Failed to load certificates and keys"),
838 );
839
840 let mut pg_server = Box::new(PostgresServer::new(
841 fe_instance_ref,
842 opts.tls.should_force_tls(),
843 tls_server_config,
844 0,
845 runtime,
846 None,
847 None,
848 ));
849
850 pg_server
851 .start(fe_pg_addr.parse::<SocketAddr>().unwrap())
852 .await
853 .unwrap();
854
855 (instance.guard, Arc::new(pg_server))
856}
857
858pub async fn setup_pg_server_with_user_provider(
859 store_type: StorageType,
860 name: &str,
861 user_provider: Option<UserProviderRef>,
862) -> (TestGuard, Arc<Box<dyn Server>>) {
863 let instance = setup_standalone_instance(name, store_type).await;
864
865 let runtime = RuntimeBuilder::default()
866 .worker_threads(2)
867 .thread_name("pg-runtime")
868 .build()
869 .unwrap();
870
871 let fe_pg_addr = format!("127.0.0.1:{}", ports::get_port());
872
873 let fe_instance_ref = instance.fe_instance().clone();
874 let opts = PostgresOptions {
875 addr: fe_pg_addr.clone(),
876 ..Default::default()
877 };
878 let tls_server_config = Arc::new(
879 ReloadableTlsServerConfig::try_new(opts.tls.clone())
880 .expect("Failed to load certificates and keys"),
881 );
882
883 let mut pg_server = Box::new(PostgresServer::new(
884 fe_instance_ref,
885 opts.tls.should_force_tls(),
886 tls_server_config,
887 0,
888 runtime,
889 user_provider,
890 None,
891 ));
892
893 pg_server
894 .start(fe_pg_addr.parse::<SocketAddr>().unwrap())
895 .await
896 .unwrap();
897
898 (instance.guard, Arc::new(pg_server))
899}
900
901pub(crate) async fn prepare_another_catalog_and_schema(instance: &Instance) {
902 let catalog_manager = instance
903 .catalog_manager()
904 .as_any()
905 .downcast_ref::<KvBackendCatalogManager>()
906 .unwrap();
907
908 let table_metadata_manager = catalog_manager.table_metadata_manager_ref();
909 table_metadata_manager
910 .catalog_manager()
911 .create(CatalogNameKey::new("another_catalog"), true)
912 .await
913 .unwrap();
914 table_metadata_manager
915 .schema_manager()
916 .create(
917 SchemaNameKey::new("another_catalog", "another_schema"),
918 None,
919 true,
920 )
921 .await
922 .unwrap();
923}
924
925pub async fn execute_sql(instance: &Arc<Instance>, sql: &str) -> Output {
926 SqlQueryHandler::do_query(instance.as_ref(), sql, QueryContext::arc())
927 .await
928 .remove(0)
929 .unwrap()
930}
931
932pub async fn try_execute_sql(
933 instance: &Arc<Instance>,
934 sql: &str,
935) -> servers::error::Result<Output> {
936 SqlQueryHandler::do_query(instance.as_ref(), sql, QueryContext::arc())
937 .await
938 .remove(0)
939}
940
941pub async fn execute_sql_and_expect(instance: &Arc<Instance>, sql: &str, expected: &str) {
942 let output = execute_sql(instance, sql).await;
943 let output = output.data.pretty_print().await;
944 assert_eq!(output, expected.trim());
945}