diff --git a/Cargo.lock b/Cargo.lock index 4043ae2865..85f4e7abb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5639,7 +5639,8 @@ dependencies = [ [[package]] name = "sqlness" version = "0.1.0" -source = "git+https://github.com/CeresDB/sqlness.git?rev=c077b17d73ab25460c152dc34e8f80f904522a57#c077b17d73ab25460c152dc34e8f80f904522a57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b94ee738bee88148b3226795dbd0f18076a8c48d5dd91d5dd573ebc20ed0855" dependencies = [ "async-trait", "derive_builder", diff --git a/tests/Makefile b/tests/Makefile index 9f3c59bcf1..12c09919c7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,6 @@ ROOT = $(shell pwd) DATA_DIR = /tmp/ceresdb export CERESDB_BINARY_PATH ?= $(ROOT)/../target/$(MODE)/ceresdb-server -export CERESDB_CONFIG_PATH ?= $(ROOT)/../docs/sqlness.toml export CERESDB_SERVER_ENDPOINT ?= 127.0.0.1:8831 export CERESDB_TEST_CASE_PATH ?= $(ROOT)/cases export CERESDB_TEST_SQLNESS ?= $(ROOT)/../target/$(MODE)/ceresdb-test @@ -22,10 +21,10 @@ build-sqlness: build: build-ceresdb build-sqlness -# rename ${case}.out to ${case}.result automatically. fd is required +# rename ${case}.output to ${case}.result automatically. fd is required # https://github.com/sharkdp/fd fix: - fd -t f out --exec mv {} {.}.result \; + fd -t f output --exec mv {} {.}.result \; run: clean build cd sqlness && $(CERESDB_TEST_SQLNESS) diff --git a/docs/sqlness.toml b/tests/cases/local/config.toml similarity index 100% rename from docs/sqlness.toml rename to tests/cases/local/config.toml diff --git a/tests/sqlness/Cargo.toml b/tests/sqlness/Cargo.toml index 47c5e4cc55..8bdf4a94bb 100644 --- a/tests/sqlness/Cargo.toml +++ b/tests/sqlness/Cargo.toml @@ -9,5 +9,5 @@ workspace = true anyhow = "1.0.58" async-trait = "0.1" ceresdb-client-rs = { git = "https://github.com/CeresDB/ceresdb-client-rs.git", rev = "a9d9190f4f7b55171ea2ad142fb41dc9909c19c5" } -sqlness = { git = "https://github.com/CeresDB/sqlness.git", rev = "c077b17d73ab25460c152dc34e8f80f904522a57" } +sqlness = "0.1" tokio = { workspace = true } diff --git a/tests/sqlness/src/client.rs b/tests/sqlness/src/client.rs deleted file mode 100644 index d1adb25cb6..0000000000 --- a/tests/sqlness/src/client.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0. - -use std::{fmt::Display, sync::Arc}; - -use async_trait::async_trait; -use ceresdb_client_rs::{ - db_client::DbClient, - model::{display::CsvFormatter, request::QueryRequest}, - RpcContext, -}; -use sqlness::Database; - -pub struct Client { - db_client: Arc, -} - -#[async_trait] -impl Database for Client { - async fn query(&self, query: String) -> Box { - Self::execute(query, self.db_client.clone()).await - } -} - -impl Client { - pub fn new(db_client: Arc) -> Self { - Client { db_client } - } - - async fn execute(query: String, client: Arc) -> Box { - let query_ctx = RpcContext { - tenant: "public".to_string(), - token: "".to_string(), - }; - let query_req = QueryRequest { - metrics: vec![], - ql: query, - }; - let result = client.query(&query_ctx, &query_req).await; - - Box::new(match result { - Ok(resp) => { - if resp.has_schema() { - format!("{}", CsvFormatter { resp }) - } else { - format!("affected_rows: {}", resp.affected_rows) - } - } - Err(e) => format!("Failed to execute query, err: {:?}", e), - }) - } -} diff --git a/tests/sqlness/src/database.rs b/tests/sqlness/src/database.rs new file mode 100644 index 0000000000..9e070f5fa8 --- /dev/null +++ b/tests/sqlness/src/database.rs @@ -0,0 +1,98 @@ +// Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0. + +use std::{ + env, + fmt::Display, + fs::File, + path::Path, + process::{Child, Command}, + sync::Arc, +}; + +use async_trait::async_trait; +use ceresdb_client_rs::{ + db_client::{Builder, DbClient, Mode}, + model::{display::CsvFormatter, request::QueryRequest}, + RpcContext, +}; +use sqlness::Database; + +const BINARY_PATH_ENV: &str = "CERESDB_BINARY_PATH"; +const SERVER_ENDPOINT_ENV: &str = "CERESDB_SERVER_ENDPOINT"; +const CERESDB_STDOUT_FILE: &str = "CERESDB_STDOUT_FILE"; +const CERESDB_STDERR_FILE: &str = "CERESDB_STDERR_FILE"; + +pub struct CeresDB { + server_process: Child, + db_client: Arc, +} + +#[async_trait] +impl Database for CeresDB { + async fn query(&self, query: String) -> Box { + Self::execute(query, self.db_client.clone()).await + } +} + +impl CeresDB { + pub fn new(config: Option<&Path>) -> Self { + let config = config.unwrap().to_string_lossy(); + let bin = env::var(BINARY_PATH_ENV).expect("Cannot parse binary path env"); + let stdout = env::var(CERESDB_STDOUT_FILE).expect("Cannot parse stdout env"); + let stderr = env::var(CERESDB_STDERR_FILE).expect("Cannot parse stderr env"); + let stdout = File::create(stdout).expect("Cannot create stdout"); + let stderr = File::create(stderr).expect("Cannot create stderr"); + + println!("Start {} with {}...", bin, config); + + let server_process = Command::new(&bin) + .args(["--config", &config]) + .stdout(stdout) + .stderr(stderr) + .spawn() + .unwrap_or_else(|_| panic!("Failed to start server at {:?}", bin)); + + // Wait for a while + std::thread::sleep(std::time::Duration::from_secs(5)); + let endpoint = env::var(SERVER_ENDPOINT_ENV).unwrap_or_else(|_| { + panic!( + "Cannot read server endpoint from env {:?}", + SERVER_ENDPOINT_ENV + ) + }); + + let db_client = Builder::new(endpoint, Mode::Standalone).build(); + + CeresDB { + db_client, + server_process, + } + } + + pub fn stop(mut self) { + self.server_process.kill().unwrap() + } + + async fn execute(query: String, client: Arc) -> Box { + let query_ctx = RpcContext { + tenant: "public".to_string(), + token: "".to_string(), + }; + let query_req = QueryRequest { + metrics: vec![], + ql: query, + }; + let result = client.query(&query_ctx, &query_req).await; + + Box::new(match result { + Ok(resp) => { + if resp.has_schema() { + format!("{}", CsvFormatter { resp }) + } else { + format!("affected_rows: {}", resp.affected_rows) + } + } + Err(e) => format!("Failed to execute query, err: {:?}", e), + }) + } +} diff --git a/tests/sqlness/src/main.rs b/tests/sqlness/src/main.rs index 7288bbb030..95a4695dd9 100644 --- a/tests/sqlness/src/main.rs +++ b/tests/sqlness/src/main.rs @@ -1,29 +1,38 @@ // Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0. -#![feature(try_blocks)] - -use std::env; +use std::{env, path::Path}; use anyhow::Result; -use sqlness::Runner; +use async_trait::async_trait; +use database::CeresDB; +use sqlness::{EnvController, Runner}; -mod client; -mod setup; +mod database; const CASE_ROOT_PATH_ENV: &str = "CERESDB_TEST_CASE_PATH"; +pub struct CeresDBController; + +#[async_trait] +impl EnvController for CeresDBController { + type DB = CeresDB; + + async fn start(&self, _env: &str, config: Option<&Path>) -> Self::DB { + CeresDB::new(config) + } + + async fn stop(&self, _env: &str, database: Self::DB) { + database.stop(); + } +} + #[tokio::main] async fn main() -> Result<()> { let case_dir = env::var(CASE_ROOT_PATH_ENV)?; - let env = setup::CeresDBEnv::start_server(); - let config = sqlness::Config { - case_dir, - test_case_extension: String::from("sql"), - output_result_extension: String::from("output"), - expect_result_extension: String::from("result"), - interceptor_prefix: String::from("-- SQLNESS"), - env_config_file: String::from("config.toml"), - }; + let env = CeresDBController; + let config = sqlness::ConfigBuilder::default() + .case_dir(case_dir) + .build()?; let runner = Runner::new_with_config(config, env).await?; runner.run().await?; diff --git a/tests/sqlness/src/setup.rs b/tests/sqlness/src/setup.rs deleted file mode 100644 index e661651a29..0000000000 --- a/tests/sqlness/src/setup.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0. - -use std::{ - env, - fs::File, - process::{Child, Command}, -}; - -use async_trait::async_trait; -use ceresdb_client_rs::db_client::{Builder, Mode}; -use sqlness::Environment as SqlnessEnv; - -use crate::client::Client; - -const BINARY_PATH_ENV: &str = "CERESDB_BINARY_PATH"; -const CONFIG_PATH_ENV: &str = "CERESDB_CONFIG_PATH"; -const SERVER_ENDPOINT_ENV: &str = "CERESDB_SERVER_ENDPOINT"; -const CERESDB_STDOUT_FILE: &str = "CERESDB_STDOUT_FILE"; -const CERESDB_STDERR_FILE: &str = "CERESDB_STDERR_FILE"; - -pub struct CeresDBEnv { - server_process: Child, -} - -#[async_trait] -impl SqlnessEnv for CeresDBEnv { - type DB = Client; - - async fn start(&self, _mode: &str, _config: Option) -> Self::DB { - let endpoint = env::var(SERVER_ENDPOINT_ENV).unwrap_or_else(|_| { - panic!( - "Cannot read server endpoint from env {:?}", - SERVER_ENDPOINT_ENV - ) - }); - - let client = Builder::new(endpoint, Mode::Standalone).build(); - Client::new(client) - } - - /// Stop one [`Database`]. - async fn stop(&self, _mode: &str, _database: Self::DB) { - // TODO: stop in `drop` now - // Need refactor to support stop here - } -} - -impl Drop for CeresDBEnv { - fn drop(&mut self) { - self.server_process.kill().unwrap() - } -} - -impl CeresDBEnv { - pub fn start_server() -> Self { - let bin = env::var(BINARY_PATH_ENV).expect("Cannot parse binary path env"); - let config = env::var(CONFIG_PATH_ENV).expect("Cannot parse config path env"); - let stdout = env::var(CERESDB_STDOUT_FILE).expect("Cannot parse stdout env"); - let stderr = env::var(CERESDB_STDERR_FILE).expect("Cannot parse stderr env"); - - let stdout = File::create(stdout).expect("Cannot create stdout"); - let stderr = File::create(stderr).expect("Cannot create stderr"); - let server_process = Command::new(&bin) - .args(["--config", &config]) - .stdout(stdout) - .stderr(stderr) - .spawn() - .unwrap_or_else(|_| panic!("Failed to start server at {:?}", bin)); - - // Wait for a while - std::thread::sleep(std::time::Duration::from_secs(5)); - - Self { server_process } - } -}