prometheus-parser 0.4.2

a Rust library for parsing and validating Prometheus query expressions
Documentation
// (C) Copyright 2019 Hewlett Packard Enterprise Development LP

extern crate prometheus_parser;

use maplit::hashset;
use prometheus_parser::*;

#[test]
fn passthrough_trivial_empty() -> Result<()> {
  assert_eq!(
    parse_expr("foo")?.return_value().passthrough(&[]),
    hashset!{}
  );

  Ok(())
}

#[test]
fn passthrough_trivial_label() -> Result<()> {
  assert_eq!(
    parse_expr(r#"foo{bar="baz"}"#)?.return_value().passthrough(&[]),
    hashset!{"bar".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_trivial_user() -> Result<()> {
  assert_eq!(
    parse_expr("foo")?.return_value().passthrough(&["bar"]),
    hashset!{"bar".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_trivial_both() -> Result<()> {
  assert_eq!(
    parse_expr(r#"foo{bar="baz"}"#)?.return_value().passthrough(&["qux"]),
    hashset!{"bar".to_string(), "qux".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_grouping() -> Result<()> {
  // non-aggregation functions don't clear labels...
  assert_eq!(
    parse_expr(r#"zxcv(foo{bar="a"})"#)?.return_value().passthrough(&["baz"]),
    hashset!{"bar".to_string(), "baz".to_string()}
  );

  // ... but actual aggregations do
  assert_eq!(
    parse_expr(r#"sum(foo{bar="a"})"#)?.return_value().passthrough(&["baz"]),
    hashset!{}
  );

  assert_eq!(
    parse_expr(r#"sum(foo{bar="a"}) by (baz)"#)?
      .return_value()
      .passthrough(&["baz"]),
    hashset!{"baz".to_string()}
  );

  assert_eq!(
    parse_expr(r#"sum(foo{bar="a"}) without (qux)"#)?
      .return_value()
      .passthrough(&["baz"]),
    hashset!{"bar".to_string(), "baz".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_grouping_operator() -> Result<()> {
  assert_eq!(
    parse_expr(r#"foo + bar"#)?.return_value().passthrough(&["baz"]),
    hashset!{"baz".to_string()}
  );

  assert_eq!(
    parse_expr(r#"sum(foo) + bar"#)?.return_value().passthrough(&["baz"]),
    hashset!{}
  );

  assert_eq!(
    parse_expr(r#"sum(foo) by (baz) + bar"#)?
      .return_value()
      .passthrough(&["baz"]),
    hashset!{"baz".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_matching() -> Result<()> {
  // these are likely impossible prometheus expressions (or at least, could
  // never return any results), but are concise enough tests
  assert_eq!(
    parse_expr(r#"foo{bar="a"} / on(foo) group_left bar{baz="b"}"#)?
      .return_value()
      .passthrough(&["qux"]),
    hashset!{"bar".to_string(), "qux".to_string()}
  );

  assert_eq!(
    parse_expr(r#"foo{bar="a"} / on(foo) group_right bar{baz="b"}"#)?
      .return_value()
      .passthrough(&["qux"]),
    hashset!{"baz".to_string(), "qux".to_string()}
  );

  assert_eq!(
    parse_expr(r#"foo{bar="a"} / on(foo) group_left(baz) bar{baz="b"}"#)?
      .return_value()
      .passthrough(&["qux"]),
    hashset!{"bar".to_string(), "baz".to_string(), "qux".to_string()}
  );

  Ok(())
}

#[test]
fn passthrough_special() -> Result<()> {
  // no arg scalar function
  assert_eq!(
    parse_expr(r#"time()"#)?.return_value().passthrough(&["baz"]),
    hashset!{}
  );

  // weird 2nd arg functions
  // histogram_quantile also implies an `le` label
  assert_eq!(
    parse_expr(r#"histogram_quantile(0.9, rate(foo[5m]))"#)?
      .return_value()
      .passthrough(&["baz"]),
    hashset!{"baz".to_string(), "le".to_string()}
  );

  assert_eq!(
    parse_expr(r#"quantile_over_time(0.9, rate(foo[5m]))"#)?
      .return_value()
      .passthrough(&["baz"]),
    hashset!{"baz".to_string()}
  );

  // https://prometheus.io/docs/prometheus/latest/querying/functions/#label_join
  assert_eq!(
    parse_expr(r#"label_join(
      up{job="api-server",src1="a",src2="b",src3="c"},
      "foo", ",", "src1", "src2", "src3"
    )"#)?
      .return_value()
      .passthrough(&[]),
    hashset!{
      "job".to_string(), "src1".to_string(), "src2".to_string(),
      "src3".to_string(), "foo".to_string()
    }
  );

  // https://prometheus.io/docs/prometheus/latest/querying/functions/#label_replace
  assert_eq!(
    parse_expr(r#"label_replace(
      up{job="api-server",service="a:c"},
       "foo", "$1", "service", "(.*):.*"
    )"#)?
      .return_value()
      .passthrough(&[]),
    hashset!{
      "job".to_string(), "service".to_string(), "foo".to_string()
    }
  );

  Ok(())
}