mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-03 02:25:35 +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>
173 lines
7.7 KiB
Rust
173 lines
7.7 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 frontend::instance::Instance;
|
|
use servers::query_handler::sql::SqlQueryHandler;
|
|
use session::context::QueryContext;
|
|
use sql::ast::FunctionArguments;
|
|
use sql::dialect::GreptimeDbDialect;
|
|
use sql::parser::{ParseOptions, ParserContext};
|
|
use sql::statements::admin::Admin;
|
|
use sql::statements::statement::Statement;
|
|
use tests_integration::standalone::GreptimeDbStandaloneBuilder;
|
|
use tests_integration::test_util::test_event_recorder_options;
|
|
|
|
use crate::event_recorder_test_util::assert_eventually_eq;
|
|
|
|
const TABLE_NAME: &str = "admin_function_event_test";
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
async fn test_standalone_admin_function_events() {
|
|
common_telemetry::init_default_ut_logging();
|
|
let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_admin_function_events")
|
|
.with_event_recorder_options(test_event_recorder_options())
|
|
.build()
|
|
.await;
|
|
assert_admin_function_events(standalone.fe_instance()).await;
|
|
}
|
|
|
|
async fn assert_admin_function_events(instance: &Arc<Instance>) {
|
|
execute(
|
|
instance,
|
|
&format!("CREATE TABLE {TABLE_NAME} (ts TIMESTAMP TIME INDEX)"),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
execute(instance, &format!("ADMIN FLUSH_TABLE('{TABLE_NAME}')"))
|
|
.await
|
|
.unwrap();
|
|
|
|
assert_admin_event(
|
|
instance,
|
|
"flush_table",
|
|
"\
|
|
+----------------+----------+---------------------+-----------+---------------------------------------------------------------------------------+--------------+
|
|
| type | actor | admin_function_name | status | payload | output |
|
|
+----------------+----------+---------------------+-----------+---------------------------------------------------------------------------------+--------------+
|
|
| admin_function | greptime | flush_table | Succeeded | {\"arguments\":{\"type\":\"list\",\"value\":[\"admin_function_event_test\"]},\"version\":1} | {\"result\":0} |
|
|
+----------------+----------+---------------------+-----------+---------------------------------------------------------------------------------+--------------+",
|
|
)
|
|
.await;
|
|
|
|
let failure = execute(instance, "ADMIN missing_admin_function('missing-input')").await;
|
|
assert!(failure.is_err());
|
|
|
|
assert_admin_event(
|
|
instance,
|
|
"missing_admin_function",
|
|
"\
|
|
+----------------+----------+------------------------+--------+---------------------------------------------------------------------+-----------------------------------------------------------------+
|
|
| type | actor | admin_function_name | status | payload | output |
|
|
+----------------+----------+------------------------+--------+---------------------------------------------------------------------+-----------------------------------------------------------------+
|
|
| admin_function | greptime | missing_admin_function | Failed | {\"arguments\":{\"type\":\"list\",\"value\":[\"missing-input\"]},\"version\":1} | {\"error\":\"0: Admin function not found: missing_admin_function\"} |
|
|
+----------------+----------+------------------------+--------+---------------------------------------------------------------------+-----------------------------------------------------------------+",
|
|
)
|
|
.await;
|
|
|
|
let failure =
|
|
execute_with_arguments(instance, "missing_no_arguments", FunctionArguments::None).await;
|
|
assert!(failure.is_err());
|
|
|
|
assert_admin_event(
|
|
instance,
|
|
"missing_no_arguments",
|
|
"\
|
|
+----------------+----------+----------------------+--------+---------------+---------------------------------------------------------------+
|
|
| type | actor | admin_function_name | status | payload | output |
|
|
+----------------+----------+----------------------+--------+---------------+---------------------------------------------------------------+
|
|
| admin_function | greptime | missing_no_arguments | Failed | {\"version\":1} | {\"error\":\"0: Admin function not found: missing_no_arguments\"} |
|
|
+----------------+----------+----------------------+--------+---------------+---------------------------------------------------------------+",
|
|
)
|
|
.await;
|
|
|
|
let Statement::Query(query) = ParserContext::create_with_dialect(
|
|
"SELECT 1",
|
|
&GreptimeDbDialect {},
|
|
ParseOptions::default(),
|
|
)
|
|
.unwrap()
|
|
.remove(0) else {
|
|
panic!("expected query statement")
|
|
};
|
|
let failure = execute_with_arguments(
|
|
instance,
|
|
"missing_subquery",
|
|
FunctionArguments::Subquery(Box::new(query.inner)),
|
|
)
|
|
.await;
|
|
assert!(failure.is_err());
|
|
|
|
assert_admin_event(
|
|
instance,
|
|
"missing_subquery",
|
|
"\
|
|
+----------------+----------+---------------------+--------+------------------------------------------------------------------+-----------------------------------------------------------+
|
|
| type | actor | admin_function_name | status | payload | output |
|
|
+----------------+----------+---------------------+--------+------------------------------------------------------------------+-----------------------------------------------------------+
|
|
| admin_function | greptime | missing_subquery | Failed | {\"arguments\":{\"type\":\"subquery\",\"value\":\"SELECT 1\"},\"version\":1} | {\"error\":\"0: Admin function not found: missing_subquery\"} |
|
|
+----------------+----------+---------------------+--------+------------------------------------------------------------------+-----------------------------------------------------------+",
|
|
)
|
|
.await;
|
|
}
|
|
|
|
async fn assert_admin_event(instance: &Arc<Instance>, function: &str, expected: &str) {
|
|
let query = format!(
|
|
r#"SELECT
|
|
type,
|
|
actor,
|
|
admin_function_name,
|
|
admin_function_status AS status,
|
|
json_to_string(payload) AS payload,
|
|
json_to_string(admin_function_output) AS output
|
|
FROM greptime_private.events
|
|
WHERE type = 'admin_function'
|
|
AND admin_function_name = '{function}'
|
|
ORDER BY timestamp DESC
|
|
LIMIT 1"#
|
|
);
|
|
assert_eventually_eq(instance, &query, expected).await;
|
|
}
|
|
|
|
async fn execute(
|
|
instance: &Arc<Instance>,
|
|
sql: &str,
|
|
) -> servers::error::Result<common_query::Output> {
|
|
instance.do_query(sql, QueryContext::arc()).await.remove(0)
|
|
}
|
|
|
|
async fn execute_with_arguments(
|
|
instance: &Arc<Instance>,
|
|
function: &str,
|
|
arguments: FunctionArguments,
|
|
) -> operator::error::Result<common_query::Output> {
|
|
let Statement::Admin(mut statement) = ParserContext::create_with_dialect(
|
|
&format!("ADMIN {function}()"),
|
|
&GreptimeDbDialect {},
|
|
ParseOptions::default(),
|
|
)
|
|
.unwrap()
|
|
.remove(0) else {
|
|
panic!("expected ADMIN statement")
|
|
};
|
|
let Admin::Func(admin_function) = &mut statement;
|
|
admin_function.args = arguments;
|
|
|
|
instance
|
|
.statement_executor()
|
|
.execute_sql(Statement::Admin(statement), QueryContext::arc())
|
|
.await
|
|
}
|