use rudb::Database;
use rudb_metrics::Document;
fn measured(rows: i64, keys: i64, threads: usize) -> Document {
let database = Database::new();
let connection = database.connect();
connection.execute(&format!("SET threads = {threads}")).expect("sets the thread count");
connection
.execute(&format!(
"CREATE TABLE t AS SELECT i % {keys} AS k, i AS v FROM range(0, {rows}) AS r(i)"
))
.expect("builds the table");
let result = connection
.query("SELECT k, COUNT(*) AS c, SUM(v) AS s FROM t GROUP BY k")
.expect("runs the aggregate");
result.metrics().expect("a query that ran has metrics").clone()
}
fn phase(metrics: &Document, phase: &str) -> u64 {
let aggregate = metrics
.operators
.iter()
.find(|operator| operator.kind == "Aggregate")
.expect("the query contains an aggregate");
aggregate
.stages
.taken()
.find(|(stage, _, _)| stage.name() == phase)
.map_or(0, |(_, nanos, _)| nanos)
}
#[test]
fn an_aggregate_says_how_long_it_spent_folding_rows() {
let metrics = measured(200_000, 50_000, 4);
assert!(phase(&metrics, "fold") > 0, "folding rows was charged nothing");
}
#[test]
fn an_aggregate_says_how_long_it_spent_turning_tables_into_rows() {
let metrics = measured(200_000, 50_000, 4);
assert!(phase(&metrics, "emit") > 0, "emitting the answer was charged nothing");
}
#[test]
fn the_threads_an_aggregate_starts_for_itself_report_what_they_spent() {
let together = measured(200_000, 50_000, 4);
let alone = measured(200_000, 50_000, 1);
assert!(phase(&together, "emit") > 0, "the threads the aggregate started reported nothing");
assert!(phase(&alone, "emit") > 0, "one thread closing every partition reported nothing");
}
#[test]
fn one_thread_has_no_table_to_merge_and_several_threads_do() {
let alone = measured(4_000, 10, 1);
let together = measured(4_000, 10, 4);
assert_eq!(phase(&alone, "merge"), 0, "one worker merged a table with itself");
assert!(phase(&together, "merge") > 0, "four workers' tables met without being charged");
}
#[test]
fn a_scan_still_reports_the_stages_of_a_read() {
let database = Database::new();
let result = database
.query("SELECT COUNT(*) FROM range(0, 1000) AS r(i)")
.expect("runs a query with no aggregate phases worth naming");
assert!(result.metrics().is_some(), "a query that ran has metrics");
}