mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-04 19:15:34 +00:00
* test: cut integration test time and make the storage matrix meaningful
tests-integration is ~85% of workspace test CPU, and 81% of that is the
S3/S3WithCache variants of the HTTP and gRPC suites. Those suites do not
touch the object store: of the 70 matrix HTTP tests only one flushed and
read back an SST, so the matrix was paying real AWS round trips to
re-prove protocol parsing.
- Point the PR CI object-store matrix at the MinIO already started by
tests-integration/fixtures. Three GT_S3_* consumers did not read
GT_S3_ENDPOINT_URL and would have hit real AWS with MinIO credentials;
they now do.
- Add a nightly Linux job against real AWS S3, and pass GT_S3_* into the
release integration-test container. The release previously ran every
remote-backend case as a skip and only exercised the file backend.
- Give each S3WithCache test its own read cache directory. They shared
/tmp/greptimedb_cache, which the datanode wipes on startup, so a
starting test deleted the read cache of a running one.
- Add flush -> read-back assertions to the tests whose columns have a
non-trivial SST representation: JSON/JSON2 columns, native histograms,
metric-engine logical tables, and tables carrying fulltext or skipping
indexes whose puffin files only exist after a flush.
- Move eight tests that create no table out of the storage matrix.
- Make the event recorder flush interval a constructor parameter and
shorten it in the event tests, which otherwise wait a 5s window per DDL
they assert on. It is skipped by serde and never reaches config files.
- Drop duplicates: test_grpc_zstd_compression was a verbatim copy of
test_grpc_message_size_ok and is now rewritten to assert the negotiated
grpc-encoding; test_execute_copy_to_{s3,oss,gcs,azblob} were strict
prefixes of their copy_from siblings; two standalone/distributed event
test pairs shared one assertion body.
- Fix and un-ignore stddev_by_label. stddev_pop merges partial aggregates
in a parallelism-dependent order, so its last digits are unstable; the
test now compares values with a tolerance.
- Rebase the jaeger v1 fixture on the current instant. It carries
ttl=7d with 2025 timestamps, so its rows were only readable as long as
they stayed in the memtable.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
* test: address review — wire nightly real-S3 job into check-status, keep the short event interval
The nightly `check-status` job did not depend on the new real-S3 job, so a
failure there would not have reached the status or Slack notification.
In database_ddl_event the short interval was set by a first
`with_event_recorder_options` call and then overwritten by the pre-existing
one, which carries `..Default::default()`. Merged into a single call.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
---------
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
214 lines
6.9 KiB
Rust
214 lines
6.9 KiB
Rust
// 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::sync::Arc;
|
|
|
|
use common_test_util::temp_dir::create_temp_dir;
|
|
use common_wal::config::DatanodeWalConfig;
|
|
use tests_integration::cluster::GreptimeDbClusterBuilder;
|
|
use tests_integration::test_util::{
|
|
StorageType, get_test_store_config, setup_authenticated_grpc_database,
|
|
test_event_recorder_options,
|
|
};
|
|
use uuid::Uuid;
|
|
|
|
use crate::event_recorder_test_util::{
|
|
assert_procedure_actor, assert_single_event, find_eventually_string,
|
|
};
|
|
|
|
const CREATE_VIEW_EVENT_TYPE: &str = "create_view";
|
|
const DROP_VIEW_EVENT_TYPE: &str = "drop_view";
|
|
const PROCEDURE_ACTOR: &str = "procedure_actor";
|
|
const PROCEDURE_ACTOR_PASSWORD: &str = "procedure_actor_pwd";
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
async fn test_view_ddl_events() {
|
|
let store_type = StorageType::File;
|
|
if !store_type.test_on() {
|
|
return;
|
|
}
|
|
|
|
common_telemetry::init_default_ut_logging();
|
|
let (store_config, _guard) = get_test_store_config(&store_type);
|
|
let home_dir = create_temp_dir("test_view_ddl_events_data_home");
|
|
let cluster = GreptimeDbClusterBuilder::new("test_view_ddl_events")
|
|
.await
|
|
.with_event_recorder_options(test_event_recorder_options())
|
|
.with_datanodes(1)
|
|
.with_store_config(store_config)
|
|
.with_datanode_wal_config(DatanodeWalConfig::Noop)
|
|
.with_shared_home_dir(Arc::new(home_dir))
|
|
.build(true)
|
|
.await;
|
|
let instance = cluster.fe_instance();
|
|
let suffix = Uuid::new_v4().simple();
|
|
let source_table = format!("view_ddl_event_source_{suffix}");
|
|
let view = format!("view_ddl_event_{suffix}");
|
|
|
|
execute_view_ddl(instance, &source_table, &view).await;
|
|
}
|
|
|
|
async fn execute_view_ddl(
|
|
instance: &Arc<frontend::instance::Instance>,
|
|
source_table: &str,
|
|
view: &str,
|
|
) {
|
|
let (database, _grpc_server) = setup_authenticated_grpc_database(
|
|
instance.clone(),
|
|
PROCEDURE_ACTOR,
|
|
PROCEDURE_ACTOR_PASSWORD,
|
|
)
|
|
.await;
|
|
|
|
database
|
|
.sql(format!(
|
|
"CREATE TABLE {source_table} (host STRING PRIMARY KEY, amount DOUBLE, ts TIMESTAMP TIME INDEX)"
|
|
))
|
|
.await
|
|
.unwrap();
|
|
|
|
database
|
|
.sql(format!(
|
|
"CREATE VIEW {view} AS SELECT amount FROM {source_table}"
|
|
))
|
|
.await
|
|
.unwrap();
|
|
assert_create_events(instance, view).await;
|
|
|
|
database.sql(format!("DROP VIEW {view}")).await.unwrap();
|
|
assert_drop_events(instance, view).await;
|
|
}
|
|
|
|
async fn assert_create_events(instance: &Arc<frontend::instance::Instance>, view: &str) {
|
|
let procedure_id = find_submitted_procedure_id(instance, CREATE_VIEW_EVENT_TYPE, view).await;
|
|
assert_procedure_actor(instance, &procedure_id, Some(PROCEDURE_ACTOR)).await;
|
|
assert_single_event(
|
|
instance,
|
|
&format!(
|
|
r#"SELECT count(*) AS event_count
|
|
FROM greptime_private.events
|
|
WHERE type = '{CREATE_VIEW_EVENT_TYPE}'
|
|
AND procedure_id = '{procedure_id}'
|
|
AND procedure_state = 'Running'
|
|
AND json_path_match(procedure_trigger, '$.type == "Submitted"')
|
|
AND catalog_name = 'greptime'
|
|
AND schema_name = 'public'
|
|
AND view_name = '{view}'
|
|
AND view_id IS NULL
|
|
AND json_path_match(payload, '$.version == 1')
|
|
AND json_path_match(payload, '$.or_replace == false')
|
|
AND json_path_match(payload, '$.create_if_not_exists == false')
|
|
AND json_path_match(payload, '$.referenced_table_count == 1')
|
|
AND json_path_match(payload, '$.column_count == 0')"#,
|
|
),
|
|
)
|
|
.await;
|
|
assert_event_context(instance, CREATE_VIEW_EVENT_TYPE, &procedure_id).await;
|
|
assert_single_event(
|
|
instance,
|
|
&format!(
|
|
r#"SELECT count(*) AS event_count
|
|
FROM greptime_private.events
|
|
WHERE type = '{CREATE_VIEW_EVENT_TYPE}'
|
|
AND procedure_id = '{procedure_id}'
|
|
AND procedure_state = 'Done'
|
|
AND json_path_match(procedure_trigger, '$.type == "Succeeded"')
|
|
AND catalog_name = 'greptime'
|
|
AND schema_name = 'public'
|
|
AND view_name = '{view}'
|
|
AND view_id IS NOT NULL
|
|
AND json_is_null(payload)"#,
|
|
),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
async fn assert_event_context(
|
|
instance: &Arc<frontend::instance::Instance>,
|
|
event_type: &str,
|
|
procedure_id: &str,
|
|
) {
|
|
let actual = find_eventually_string(
|
|
instance,
|
|
&format!(
|
|
"SELECT json_to_string(event_context) AS event_context FROM greptime_private.events WHERE type = '{event_type}' AND procedure_id = '{procedure_id}' AND json_path_match(procedure_trigger, '$.type == \"Submitted\"')"
|
|
),
|
|
"event_context",
|
|
)
|
|
.await;
|
|
assert_eq!(r#"{"protocol":"grpc","reason":"manual"}"#, actual);
|
|
}
|
|
|
|
async fn assert_drop_events(instance: &Arc<frontend::instance::Instance>, view: &str) {
|
|
let procedure_id = find_submitted_procedure_id(instance, DROP_VIEW_EVENT_TYPE, view).await;
|
|
assert_procedure_actor(instance, &procedure_id, Some(PROCEDURE_ACTOR)).await;
|
|
assert_single_event(
|
|
instance,
|
|
&format!(
|
|
r#"SELECT count(*) AS event_count
|
|
FROM greptime_private.events
|
|
WHERE type = '{DROP_VIEW_EVENT_TYPE}'
|
|
AND procedure_id = '{procedure_id}'
|
|
AND procedure_state = 'Running'
|
|
AND json_path_match(procedure_trigger, '$.type == "Submitted"')
|
|
AND catalog_name = 'greptime'
|
|
AND schema_name = 'public'
|
|
AND view_name = '{view}'
|
|
AND view_id IS NOT NULL
|
|
AND json_path_match(payload, '$.version == 1')
|
|
AND json_path_match(payload, '$.drop_if_exists == false')"#,
|
|
),
|
|
)
|
|
.await;
|
|
assert_event_context(instance, DROP_VIEW_EVENT_TYPE, &procedure_id).await;
|
|
assert_single_event(
|
|
instance,
|
|
&format!(
|
|
r#"SELECT count(*) AS event_count
|
|
FROM greptime_private.events
|
|
WHERE type = '{DROP_VIEW_EVENT_TYPE}'
|
|
AND procedure_id = '{procedure_id}'
|
|
AND procedure_state = 'Done'
|
|
AND json_path_match(procedure_trigger, '$.type == "Succeeded"')
|
|
AND catalog_name = 'greptime'
|
|
AND schema_name = 'public'
|
|
AND view_name = '{view}'
|
|
AND view_id IS NOT NULL
|
|
AND json_is_null(payload)"#,
|
|
),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
async fn find_submitted_procedure_id(
|
|
instance: &Arc<frontend::instance::Instance>,
|
|
event_type: &str,
|
|
view_name: &str,
|
|
) -> String {
|
|
find_eventually_string(
|
|
instance,
|
|
&format!(
|
|
r#"SELECT procedure_id
|
|
FROM greptime_private.events
|
|
WHERE type = '{event_type}'
|
|
AND view_name = '{view_name}'
|
|
AND json_path_match(procedure_trigger, '$.type == "Submitted"')
|
|
ORDER BY timestamp DESC
|
|
LIMIT 1"#,
|
|
),
|
|
"procedure_id",
|
|
)
|
|
.await
|
|
}
|