test(promql): drop redundant and no-op unit tests (#15285)

This commit is contained in:
Huaijin
2026-10-13 07:14:46 +00:00
committed by GitHub
parent 6df43be42f
commit fe3cb94aef
42 changed files with 5 additions and 2124 deletions
-24
View File
@@ -113,30 +113,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_avg_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Avg, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_avg_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Avg, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_avg_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Avg, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_avg_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-24
View File
@@ -82,30 +82,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_count_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Count, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_count_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Count, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_count_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Count, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_count_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-13
View File
@@ -78,16 +78,3 @@ impl<const IS_MAX: bool> Accumulate for ExtremaAccumulator<IS_MAX> {
group_series(group_labels, samples)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_min_and_max_have_distinct_accumulator_types() {
assert_ne!(
std::any::TypeId::of::<ExtremaAccumulator<false>>(),
std::any::TypeId::of::<ExtremaAccumulator<true>>(),
);
}
}
-24
View File
@@ -83,30 +83,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_group_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Group, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_group_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Group, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_group_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Group, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_group_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-24
View File
@@ -39,30 +39,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_max_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Max, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_max_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Max, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_max_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Max, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_max_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-24
View File
@@ -39,30 +39,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_min_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Min, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_min_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Min, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_min_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Min, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_min_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-49
View File
@@ -537,14 +537,6 @@ mod tests {
use super::*;
// Test data helpers
fn create_test_labels() -> Labels {
vec![
Arc::new(Label::new("instance", "localhost:9090")),
Arc::new(Label::new("job", "prometheus")),
Arc::new(Label::new("__name__", "http_requests_total")),
]
}
fn labels_to_include(
include_labels: &[String],
mut actual_labels: Vec<Arc<Label>>,
@@ -562,19 +554,6 @@ mod tests {
actual_labels
}
#[test]
fn test_labels_to_include() {
let actual_labels = create_test_labels();
let include_labels = vec!["instance".to_string(), "job".to_string()];
let result = labels_to_include(&include_labels, actual_labels.clone());
assert_eq!(result.len(), 2);
assert!(result.iter().any(|l| l.name == "instance"));
assert!(result.iter().any(|l| l.name == "job"));
assert!(!result.iter().any(|l| l.name == "__name__"));
}
/// One value of a label-less series, for the scalar accumulators that never read labels.
fn push<A: Accumulate>(acc: &mut A, slot: usize, value: f64) {
acc.push_series(std::iter::once((slot, value)), Labels::default);
@@ -986,34 +965,6 @@ mod tests {
assert_eq!(eval_chunked_single_group(&values, Avg), -2.0 / n as f64);
}
#[test]
fn test_labels_to_exclude_removes_name_label() {
let actual_labels = create_test_labels();
let exclude_labels = vec!["instance".to_string()];
let result = labels_to_exclude(&exclude_labels, actual_labels.clone());
// Should not contain __name__ label (which is NAME_LABEL)
assert!(!result.iter().any(|l| l.name == "__name__"));
}
#[test]
fn test_labels_to_include_empty_include_list() {
let actual_labels = create_test_labels();
let result = labels_to_include(&[], actual_labels);
assert_eq!(result.len(), 0);
}
#[test]
fn test_labels_to_exclude_empty_exclude_list() {
let actual_labels = create_test_labels();
let result = labels_to_exclude(&[], actual_labels);
// NAME_LABEL (__name__) is always excluded
assert!(!result.iter().any(|l| l.name == "__name__"));
assert!(result.iter().any(|l| l.name == "instance"));
assert!(result.iter().any(|l| l.name == "job"));
}
#[test]
fn test_projected_labels_signature_matches_materialized_projection() {
use promql_parser::label::Labels as ParserLabels;
-16
View File
@@ -246,22 +246,6 @@ mod tests {
assert_eq!(result[1].samples[0].value, 30.0);
}
#[test]
fn test_quantile_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = quantile(ScalarParam::Const(0.5), &None, Value::None, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_quantile_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = quantile(ScalarParam::Const(0.5), &None, Value::Float(1.0), &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_quantile_out_of_range_phi_is_per_group() {
let ts = 1000;
-24
View File
@@ -44,30 +44,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_stddev_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Stddev, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_stddev_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Stddev, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_stddev_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Stddev, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_stddev_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-24
View File
@@ -44,30 +44,6 @@ mod tests {
use super::*;
use crate::aggregations::eval_aggregate;
#[test]
fn test_stdvar_value_none_input() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Stdvar, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_stdvar_invalid_input_returns_err() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Stdvar, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_stdvar_empty_matrix_returns_none() {
let timestamp = 1640995200;
let eval_ctx = EvalContext::new(timestamp, timestamp + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Stdvar, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_stdvar_range_function() {
let timestamp = 1640995200; // 2022-01-01 00:00:00 UTC
-24
View File
@@ -148,30 +148,6 @@ mod tests {
}
}
#[test]
fn test_sum_value_none_input() {
let ts = 1640995200;
let eval_ctx = EvalContext::new(ts, ts + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::None, Sum, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_sum_invalid_input_returns_err() {
let ts = 1640995200;
let eval_ctx = EvalContext::new(ts, ts + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Float(1.0), Sum, &eval_ctx);
assert!(result.is_err());
}
#[test]
fn test_sum_empty_matrix_returns_none() {
let ts = 1640995200;
let eval_ctx = EvalContext::new(ts, ts + 1, 1, "test".to_string());
let result = eval_aggregate(&None, Value::Matrix(vec![]), Sum, &eval_ctx).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_sum_range_function() {
// Create test matrix data with multiple series and timestamps
-6
View File
@@ -85,12 +85,6 @@ mod tests {
assert_eq!(visitor.name.len(), 1);
}
#[test]
fn test_name_visitor_new_starts_empty() {
let visitor = MetricNameVisitor::new();
assert!(visitor.name.is_empty());
}
#[test]
fn test_name_visitor_resolves_name_label_matcher() {
let promql = r#"sum(rate({__name__="http_requests_total"}[1m]))"#;
-47
View File
@@ -66,53 +66,6 @@ mod tests {
}
}
#[test]
fn test_match_placeholder_equal_op() {
let placeholder = get_config().common.dashboard_placeholder.to_string();
let matcher = create_test_matcher("label", MatchOp::Equal, &placeholder);
assert!(match_placeholder(&matcher, &placeholder));
let non_matching_matcher = create_test_matcher("label", MatchOp::Equal, "other_value");
assert!(!match_placeholder(&non_matching_matcher, &placeholder));
}
#[test]
fn test_match_placeholder_not_equal_op() {
let placeholder = get_config().common.dashboard_placeholder.to_string();
let matcher = create_test_matcher("label", MatchOp::NotEqual, &placeholder);
assert!(match_placeholder(&matcher, &placeholder));
let non_matching_matcher = create_test_matcher("label", MatchOp::NotEqual, "other_value");
assert!(!match_placeholder(&non_matching_matcher, &placeholder));
}
#[test]
fn test_match_placeholder_regex_op() {
let placeholder = get_config().common.dashboard_placeholder.to_string();
let matcher =
create_test_matcher("label", MatchOp::Re(Regex::new("").unwrap()), &placeholder);
assert!(match_placeholder(&matcher, &placeholder));
let non_matching_matcher =
create_test_matcher("label", MatchOp::Re(Regex::new("").unwrap()), "other.*");
assert!(!match_placeholder(&non_matching_matcher, &placeholder));
}
#[test]
fn test_match_placeholder_not_regex_op() {
let placeholder = get_config().common.dashboard_placeholder.to_string();
let matcher = create_test_matcher(
"label",
MatchOp::NotRe(Regex::new("").unwrap()),
&placeholder,
);
assert!(match_placeholder(&matcher, &placeholder));
let non_matching_matcher =
create_test_matcher("label", MatchOp::NotRe(Regex::new("").unwrap()), "other.*");
assert!(!match_placeholder(&non_matching_matcher, &placeholder));
}
#[test]
fn test_remove_filter_all_removes_placeholder_matchers() {
let placeholder = get_config().common.dashboard_placeholder.to_string();
-6
View File
@@ -89,12 +89,6 @@ mod tests {
);
}
#[test]
fn test_selector_visitor_empty() {
let visitor = MetricSelectorVisitor::default();
assert!(visitor.exprs.is_empty());
}
#[test]
fn test_selector_visitor_non_selector_expr_not_collected() {
// Scalar arithmetic has no VectorSelector or MatrixSelector
+1 -357
View File
@@ -600,19 +600,10 @@ pub fn vector_bin_op(
mod tests {
use std::sync::Arc;
use config::meta::promql::value::{Label, Sample, signature};
use config::meta::promql::value::{Label, Sample};
use super::*;
// Helper function to create test data for matrix operations
fn create_test_matrix_data() -> Vec<RangeValue> {
vec![
create_test_range_value(vec![1.0], vec![("instance", "localhost"), ("job", "node")]),
create_test_range_value(vec![2.0], vec![("instance", "localhost"), ("job", "node")]),
create_test_range_value(vec![3.0], vec![("instance", "remote"), ("job", "api")]),
]
}
fn create_test_range_value(values: Vec<f64>, labels: Vec<(&str, &str)>) -> RangeValue {
let labels = labels
.into_iter()
@@ -634,353 +625,6 @@ mod tests {
}
}
// Simple tests that don't require complex BinaryExpr construction
#[test]
fn test_range_value_creation() {
let range = create_test_range_value(vec![42.0], vec![("instance", "localhost")]);
assert_eq!(range.samples[0].value, 42.0);
assert_eq!(range.samples[0].timestamp, 1640995200000000i64);
assert_eq!(range.labels.len(), 1);
assert_eq!(range.labels[0].name, "instance");
assert_eq!(range.labels[0].value, "localhost");
}
#[test]
fn test_range_value_with_multiple_labels() {
let range = create_test_range_value(
vec![100.0],
vec![("env", "prod"), ("region", "us-west"), ("service", "api")],
);
assert_eq!(range.samples[0].value, 100.0);
assert_eq!(range.labels.len(), 3);
let label_names: Vec<&str> = range.labels.iter().map(|l| l.name.as_str()).collect();
assert!(label_names.contains(&"env"));
assert!(label_names.contains(&"region"));
assert!(label_names.contains(&"service"));
}
#[test]
fn test_range_value_empty_labels() {
let range = create_test_range_value(vec![0.0], vec![]);
assert_eq!(range.samples[0].value, 0.0);
assert!(range.labels.is_empty());
}
#[test]
fn test_range_value_numeric_values() {
let test_cases = [
(0.0, "zero"),
(1.0, "positive integer"),
(-1.0, "negative integer"),
(1.234, "positive float"),
(-1.234, "negative float"),
(f64::MAX, "max value"),
(f64::MIN, "min value"),
];
for (value, description) in test_cases {
let range = create_test_range_value(vec![value], vec![("test", description)]);
assert_eq!(range.samples[0].value, value, "Failed for: {description}");
}
}
#[test]
fn test_range_value_timestamp_consistency() {
let range1 = create_test_range_value(vec![1.0], vec![("a", "1")]);
let range2 = create_test_range_value(vec![2.0], vec![("b", "2")]);
// Both should have the same starting timestamp
assert_eq!(range1.samples[0].timestamp, range2.samples[0].timestamp);
assert_eq!(range1.samples[0].timestamp, 1640995200000000i64);
}
#[test]
fn test_label_creation() {
let labels = vec![
("cpu", "0"),
("mode", "idle"),
("instance", "localhost:9100"),
];
let range = create_test_range_value(vec![75.5], labels.clone());
for (i, (expected_name, expected_value)) in labels.iter().enumerate() {
assert_eq!(range.labels[i].name, *expected_name);
assert_eq!(range.labels[i].value, *expected_value);
}
}
#[test]
fn test_label_modification() {
let mut labels = vec![
Arc::new(Label::new("env", "prod")),
Arc::new(Label::new("region", "us-west")),
Arc::new(Label::new("service", "api")),
];
// Test label modification
labels[0] = Arc::new(Label::new("env", "staging"));
assert_eq!(labels[0].value, "staging");
// Test label filtering (simulate what vector operations do)
let filtered_labels: Vec<Arc<Label>> = labels
.into_iter()
.filter(|label| label.name != "env")
.collect();
assert_eq!(filtered_labels.len(), 2);
assert_eq!(filtered_labels[0].name, "region");
assert_eq!(filtered_labels[1].name, "service");
}
#[test]
fn test_matrix_operations_parallel_processing() {
// Test that we can process matrices in parallel (simulating what the actual functions do)
let matrix = vec![
create_test_range_value(vec![1.0], vec![("a", "1")]),
create_test_range_value(vec![2.0], vec![("a", "2")]),
create_test_range_value(vec![3.0], vec![("a", "3")]),
create_test_range_value(vec![4.0], vec![("a", "4")]),
create_test_range_value(vec![5.0], vec![("a", "5")]),
];
// Simulate parallel processing by mapping over the matrix
let processed: Vec<f64> = matrix
.par_iter()
.map(|range| range.samples[0].value * 2.0)
.collect();
assert_eq!(processed.len(), 5);
assert_eq!(processed[0], 2.0);
assert_eq!(processed[1], 4.0);
assert_eq!(processed[2], 6.0);
assert_eq!(processed[3], 8.0);
assert_eq!(processed[4], 10.0);
}
#[test]
fn test_matrix_operations_error_scenarios() {
// Test scenarios that could lead to errors in matrix operations
// Test with very large numbers
let large_matrix = [
create_test_range_value(vec![f64::MAX], vec![("a", "1")]),
create_test_range_value(vec![f64::MIN], vec![("a", "2")]),
];
assert!(large_matrix[0].samples[0].value.is_finite());
assert!(large_matrix[1].samples[0].value.is_finite());
// Test with NaN values
let nan_matrix = [create_test_range_value(vec![f64::NAN], vec![("a", "1")])];
// Should handle NaN gracefully
assert!(nan_matrix[0].samples[0].value.is_nan());
}
#[test]
fn test_matrix_operations_data_structures() {
// Test RangeValue creation and properties
let value =
create_test_range_value(vec![42.0], vec![("label1", "value1"), ("label2", "value2")]);
assert_eq!(value.samples[0].value, 42.0);
assert_eq!(value.labels.len(), 2);
assert_eq!(value.labels[0].name, "label1");
assert_eq!(value.labels[0].value, "value1");
assert_eq!(value.labels[1].name, "label2");
assert_eq!(value.labels[1].value, "value2");
}
#[test]
fn test_matrix_operations_timestamp_consistency() {
let timestamp = 1640995200000000i64;
let value = create_test_range_value(vec![10.0], vec![("test", "value")]);
assert_eq!(value.samples[0].timestamp, timestamp);
}
#[test]
fn test_matrix_operations_label_handling() {
let value = create_test_range_value(vec![5.0], vec![("a", "1"), ("b", "2"), ("c", "3")]);
assert_eq!(value.labels.len(), 3);
// Test label ordering and values
let labels = &value.labels;
assert_eq!(labels[0].name, "a");
assert_eq!(labels[0].value, "1");
assert_eq!(labels[1].name, "b");
assert_eq!(labels[1].value, "2");
assert_eq!(labels[2].name, "c");
assert_eq!(labels[2].value, "3");
}
#[test]
fn test_matrix_operations_empty_labels() {
let value = create_test_range_value(vec![0.0], vec![]);
assert_eq!(value.labels.len(), 0);
assert_eq!(value.samples[0].value, 0.0);
}
#[test]
fn test_matrix_operations_negative_values() {
let value = create_test_range_value(vec![-15.5], vec![("negative", "test")]);
assert_eq!(value.samples[0].value, -15.5);
assert_eq!(value.labels.len(), 1);
assert_eq!(value.labels[0].name, "negative");
assert_eq!(value.labels[0].value, "test");
}
#[test]
fn test_matrix_operations_large_numbers() {
let value = create_test_range_value(vec![1e15], vec![("large", "number")]);
assert_eq!(value.samples[0].value, 1e15);
assert_eq!(value.labels.len(), 1);
}
#[test]
fn test_matrix_operations_special_floats() {
let value = create_test_range_value(vec![f64::INFINITY], vec![("inf", "test")]);
assert!(value.samples[0].value.is_infinite());
assert!(value.samples[0].value.is_sign_positive());
let value = create_test_range_value(vec![f64::NEG_INFINITY], vec![("neg_inf", "test")]);
assert!(value.samples[0].value.is_infinite());
assert!(value.samples[0].value.is_sign_negative());
let value = create_test_range_value(vec![f64::NAN], vec![("nan", "test")]);
assert!(value.samples[0].value.is_nan());
}
#[test]
fn test_matrix_operations_unicode_labels() {
let value = create_test_range_value(
vec![1.0],
vec![("🚀", "🚀"), ("测试", "测试"), ("🎉", "🎉")],
);
assert_eq!(value.labels.len(), 3);
assert_eq!(value.labels[0].name, "🚀");
assert_eq!(value.labels[0].value, "🚀");
assert_eq!(value.labels[1].name, "测试");
assert_eq!(value.labels[1].value, "测试");
assert_eq!(value.labels[2].name, "🎉");
assert_eq!(value.labels[2].value, "🎉");
}
#[test]
fn test_matrix_operations_long_labels() {
let long_name = "a".repeat(1000);
let long_value = "b".repeat(1000);
let value = create_test_range_value(vec![1.0], vec![(&long_name, &long_value)]);
assert_eq!(value.labels.len(), 1);
assert_eq!(value.labels[0].name, long_name);
assert_eq!(value.labels[0].value, long_value);
}
#[test]
fn test_matrix_operations_duplicate_labels() {
let value = create_test_range_value(vec![1.0], vec![("a", "1"), ("a", "2"), ("a", "3")]);
assert_eq!(value.labels.len(), 3);
// All labels should be preserved even if names are duplicate
assert_eq!(value.labels[0].name, "a");
assert_eq!(value.labels[0].value, "1");
assert_eq!(value.labels[1].name, "a");
assert_eq!(value.labels[1].value, "2");
assert_eq!(value.labels[2].name, "a");
assert_eq!(value.labels[2].value, "3");
}
#[test]
fn test_matrix_operations_edge_case_values() {
let value = create_test_range_value(vec![f64::EPSILON], vec![("epsilon", "test")]);
assert_eq!(value.samples[0].value, f64::EPSILON);
let value =
create_test_range_value(vec![f64::MIN_POSITIVE], vec![("min_positive", "test")]);
assert_eq!(value.samples[0].value, f64::MIN_POSITIVE);
let value = create_test_range_value(vec![f64::MAX], vec![("max", "test")]);
assert_eq!(value.samples[0].value, f64::MAX);
}
#[test]
fn test_matrix_operations_matrix_data() {
let matrix_data = create_test_matrix_data();
assert_eq!(matrix_data.len(), 3);
// Test first element
assert_eq!(matrix_data[0].samples[0].value, 1.0);
assert_eq!(matrix_data[0].labels.len(), 2);
assert_eq!(matrix_data[0].labels[0].name, "instance");
assert_eq!(matrix_data[0].labels[0].value, "localhost");
// Test second element
assert_eq!(matrix_data[1].samples[0].value, 2.0);
assert_eq!(matrix_data[1].labels.len(), 2);
// Test third element
assert_eq!(matrix_data[2].samples[0].value, 3.0);
assert_eq!(matrix_data[2].labels.len(), 2);
assert_eq!(matrix_data[2].labels[0].name, "instance");
assert_eq!(matrix_data[2].labels[0].value, "remote");
}
#[test]
fn test_matrix_operations_label_signatures() {
let value1 = create_test_range_value(vec![1.0], vec![("a", "1"), ("b", "2")]);
let value2 = create_test_range_value(vec![2.0], vec![("a", "1"), ("b", "2")]);
let value3 = create_test_range_value(vec![3.0], vec![("a", "1"), ("b", "3")]);
// value1 and value2 should have the same signature (same labels)
let sig1 = signature(&value1.labels);
let sig2 = signature(&value2.labels);
let sig3 = signature(&value3.labels);
assert_eq!(sig1, sig2);
assert_ne!(sig1, sig3);
assert_ne!(sig2, sig3);
}
#[test]
fn test_matrix_operations_empty_matrix() {
let empty_matrix: Vec<RangeValue> = vec![];
assert_eq!(empty_matrix.len(), 0);
// Test that we can create an empty matrix and it doesn't panic
let empty_matrix_with_capacity: Vec<RangeValue> = Vec::with_capacity(100);
assert_eq!(empty_matrix_with_capacity.len(), 0);
assert_eq!(empty_matrix_with_capacity.capacity(), 100);
}
#[test]
fn test_matrix_operations_single_element() {
let single_element = [create_test_range_value(
vec![42.0],
vec![("single", "test")],
)];
assert_eq!(single_element.len(), 1);
assert_eq!(single_element[0].samples[0].value, 42.0);
assert_eq!(single_element[0].labels.len(), 1);
assert_eq!(single_element[0].labels[0].name, "single");
assert_eq!(single_element[0].labels[0].value, "test");
}
#[test]
fn test_matrix_operations_multiple_samples() {
// Test RangeValue with multiple samples
let value =
create_test_range_value(vec![1.0, 2.0, 3.0, 4.0, 5.0], vec![("metric", "test")]);
assert_eq!(value.samples.len(), 5);
assert_eq!(value.samples[0].value, 1.0);
assert_eq!(value.samples[1].value, 2.0);
assert_eq!(value.samples[2].value, 3.0);
assert_eq!(value.samples[3].value, 4.0);
assert_eq!(value.samples[4].value, 5.0);
// Check timestamps are incrementing
for i in 1..value.samples.len() {
assert!(value.samples[i].timestamp > value.samples[i - 1].timestamp);
}
}
fn try_eval_bin_op(
query: &str,
left: Vec<RangeValue>,
-74
View File
@@ -186,18 +186,6 @@ mod tests {
assert_eq!(quantile(&infinite, 0.75), Some(f64::INFINITY));
}
#[test]
fn test_quantile() {
let data = vec![4.0, 2.0, 1.0, 3.0, 5.0];
let phi_quantile = 0.5;
let result = quantile(&data, phi_quantile);
let expected = 3.0;
match result {
Some(got) => assert_eq!(got, expected),
None => panic!(),
}
}
#[test]
fn test_quantile_comprehensive() {
// Test basic quartiles
@@ -414,68 +402,6 @@ mod tests {
assert_eq!(result, None);
}
#[test]
fn test_calculate_trend() {
// Test first iteration (index == 0)
let result = calculate_trend(0, 0.1, 10.0, 12.0, 1.0);
assert_eq!(result, 1.0);
// Test normal case
let result = calculate_trend(1, 0.1, 10.0, 12.0, 1.0);
// trend_factor * (current_smoothed - previous_smoothed) + (1.0 - trend_factor) *
// previous_trend 0.1 * (12.0 - 10.0) + 0.9 * 1.0 = 0.2 + 0.9 = 1.1
assert!((result - 1.1).abs() < 1e-10);
// Test with zero trend factor
let result = calculate_trend(1, 0.0, 10.0, 12.0, 1.0);
assert_eq!(result, 1.0);
// Test with one trend factor
let result = calculate_trend(1, 1.0, 10.0, 12.0, 1.0);
assert_eq!(result, 2.0);
}
#[test]
fn test_linear_regression() {
// Test with constant y values
let samples = vec![
Sample::new(1000, 5.0),
Sample::new(2000, 5.0),
Sample::new(3000, 5.0),
];
let result = linear_regression(&samples, 0);
assert!(result.is_some());
let (slope, intercept) = result.unwrap();
assert_eq!(slope, 0.0);
assert_eq!(intercept, 5.0);
// Test with linear relationship
let samples = vec![
Sample::new(1000, 1.0),
Sample::new(2000, 2.0),
Sample::new(3000, 3.0),
];
let result = linear_regression(&samples, 0);
assert!(result.is_some());
let (slope, intercept) = result.unwrap();
// Slope should be 1000.0 (y increases by 1 for each 0.001 increase in x)
assert!((slope - 1000.0).abs() < 1e-6);
assert!((intercept - 0.0).abs() < 1e-6);
// Test with infinite values
let samples = vec![
Sample::new(1000, f64::INFINITY),
Sample::new(2000, f64::INFINITY),
];
let (slope, intercept) = linear_regression(&samples, 0).unwrap();
assert!(slope.is_nan() && intercept.is_nan());
// Test with empty samples
let samples: Vec<Sample> = vec![];
let result = linear_regression(&samples, 0);
assert!(result.is_none());
}
#[test]
fn test_kahan_sum_increment() {
// Test basic increment
-21
View File
@@ -346,27 +346,6 @@ mod tests {
);
}
#[test]
fn test_fused_agg_shape_ignores_the_parameter() {
assert_eq!(
shape("topk(3, rate(m[5m]))"),
Some((
"rate".to_string(),
true,
Some(Some(Duration::from_secs(300)))
))
);
assert_eq!(
shape("bottomk by(instance) (2, m{job=\"a\"} offset 1m)"),
Some(("last_over_time".to_string(), false, Some(None)))
);
assert_eq!(
shape("topk(scalar(m), m)"),
Some(("last_over_time".to_string(), false, Some(None)))
);
assert_eq!(shape("topk(3, abs(m))"), None);
}
/// `n` series `{instance="<i>", job="api"|"db"}` whose values differ at every step.
fn requests(n: usize) -> String {
(0..n)
-155
View File
@@ -803,161 +803,6 @@ mod tests {
}
}
#[tokio::test]
async fn test_call_expr_first_arg() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs {
args: vec![Box::new(PromExpr::NumberLiteral(NumberLiteral {
val: 42.0,
}))],
};
let result = engine.call_expr_arg(&args, 0).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
#[tokio::test]
async fn test_call_expr_second_arg() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs {
args: vec![
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 10.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 42.0 })),
],
};
let result = engine.call_expr_arg(&args, 1).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
#[tokio::test]
async fn test_call_expr_third_arg() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs {
args: vec![
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 10.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 20.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 42.0 })),
],
};
let result = engine.call_expr_arg(&args, 2).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
#[tokio::test]
async fn test_call_expr_fourth_arg() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs {
args: vec![
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 10.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 20.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 30.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 42.0 })),
],
};
let result = engine.call_expr_arg(&args, 3).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
#[tokio::test]
async fn test_call_expr_fifth_arg() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs {
args: vec![
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 10.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 20.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 30.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 40.0 })),
Box::new(PromExpr::NumberLiteral(NumberLiteral { val: 42.0 })),
],
};
let result = engine.call_expr_arg(&args, 4).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
const SECOND: i64 = 1_000_000;
const BASE: i64 = 1_640_995_200;
+3 -325
View File
@@ -226,11 +226,10 @@ pub(crate) mod tests {
use std::{sync::Arc, time::Duration};
use promql_parser::{
label::{MatchOp, Matchers},
label::Matchers,
parser::{
AggregateExpr, BinaryExpr, Call, EvalStmt, Extension, Function, FunctionArgs,
MatrixSelector, NumberLiteral, Offset, ParenExpr, StringLiteral, SubqueryExpr,
UnaryExpr, VectorSelector, token, value::ValueType,
AggregateExpr, BinaryExpr, EvalStmt, Extension, NumberLiteral, ParenExpr,
StringLiteral, SubqueryExpr, UnaryExpr, token, value::ValueType,
},
};
@@ -426,26 +425,6 @@ pub(crate) mod tests {
TwoInstanceProvider(ctx, vec![])
}
#[test]
fn test_engine_new() {
// Test basic engine creation with a simple mock
let trace_id = "test_trace";
let org_id = "test_org";
let engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
assert_eq!(engine.trace_id, trace_id.to_string());
assert!(engine.label_selector.is_empty());
assert!(engine.result_type.is_none());
}
/// The guard must not fire on a query that merely LOOKS adjacent — `offset`
/// is genuinely implemented and must keep working.
#[tokio::test]
@@ -475,31 +454,6 @@ pub(crate) mod tests {
}
}
#[tokio::test]
async fn test_exec_expr_number_literal() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let expr = PromExpr::NumberLiteral(NumberLiteral { val: 42.0 });
let result = engine.exec_expr(&expr).await;
assert!(result.is_ok());
if let Ok(Value::Float(val)) = result {
assert_eq!(val, 42.0);
} else {
panic!("Expected Value::Float");
}
}
#[tokio::test]
async fn test_exec_expr_string_literal() {
let trace_id = "test_trace";
@@ -626,39 +580,6 @@ pub(crate) mod tests {
}
}
#[tokio::test]
async fn test_exec_expr_unary_vector() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let sample = Sample::new(1640995200000000i64, 42.0);
let instant = InstantValue {
labels: vec![Arc::new(Label::new("env", "prod"))],
sample,
};
let _vector = Value::Vector(vec![instant]);
let vector_expr = PromExpr::Extension(Extension {
expr: Arc::new(TestExtension),
});
let expr = PromExpr::Unary(UnaryExpr {
expr: Box::new(vector_expr),
});
let result = engine.exec_expr(&expr).await;
// This will fail because Extension is not implemented, but we're testing the unary logic
assert!(result.is_err());
}
#[tokio::test]
async fn test_exec_expr_binary_float_float() {
let trace_id = "test_trace";
@@ -897,38 +818,6 @@ pub(crate) mod tests {
assert_eq!(series[0].samples[0].value, 1.0);
}
#[tokio::test]
async fn test_exec_expr_binary_none_none() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let lhs = PromExpr::Extension(Extension {
expr: Arc::new(TestExtension),
});
let rhs = PromExpr::Extension(Extension {
expr: Arc::new(TestExtension),
});
let expr = PromExpr::Binary(BinaryExpr {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: create_test_token(),
modifier: None,
});
let result = engine.exec_expr(&expr).await;
// This will fail because Extension is not implemented, but we're testing the binary logic
assert!(result.is_err());
}
#[tokio::test]
async fn test_exec_expr_subquery() {
let trace_id = "test_trace";
@@ -963,108 +852,6 @@ pub(crate) mod tests {
);
}
#[tokio::test]
async fn test_exec_expr_subquery_with_offset() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let expr = PromExpr::NumberLiteral(NumberLiteral { val: 42.0 });
let offset = Some(Offset::Pos(Duration::from_secs(60)));
let subquery_expr = PromExpr::Subquery(SubqueryExpr {
expr: Box::new(expr),
range: Duration::from_secs(300),
offset,
step: None,
at: None,
});
let result = engine.exec_expr(&subquery_expr).await;
// Subquery with float input should fail because subquery expects matrix input
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("Unsupported subquery")
);
}
#[tokio::test]
async fn test_exec_expr_subquery_vector() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let sample = Sample::new(1640995200000000i64, 42.0);
let _instant = InstantValue {
labels: vec![Arc::new(Label::new("env", "prod"))],
sample,
};
let vector = PromExpr::Extension(Extension {
expr: Arc::new(TestExtension),
});
let subquery_expr = PromExpr::Subquery(SubqueryExpr {
expr: Box::new(vector),
range: Duration::from_secs(300),
offset: None,
step: None,
at: None,
});
let result = engine.exec_expr(&subquery_expr).await;
// This will fail because Extension is not implemented, but we're testing the subquery logic
assert!(result.is_err());
}
#[tokio::test]
async fn test_exec_expr_subquery_float() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let float_expr = PromExpr::Extension(Extension {
expr: Arc::new(TestExtension),
});
let subquery_expr = PromExpr::Subquery(SubqueryExpr {
expr: Box::new(float_expr),
range: Duration::from_secs(300),
offset: None,
step: None,
at: None,
});
let result = engine.exec_expr(&subquery_expr).await;
// This will fail because Extension is not implemented, but we're testing the subquery logic
assert!(result.is_err());
}
#[tokio::test]
async fn test_exec_expr_aggregate() {
let trace_id = "test_trace";
@@ -1093,34 +880,6 @@ pub(crate) mod tests {
assert!(result.is_err());
}
#[tokio::test]
async fn test_exec_expr_call() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let args = FunctionArgs { args: vec![] };
let func = Function {
name: "time",
arg_types: vec![],
variadic: 0,
experimental: false,
return_type: ValueType::Scalar,
};
let expr = PromExpr::Call(Call { func, args });
let result = engine.exec_expr(&expr).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_exec_expr_extension() {
let trace_id = "test_trace";
@@ -1149,87 +908,6 @@ pub(crate) mod tests {
);
}
#[tokio::test]
async fn test_exec_expr_vector_selector() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: None,
at: None,
};
let expr = PromExpr::VectorSelector(selector);
let result = engine.exec_expr(&expr).await;
// This will fail because the mock provider doesn't have real data, but we're testing the
// vector selector logic
assert!(result.is_ok());
}
#[tokio::test]
async fn test_exec_expr_matrix_selector() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: None,
at: None,
};
let matrix_selector = MatrixSelector {
vs: selector,
range: Duration::from_secs(300),
};
let expr = PromExpr::MatrixSelector(matrix_selector);
let result = engine.exec_expr(&expr).await;
// This will fail because the mock provider doesn't have real data, but we're testing the
// matrix selector logic
assert!(result.is_ok());
}
#[tokio::test]
async fn test_exec() {
let trace_id = "test_trace";
+1 -191
View File
@@ -682,7 +682,7 @@ mod tests {
use datafusion::{arrow::datatypes::Schema, prelude::SessionContext};
use promql_parser::{
label::{MatchOp, Matchers},
parser::{Offset, VectorSelector},
parser::VectorSelector,
};
use super::*;
@@ -775,158 +775,6 @@ mod tests {
assert_eq!(matchers.matchers[0].name, "env");
}
#[tokio::test]
async fn test_eval_vector_selector_basic() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: None,
at: None,
};
let result = engine
.eval_vector_selector(&selector, None, SelectorOutput::Value)
.await;
assert!(result.is_ok());
let values = result.unwrap();
assert_eq!(values.len(), 0); // Mock provider returns empty data
}
#[tokio::test]
async fn test_eval_vector_selector_with_offset() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: Some(Offset::Pos(Duration::from_secs(60))),
at: None,
};
let result = engine
.eval_vector_selector(&selector, None, SelectorOutput::Value)
.await;
assert!(result.is_ok());
let values = result.unwrap();
assert_eq!(values.len(), 0); // Mock provider returns empty data
}
#[tokio::test]
async fn test_eval_vector_selector_with_negative_offset() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: Some(Offset::Neg(Duration::from_secs(60))),
at: None,
};
let result = engine
.eval_vector_selector(&selector, None, SelectorOutput::Value)
.await;
assert!(result.is_ok());
let values = result.unwrap();
assert_eq!(values.len(), 0); // Mock provider returns empty data
}
#[tokio::test]
async fn test_eval_matrix_selector_basic() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: None,
at: None,
};
let result = engine
.eval_matrix_selector(&selector, Duration::from_secs(300), None)
.await;
assert!(result.is_ok());
let values = result.unwrap();
assert_eq!(values.len(), 0); // Mock provider returns empty data
}
#[tokio::test]
async fn test_eval_vector_selector_without_a_metric_name_is_an_error() {
let trace_id = "test_trace";
@@ -1013,44 +861,6 @@ mod tests {
);
}
#[tokio::test]
async fn test_eval_matrix_selector_with_offset() {
let trace_id = "test_trace";
let org_id = "test_org";
let mut engine = Engine::new(
trace_id,
Arc::new(PromqlContext::new(
create_test_query_ctx(trace_id, org_id, 30),
SimpleMockProvider,
vec![],
)),
create_test_eval_ctx(),
);
let matchers = Matchers {
matchers: vec![promql_parser::label::Matcher {
name: "env".to_string(),
op: MatchOp::Equal,
value: "prod".to_string(),
}],
or_matchers: vec![],
};
let selector = VectorSelector {
name: Some("test_metric".to_string()),
matchers,
offset: Some(Offset::Pos(Duration::from_secs(120))),
at: None,
};
let result = engine
.eval_matrix_selector(&selector, Duration::from_secs(300), None)
.await;
assert!(result.is_ok());
let values = result.unwrap();
assert_eq!(values.len(), 0); // Mock provider returns empty data
}
/// Serves one series that carries only an exemplar, as the exemplar loader produces.
struct ExemplarProvider;
-18
View File
@@ -74,24 +74,6 @@ mod tests {
avg_over_time(data, &eval_ctx)
}
#[test]
fn test_avg_over_time_value_none_input() {
let result = avg_over_time_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_avg_over_time_invalid_input_returns_err() {
let result = avg_over_time_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_avg_over_time_exec_empty_samples_returns_none() {
let func = AvgOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_avg_over_time_function() {
// Create a range value with sample data
-12
View File
@@ -57,18 +57,6 @@ mod tests {
changes(data, &eval_ctx)
}
#[test]
fn test_changes_value_none_input() {
let result = changes_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_changes_invalid_input_returns_err() {
let result = changes_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_changes_no_changes() {
let func = ChangesFunc;
@@ -52,24 +52,6 @@ mod tests {
count_over_time(data, &eval_ctx)
}
#[test]
fn test_count_over_time_value_none_input() {
let result = count_over_time_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_count_over_time_invalid_input_returns_err() {
let result = count_over_time_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_count_over_time_exec_empty_samples_returns_none() {
let func = CountOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_count_over_time_function() {
// Create a range value with sample data
-12
View File
@@ -54,18 +54,6 @@ mod tests {
deriv(data, &eval_ctx)
}
#[test]
fn test_deriv_value_none_input() {
let result = deriv_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_deriv_invalid_input_returns_err() {
let result = deriv_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_deriv_exec_fewer_than_two_samples_returns_none() {
let func = DerivFunc;
-29
View File
@@ -44,17 +44,6 @@ impl RangeFunc for ExtrapolationKind {
mod rate_tests {
use super::*;
#[test]
fn test_rate_name() {
assert_eq!(ExtrapolationKind::Rate.name(), "rate");
}
#[test]
fn test_rate_empty_samples() {
let func = ExtrapolationKind::Rate;
assert!(func.exec(&[], 0, &Duration::from_secs(60)).is_none());
}
#[test]
fn test_rate_single_sample() {
let func = ExtrapolationKind::Rate;
@@ -107,18 +96,6 @@ mod increase_tests {
increase(data, &eval_ctx)
}
#[test]
fn test_increase_value_none_input() {
let result = increase_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_increase_invalid_input_returns_err() {
let result = increase_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_increase_function() {
// Create a range value with increasing counter values
@@ -218,12 +195,6 @@ mod delta_tests {
_ => panic!("Expected Matrix result"),
}
}
#[test]
fn test_delta_function_name() {
let func = ExtrapolationKind::Delta;
assert_eq!(func.name(), "delta");
}
}
#[cfg(test)]
-12
View File
@@ -118,18 +118,6 @@ mod tests {
)
}
#[test]
fn test_holt_winters_value_none_input() {
let result = holt_winters_test_helper(Value::None, 0.5, 0.3).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_holt_winters_invalid_input_returns_err() {
let result = holt_winters_test_helper(Value::Float(1.0), 0.5, 0.3);
assert!(result.is_err());
}
#[test]
fn test_holt_winters_calculation_fewer_than_two_samples() {
assert!(holt_winters_calculation(&[], 0.5, 0.3).is_none());
-12
View File
@@ -52,18 +52,6 @@ mod tests {
idelta(data, &eval_ctx)
}
#[test]
fn test_idelta_value_none_input() {
let result = idelta_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_idelta_invalid_input_returns_err() {
let result = idelta_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_idelta_exec_fewer_than_two_samples_returns_none() {
let func = IdeltaFunc;
-12
View File
@@ -62,18 +62,6 @@ mod tests {
irate(data, &eval_ctx)
}
#[test]
fn test_irate_value_none_input() {
let result = irate_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_irate_invalid_input_returns_err() {
let result = irate_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_irate_function() {
// Create a range value with increasing counter values
-54
View File
@@ -180,58 +180,4 @@ mod tests {
let result = label_join(Value::Float(1.0), "dst", "-", vec![]);
assert!(result.is_err());
}
#[test]
fn test_label_join_function() {
use config::meta::promql::value::{RangeValue, Sample};
let eval_ts = 1000;
// Create range values with labels
let labels1 = vec![
Arc::new(Label::new("instance", "server1")),
Arc::new(Label::new("job", "web")),
];
let range_value1 = RangeValue {
labels: labels1,
samples: vec![Sample::new(eval_ts, 42.0)],
exemplars: None,
time_window: None,
};
let labels2 = vec![
Arc::new(Label::new("instance", "server2")),
Arc::new(Label::new("job", "web")),
];
let range_value2 = RangeValue {
labels: labels2,
samples: vec![Sample::new(eval_ts, 43.0)],
exemplars: None,
time_window: None,
};
let matrix = Value::Matrix(vec![range_value1, range_value2]);
let source_labels = vec!["instance".to_string(), "job".to_string()];
let result = label_join(matrix, "combined", "-", source_labels).unwrap();
// Should return a matrix with joined labels
match result {
Value::Matrix(m) => {
assert_eq!(m.len(), 2);
// Check that the combined label was added
let combined_label1 = m[0].labels.iter().find(|l| l.name == "combined");
let combined_label2 = m[1].labels.iter().find(|l| l.name == "combined");
assert!(combined_label1.is_some());
assert!(combined_label2.is_some());
assert_eq!(combined_label1.unwrap().value, "server1-web");
assert_eq!(combined_label2.unwrap().value, "server2-web");
// Verify samples are preserved
assert_eq!(m[0].samples[0].value, 42.0);
assert_eq!(m[1].samples[0].value, 43.0);
}
_ => panic!("Expected Matrix result"),
}
}
}
-112
View File
@@ -253,116 +253,4 @@ mod tests {
let result = label_replace(Value::Float(1.0), "dst", "$1", "src", ".*");
assert!(result.is_err());
}
#[test]
fn test_label_replace_function() {
use config::meta::promql::value::{RangeValue, Sample};
let eval_ts = 1000;
// Create range values with labels
let labels = vec![
Arc::new(Label::new("instance", "server-123.example.com")),
Arc::new(Label::new("job", "web")),
];
let range_value = RangeValue {
labels,
samples: vec![Sample::new(eval_ts, 42.0)],
exemplars: None,
time_window: None,
};
let matrix = Value::Matrix(vec![range_value]);
let result = label_replace(
matrix,
"hostname",
"$1",
"instance",
r"server-(\d+)\.example\.com",
)
.unwrap();
// Should return a matrix with replaced label
match result {
Value::Matrix(m) => {
assert_eq!(m.len(), 1);
// Check that the hostname label was added
let hostname_label = m[0].labels.iter().find(|l| l.name == "hostname");
assert!(hostname_label.is_some());
assert_eq!(hostname_label.unwrap().value, "123");
// Verify samples are preserved
assert_eq!(m[0].samples[0].value, 42.0);
}
_ => panic!("Expected Matrix result"),
}
}
#[test]
fn test_label_replace_empty_replacement_removes_dest_label() {
use config::meta::promql::value::{RangeValue, Sample};
let labels = vec![
Arc::new(Label::new("dst", "old_value")),
Arc::new(Label::new("src", "source_val")),
];
let range_value = RangeValue {
labels,
samples: vec![Sample::new(1000, 1.0)],
exemplars: None,
time_window: None,
};
let matrix = Value::Matrix(vec![range_value]);
let result = label_replace(matrix, "dst", "", "src", ".*").unwrap();
match result {
Value::Matrix(m) => {
assert_eq!(m.len(), 1);
// Empty replacement removes dst label
assert!(m[0].labels.iter().all(|l| l.name != "dst"));
}
_ => panic!("Expected Matrix result"),
}
}
#[test]
fn test_label_replace_no_regex_match_leaves_labels_unchanged() {
use config::meta::promql::value::{RangeValue, Sample};
let labels = vec![Arc::new(Label::new("instance", "prod-server"))];
let range_value = RangeValue {
labels,
samples: vec![Sample::new(1000, 1.0)],
exemplars: None,
time_window: None,
};
let matrix = Value::Matrix(vec![range_value]);
// Regex won't match "prod-server"
let result = label_replace(matrix, "hostname", "$1", "instance", r"(\d+)").unwrap();
match result {
Value::Matrix(m) => {
assert_eq!(m.len(), 1);
// hostname label NOT added since regex didn't match
assert!(m[0].labels.iter().all(|l| l.name != "hostname"));
// instance label preserved
assert!(m[0].labels.iter().any(|l| l.name == "instance"));
}
_ => panic!("Expected Matrix result"),
}
}
#[test]
fn test_label_replace_invalid_dest_label_returns_err() {
let matrix = Value::Matrix(vec![]);
let result = label_replace(matrix, "123invalid", "$1", "src", ".*");
assert!(result.is_err());
}
#[test]
fn test_label_replace_invalid_regex_returns_err() {
let matrix = Value::Matrix(vec![]);
let result = label_replace(matrix, "dst", "$1", "src", "[invalid");
assert!(result.is_err());
}
}
@@ -75,24 +75,6 @@ mod tests {
last_over_time(data, &eval_ctx)
}
#[test]
fn test_last_over_time_value_none_input() {
let result = last_over_time_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_last_over_time_invalid_input_returns_err() {
let result = last_over_time_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_last_over_time_exec_empty_samples_returns_none() {
let func = LastOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_last_over_time_function() {
// Create a range value with sample data
-155
View File
@@ -223,161 +223,6 @@ mod tests {
assert_eq!(apply(sgn, -5.0), -1.0);
}
#[test]
fn test_abs() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![-5.0, 3.0]);
let result = abs(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 2);
assert_eq!(result_matrix[0].samples[0].value, 5.0);
assert_eq!(result_matrix[1].samples[0].value, 3.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_ceil() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![3.2, -3.2]);
let result = ceil(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 2);
assert_eq!(result_matrix[0].samples[0].value, 4.0);
assert_eq!(result_matrix[1].samples[0].value, -3.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_floor() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![3.2, -3.2]);
let result = floor(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 2);
assert_eq!(result_matrix[0].samples[0].value, 3.0);
assert_eq!(result_matrix[1].samples[0].value, -4.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_exp() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![0.0, 1.0]);
let result = exp(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 2);
assert_eq!(result_matrix[0].samples[0].value, 1.0);
assert_eq!(result_matrix[1].samples[0].value, std::f64::consts::E);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_ln() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![1.0, std::f64::consts::E]);
let result = ln(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 2);
assert_eq!(result_matrix[0].samples[0].value, 0.0);
assert_eq!(result_matrix[1].samples[0].value, 1.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_log2() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![1.0, 2.0, 4.0]);
let result = log2(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 3);
assert_eq!(result_matrix[0].samples[0].value, 0.0);
assert_eq!(result_matrix[1].samples[0].value, 1.0);
assert_eq!(result_matrix[2].samples[0].value, 2.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_log10() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![1.0, 10.0, 100.0]);
let result = log10(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 3);
assert_eq!(result_matrix[0].samples[0].value, 0.0);
assert_eq!(result_matrix[1].samples[0].value, 1.0);
assert_eq!(result_matrix[2].samples[0].value, 2.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_sqrt() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![0.0, 1.0, 4.0]);
let result = sqrt(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 3);
assert_eq!(result_matrix[0].samples[0].value, 0.0);
assert_eq!(result_matrix[1].samples[0].value, 1.0);
assert_eq!(result_matrix[2].samples[0].value, 2.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_round() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![3.2, 3.5, -3.2]);
let result = round(value, &ScalarParam::Const(1.0)).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 3);
assert_eq!(result_matrix[0].samples[0].value, 3.0);
assert_eq!(result_matrix[1].samples[0].value, 4.0);
assert_eq!(result_matrix[2].samples[0].value, -3.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_sgn() {
let eval_ts = 1000;
let value = create_matrix(eval_ts, vec![5.0, -5.0, 0.0]);
let result = sgn(value).unwrap();
if let Value::Matrix(result_matrix) = result {
assert_eq!(result_matrix.len(), 3);
assert_eq!(result_matrix[0].samples[0].value, 1.0);
assert_eq!(result_matrix[1].samples[0].value, -1.0);
assert_eq!(result_matrix[2].samples[0].value, 0.0);
} else {
panic!("Expected Matrix result");
}
}
#[test]
fn test_none_value() {
let value = Value::None;
-18
View File
@@ -49,24 +49,6 @@ mod tests {
max_over_time(data, &eval_ctx)
}
#[test]
fn test_max_over_time_value_none_input() {
let result = max_over_time_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_max_over_time_invalid_input_returns_err() {
let result = max_over_time_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_max_over_time_exec_empty_samples_returns_none() {
let func = MaxOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_max_over_time_function() {
// Create a range value with sample data
-18
View File
@@ -55,24 +55,6 @@ mod tests {
min_over_time(data, &eval_ctx)
}
#[test]
fn test_min_over_time_value_none_input() {
let result = min_over_time_test_helper(Value::None).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_min_over_time_invalid_input_returns_err() {
let result = min_over_time_test_helper(Value::Float(1.0));
assert!(result.is_err());
}
#[test]
fn test_min_over_time_exec_empty_samples_returns_none() {
let func = MinOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_min_over_time_function() {
// Create a range value with sample data
-13
View File
@@ -762,19 +762,6 @@ mod tests {
}
}
#[test]
fn test_func_enum_parsing_known_functions() {
assert_eq!("abs".parse::<Func>().unwrap(), Func::Abs);
assert_eq!("rate".parse::<Func>().unwrap(), Func::Rate);
assert_eq!("avg_over_time".parse::<Func>().unwrap(), Func::AvgOverTime);
assert_eq!(
"histogram_quantile".parse::<Func>().unwrap(),
Func::HistogramQuantile
);
assert_eq!("label_join".parse::<Func>().unwrap(), Func::LabelJoin);
assert_eq!("label_replace".parse::<Func>().unwrap(), Func::LabelReplace);
}
#[test]
fn test_func_enum_unknown_returns_err() {
assert!("unknown_function".parse::<Func>().is_err());
@@ -71,18 +71,6 @@ mod tests {
predict_linear(data, ScalarParam::Const(duration), &eval_ctx, None)
}
#[test]
fn test_predict_linear_value_none_input() {
let result = predict_linear_test_helper(Value::None, 10.0).unwrap();
assert!(matches!(result, Value::None));
}
#[test]
fn test_predict_linear_invalid_input_returns_err() {
let result = predict_linear_test_helper(Value::Float(1.0), 10.0);
assert!(result.is_err());
}
#[test]
fn test_predict_linear_needs_two_samples_to_predict() {
let one_sample = RangeValue {
@@ -59,11 +59,6 @@ mod tests {
assert!(present_over_time(Value::Float(1.0)).is_err());
}
#[test]
fn test_present_over_time_exec_empty_samples_returns_none() {
assert!(PresentOverTimeFunc.exec(&[], 0, &Duration::ZERO).is_none());
}
#[test]
fn test_present_over_time_is_one_regardless_of_sample_values() {
let range_value = RangeValue {
@@ -71,20 +71,6 @@ mod tests {
.collect()
}
#[test]
fn test_quantile_over_time_name() {
assert_eq!(
QuantileOverTimeFunc::new(ScalarParam::Const(0.5)).name(),
"quantile_over_time"
);
}
#[test]
fn test_quantile_over_time_empty() {
let func = QuantileOverTimeFunc::new(ScalarParam::Const(0.5));
assert!(func.exec(&[], 0, &Duration::from_secs(1)).is_none());
}
#[test]
fn test_quantile_over_time_median() {
let func = QuantileOverTimeFunc::new(ScalarParam::Const(0.5));
@@ -47,17 +47,6 @@ mod tests {
.collect()
}
#[test]
fn test_stddev_over_time_name() {
assert_eq!(StddevOverTimeFunc.name(), "stddev_over_time");
}
#[test]
fn test_stddev_over_time_empty() {
let func = StddevOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::from_secs(1)).is_none());
}
#[test]
fn test_stddev_over_time_constant() {
let func = StddevOverTimeFunc;
@@ -47,17 +47,6 @@ mod tests {
.collect()
}
#[test]
fn test_stdvar_over_time_name() {
assert_eq!(StdvarOverTimeFunc.name(), "stdvar_over_time");
}
#[test]
fn test_stdvar_over_time_empty() {
let func = StdvarOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::from_secs(1)).is_none());
}
#[test]
fn test_stdvar_over_time_constant() {
let func = StdvarOverTimeFunc;
-11
View File
@@ -53,17 +53,6 @@ mod tests {
.collect()
}
#[test]
fn test_sum_over_time_name() {
assert_eq!(SumOverTimeFunc.name(), "sum_over_time");
}
#[test]
fn test_sum_over_time_empty() {
let func = SumOverTimeFunc;
assert!(func.exec(&[], 0, &Duration::from_secs(1)).is_none());
}
#[test]
fn test_sum_over_time_single() {
let func = SumOverTimeFunc;
-95
View File
@@ -2352,101 +2352,6 @@ mod tests {
assert_eq!(fixture.calls.load(Ordering::SeqCst), 0);
}
#[tokio::test]
async fn legacy_new_mixed_and_disabled_sources_preserve_same_series_fragments() {
use datafusion::arrow::{array::UInt32Array, ipc::writer::FileWriter};
let rows = [
(1, 10, 1.0, Some("x")),
(1, 20, -0.0, Some("x")),
(1, 30, 3.0, Some("x")),
(1, 40, 4.0, Some("x")),
];
let legacy_schema = Arc::new(Schema::new(vec![
Field::new("__oo_midx_row_count", DataType::UInt32, false),
Field::new("group", DataType::Utf8, true),
]));
let legacy_batch = RecordBatch::try_new(
Arc::clone(&legacy_schema),
vec![
Arc::new(UInt32Array::from(vec![2])),
Arc::new(StringArray::from(vec!["x"])),
],
)
.unwrap();
let mut legacy = Vec::new();
let mut writer = FileWriter::try_new(&mut legacy, &legacy_schema).unwrap();
writer.write(&legacy_batch).unwrap();
writer.finish().unwrap();
for legacy_count in [0, 1, 2] {
for enabled in [false, true] {
let mut files = vec![file(&rows[..2]), file(&rows[2..])];
for source in files.iter_mut().take(legacy_count) {
source.1 = legacy.clone();
}
let fixture = Fixture::new(&files, false).await;
let source = if enabled {
ScanSource::Blocks(Arc::new(fixture.scan(files.iter().map(|v| v.0.clone()))))
} else {
ScanSource::HashSorted
};
let ctx =
SessionContext::new_with_config(SessionConfig::new().with_target_partitions(2));
let table = MemTable::try_new(schema(), vec![vec![batch(&rows)]])
.unwrap()
.with_sort_order(vec![vec![
col("__hash__").sort(true, false),
col("_timestamp").sort(true, false),
]]);
ctx.register_table("m", Arc::new(table)).unwrap();
let matchers = Matchers::empty();
let selector = StreamingSelector {
table_name: "m",
matchers: &matchers,
offset: 0,
};
let result = execute_partitioned(
&ctx,
&source,
&selector,
LabelColumns::grouped(vec!["group".into()]),
20,
&EvalContext::new(10, 40, 10, "compatibility".into()),
)
.await;
if enabled && legacy_count > 0 {
assert!(result.is_err());
assert_eq!(fixture.calls.load(Ordering::SeqCst), 0);
continue;
}
let sources = result.unwrap();
let mut actual = Vec::new();
for source in sources {
let mut source = source.await.unwrap();
assert_eq!(
matches!(&source, SeriesSource::Block(_)),
enabled && legacy_count == 0
);
while source.advance().await.unwrap().is_some() {
let mut samples = Vec::new();
source.consume(&mut samples).await.unwrap();
actual.extend(samples.iter().map(|s| (s.timestamp, s.value.to_bits())));
}
}
actual.sort_unstable();
assert_eq!(
actual,
rows.iter()
.map(|r| (r.1, r.2.to_bits()))
.collect::<Vec<_>>()
);
assert_eq!(
fixture.calls.load(Ordering::SeqCst) > 0,
enabled && legacy_count == 0
);
}
}
}
#[tokio::test]
async fn schema_evolution_distinguishes_absent_null_and_empty_labels() {
let original = batch(&[(1, 10, 1.0, None), (1, 20, 2.0, None)]);