Skip to content

Commit

Permalink
test: data files compatibility test
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelScofield committed Jan 9, 2024
1 parent 798aa66 commit 40a7d1c
Show file tree
Hide file tree
Showing 17 changed files with 388 additions and 133 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

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

9 changes: 9 additions & 0 deletions src/common/test-util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ edition.workspace = true
license.workspace = true

[dependencies]
client.workspace = true
common-error.workspace = true
common-query.workspace = true
common-recordbatch.workspace = true
common-time.workspace = true
once_cell.workspace = true
rand.workspace = true
serde.workspace = true
strum.workspace = true
tempfile.workspace = true
tinytemplate = "1.2"
tokio.workspace = true
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ linger = "5ms"
type = 'File'
data_home = '{data_home}'

[grpc_options]
addr = '127.0.0.1:4001'
[grpc]
addr = "{grpc_addr}"
runtime_size = 8

[procedure]
Expand Down
74 changes: 74 additions & 0 deletions src/common/test-util/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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::fs;
use std::path::Path;

use serde::Serialize;
use strum::{Display, EnumString};
use tinytemplate::TinyTemplate;

use crate::find_workspace_path;

#[derive(EnumString, Display)]
#[strum(serialize_all = "lowercase")]
pub enum ConfigTemplate {
Datanode,
Metasrv,
Standalone,
}

impl ConfigTemplate {
fn render(&self, config_values: ConfigValues) -> String {
let template_name = self.to_string();

let template = fs::read_to_string(find_workspace_path(&format!(
"/src/common/test-util/conf/{template_name}-test.toml.template"
)))
.unwrap();

let mut tt = TinyTemplate::new();
tt.add_template(&template_name, &template).unwrap();
tt.render(&template_name, &config_values).unwrap()
}
}

#[derive(Serialize, Default)]
pub struct ConfigValues {
pub wal_dir: String,
pub data_home: String,
pub procedure_dir: String,
pub is_raft_engine: bool,
pub kafka_wal_broker_endpoints: String,
pub grpc_addr: String,
}

/// Generate a config file from template (determined by parameter `config_template`), with provided
/// config values (in parameter `config_values`), and stores the file under the directory specified
/// by parameter `target_dir`, returns the target file name.
pub fn generate_config_file(
config_template: ConfigTemplate,
config_values: ConfigValues,
target_dir: &Path,
) -> String {
let rendered = config_template.render(config_values);

let target_file = format!(
"{config_template}-{}.toml",
common_time::util::current_time_millis()
);
fs::write(target_dir.join(&target_file), rendered).unwrap();

target_file
}
58 changes: 58 additions & 0 deletions src/common/test-util/src/display.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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::fmt;
use std::fmt::Formatter;

use client::error::Result;
use common_error::ext::ErrorExt;
use common_query::Output;
use common_recordbatch::util::collect_batches;

pub struct ResultDisplayer(pub Result<Output>);

impl fmt::Display for ResultDisplayer {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match &self.0 {
Ok(result) => match result {
Output::AffectedRows(rows) => {
write!(f, "Affected Rows: {rows}")
}
Output::RecordBatches(recordbatches) => {
let pretty = recordbatches.pretty_print().unwrap();
write!(f, "{pretty}")
}
Output::Stream(_) => unimplemented!(),
},
Err(e) => {
let status_code = e.status_code();
let root_cause = e.output_msg();
write!(
f,
"Error: {}({status_code}), {root_cause}",
status_code as u32
)
}
}
}
}

impl ResultDisplayer {
pub async fn display(self) -> String {
match self.0 {
Ok(Output::Stream(s)) => collect_batches(s).await.unwrap().pretty_print().unwrap(),
_ => self.to_string(),
}
}
}
2 changes: 2 additions & 0 deletions src/common/test-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::LazyLock;

pub mod config;
pub mod display;
pub mod ports;
pub mod temp_dir;

Expand Down
25 changes: 25 additions & 0 deletions src/common/test-util/src/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
// limitations under the License.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;

use once_cell::sync::OnceCell;
use rand::Rng;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpSocket;

const PORT_CHECK_INTERVAL: Duration = Duration::from_millis(100);

static PORTS: OnceCell<AtomicUsize> = OnceCell::new();

Expand All @@ -25,3 +30,23 @@ pub fn get_port() -> usize {
.get_or_init(|| AtomicUsize::new(rand::thread_rng().gen_range(3000..3800)))
.fetch_add(1, Ordering::Relaxed)
}

/// Spin awaits a socket address until it is connectable, or timeout.
pub async fn check_connectable(ip_addr: &str, timeout: Duration) -> bool {
let ip_addr = ip_addr.parse().unwrap();

let check_task = async {
loop {
let socket = TcpSocket::new_v4().unwrap();
match socket.connect(ip_addr).await {
Ok(mut stream) => {
let _ = stream.shutdown().await;
break;
}
Err(_) => tokio::time::sleep(PORT_CHECK_INTERVAL).await,
}
}
};

tokio::time::timeout(timeout, check_task).await.is_ok()
}
7 changes: 4 additions & 3 deletions tests-compatibility/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition.workspace = true
license.workspace = true

[dependencies]

[dev-dependencies]
tinytemplate = "1.2"
client.workspace = true
common-telemetry.workspace = true
common-test-util.workspace = true
tokio.workspace = true
8 changes: 8 additions & 0 deletions tests-compatibility/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# When compatibility tests failed:

- Start an old version (or built from old source codes) GreptimeDB with its data home and WAL set to directory `tests-compatibility/data_home` and `tests-compatibility/data_home/wal/` respectively.
- Using our CLI tool to [export](https://docs.greptime.com/user-guide/upgrade) the data.
- Clear everything under `tests-compatibility/data_home/`.
- Build a new GreptimeDB with your changes with the same data home and WAL dir config.
- Using our CLI tool again to [import](https://docs.greptime.com/user-guide/upgrade) the data.
- Rerun the compatibility test. If it passes, commit the data files.
13 changes: 0 additions & 13 deletions tests-compatibility/src/lib.rs

This file was deleted.

Loading

0 comments on commit 40a7d1c

Please sign in to comment.