From e8f4858b5e3ee79917c508f3b6b8c7845d9b76f8 Mon Sep 17 00:00:00 2001 From: Charles Schleich Date: Tue, 9 Jul 2024 17:39:46 +0200 Subject: [PATCH 1/2] Added integration Test Step to CI, clippy code cleanup --- .github/workflows/rust.yml | 19 ++++++++++- examples/measurement.rs | 14 ++++---- src/api/authorizations.rs | 2 +- src/api/label.rs | 4 +-- src/api/query.rs | 59 ++++++++++++++-------------------- src/lib.rs | 3 +- tests/common/server_fixture.rs | 4 ++- 7 files changed, 57 insertions(+), 48 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c7c9cac..67b0285 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -22,6 +22,8 @@ jobs: build: runs-on: ubuntu-latest + id: build + needs: typos steps: - name: Clone this repository uses: actions/checkout@v4 @@ -50,5 +52,20 @@ jobs: - name: Build run: cargo build --verbose + test: + name: Run Tests + runs-on: ubuntu-latest + id: test + needs: build + steps: + - name: Clone this repository + uses: actions/checkout@v4 + + - name: Rust Toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Update Stable Rust toolchain + run: rustup update stable + - name: Run tests - run: cargo test --verbose + run: TEST_INTEGRATION=true cargo test --verbose \ No newline at end of file diff --git a/examples/measurement.rs b/examples/measurement.rs index 227a1b4..74cb801 100644 --- a/examples/measurement.rs +++ b/examples/measurement.rs @@ -17,7 +17,7 @@ async fn main() -> Result<(), Box> { for m in measurements.iter() { let field_keys = client - .list_measurement_field_keys(bucket, &m, Some("-365d"), Some("now()")) + .list_measurement_field_keys(bucket, m, Some("-365d"), Some("now()")) .await .unwrap(); println!("field keys: {:?}", field_keys); @@ -25,21 +25,21 @@ async fn main() -> Result<(), Box> { for m in measurements.iter() { let tag_values = client - .list_measurement_tag_values(bucket, &m, "host", Some("-365d"), None) + .list_measurement_tag_values(bucket, m, "host", Some("-365d"), None) .await; println!( - "tag values for measurement {} and tag {}: {:?}", - &m, "host", tag_values + "tag values for measurement {} and tag host: {:?}", + &m, tag_values ); } for m in measurements.iter() { let tag_values = client - .list_measurement_tag_keys(bucket, &m, Some("-365d"), None) + .list_measurement_tag_keys(bucket, m, Some("-365d"), None) .await; println!( - "tag values for measurement {} and tag {}: {:?}", - &m, "host", tag_values + "tag values for measurement {} and tag host: {:?}", + &m, tag_values ); } diff --git a/src/api/authorizations.rs b/src/api/authorizations.rs index d698aea..0b81e75 100644 --- a/src/api/authorizations.rs +++ b/src/api/authorizations.rs @@ -30,7 +30,7 @@ impl Client { return res; } - Ok(response.json().await.context(ReqwestProcessing)?) + response.json().await.context(ReqwestProcessing) } /// Create a new authorization in the organization. diff --git a/src/api/label.rs b/src/api/label.rs index 502bb52..01614a5 100644 --- a/src/api/label.rs +++ b/src/api/label.rs @@ -9,12 +9,12 @@ use std::collections::HashMap; impl Client { /// List all Labels pub async fn labels(&self) -> Result { - Ok(self.get_labels(None).await?) + self.get_labels(None).await } /// List all Labels by organization ID pub async fn labels_by_org(&self, org_id: &str) -> Result { - Ok(self.get_labels(Some(org_id)).await?) + self.get_labels(Some(org_id)).await } async fn get_labels(&self, org_id: Option<&str>) -> Result { diff --git a/src/api/query.rs b/src/api/query.rs index 508c0f7..d518614 100644 --- a/src/api/query.rs +++ b/src/api/query.rs @@ -29,23 +29,18 @@ pub struct QueryTableIter { } impl<'a> QueryTableIter { - fn new(text: String) -> QueryTableIter { - return QueryTableIter { text }; + fn new(text: String) -> Self { + Self { text } } /// Get the iterator - pub fn result( - self: &'a QueryTableIter, - ) -> impl FallibleIterator + 'a { + pub fn result(&'a self) -> impl FallibleIterator + 'a { QueryTableResult::new(&self.text) } /// Is the response empty? - pub fn is_empty(self: &QueryTableIter) -> bool { - match QueryTableResult::new(&self.text).next() { - Ok(None) => true, - _ => false, - } + pub fn is_empty(&self) -> bool { + matches!(QueryTableResult::new(&self.text).next(), Ok(None)) } } @@ -402,7 +397,8 @@ impl Client { match response.status() { StatusCode::OK => { - let text = response.text().await.unwrap(); + let text: String = response.text().await.unwrap(); + let mut reader = csv::ReaderBuilder::new() .has_headers(true) .comment(Some(b'#')) @@ -410,10 +406,8 @@ impl Client { Ok(reader .records() - .into_iter() - .flatten() - .map(|r| r.get(3).map(|s| s.to_owned())) .flatten() + .flat_map(|r: StringRecord| r.get(3).map(|s| s.to_owned())) .collect()) } status => { @@ -439,17 +433,17 @@ enum DataType { impl FromStr for DataType { type Err = RequestError; - fn from_str(input: &str) -> Result { + fn from_str(input: &str) -> Result { match input { - "string" => Ok(DataType::String), - "double" => Ok(DataType::Double), - "boolean" => Ok(DataType::Bool), - "long" => Ok(DataType::Long), - "unsignedLong" => Ok(DataType::UnsignedLong), - "duration" => Ok(DataType::Duration), - "base64Binary" => Ok(DataType::Base64Binary), - "dateTime:RFC3339" => Ok(DataType::TimeRFC), - "dateTime:RFC3339Nano" => Ok(DataType::TimeRFC), + "string" => Ok(Self::String), + "double" => Ok(Self::Double), + "boolean" => Ok(Self::Bool), + "long" => Ok(Self::Long), + "unsignedLong" => Ok(Self::UnsignedLong), + "duration" => Ok(Self::Duration), + "base64Binary" => Ok(Self::Base64Binary), + "dateTime:RFC3339" => Ok(Self::TimeRFC), + "dateTime:RFC3339Nano" => Ok(Self::TimeRFC), _ => Err(RequestError::Deserializing { text: format!("unknown datatype: {}", input), }), @@ -528,7 +522,7 @@ impl<'a> FallibleIterator for QueryTableResult<'a> { continue; } if let Some(s) = row.get(0) { - if s.len() > 0 && s.chars().nth(0).unwrap() == '#' { + if !s.is_empty() && s.chars().nth(0).unwrap() == '#' { // Finding new table, prepare for annotation parsing if parsing_state == ParsingState::Normal { self.table = Some(FluxTableMetadata { @@ -587,13 +581,13 @@ impl<'a> FallibleIterator for QueryTableResult<'a> { continue; } ParsingState::Error => { - let msg = if row.len() > 1 && row.get(1).unwrap().len() > 0 { + let msg = if row.len() > 1 && !row.get(1).unwrap().is_empty() { row.get(1).unwrap() } else { "unknown query error" }; let mut reference = String::from(""); - if row.len() > 2 && row.get(2).unwrap().len() > 0 { + if row.len() > 2 && !row.get(2).unwrap().is_empty() { let s = row.get(2).unwrap(); reference = format!(",{}", s); } @@ -610,7 +604,7 @@ impl<'a> FallibleIterator for QueryTableResult<'a> { if v.is_empty() { v = &column.default_value[..]; } - let value = parse_value(v, column.data_type, &column.name.as_str())?; + let value = parse_value(v, column.data_type, column.name.as_str())?; values.entry(column.name.clone()).or_insert(value); } record = FluxRecord { @@ -656,7 +650,7 @@ struct QueryResult { } impl QueryResult { - fn new<'a>(qtr: QueryTableResult<'a>) -> Result { + fn new(qtr: QueryTableResult<'_>) -> Result { let ignored_keys = vec!["_field", "_value", "table"]; let ignored_keys: HashSet<&str> = ignored_keys.into_iter().collect(); @@ -828,18 +822,13 @@ mod tests { async fn query_opt() { let token = "some-token"; let org = "some-org"; - let query: Option = None; let mock_server = mock("POST", "/api/v2/query") .match_header("Authorization", format!("Token {}", token).as_str()) .match_header("Accepting-Encoding", "identity") .match_header("Content-Type", "application/json") .match_query(Matcher::UrlEncoded("org".into(), org.into())) - .match_body( - serde_json::to_string(&query.unwrap_or_default()) - .unwrap() - .as_str(), - ) + .match_body(serde_json::to_string(&Query::default()).unwrap().as_str()) .create(); let client = Client::new(mockito::server_url(), org, token); diff --git a/src/lib.rs b/src/lib.rs index 507eecc..996007e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,7 +250,8 @@ impl ClientBuilder { }; let url: String = url.into(); - let base = Url::parse(&url).expect(&format!("Invalid url was provided: {}", &url)); + let base = + Url::parse(&url).unwrap_or_else(|_| panic!("Invalid url was provided: {}", &url)); Self { base, diff --git a/tests/common/server_fixture.rs b/tests/common/server_fixture.rs index eee6eb4..aa3ec6f 100644 --- a/tests/common/server_fixture.rs +++ b/tests/common/server_fixture.rs @@ -1,3 +1,5 @@ +#![allow(clippy::await_holding_lock)] + use once_cell::sync::OnceCell; use std::{ fs::File, @@ -223,7 +225,7 @@ impl TestServer { .arg("--pull") .arg("always") .arg("--detach") - .arg(&ci_image) + .arg(ci_image) .arg("influxd") .output() .expect("starting of docker server process"); From 4a74241883231d5e731b01ddee18541476c8ba86 Mon Sep 17 00:00:00 2001 From: Charles Schleich Date: Tue, 9 Jul 2024 17:58:59 +0200 Subject: [PATCH 2/2] ci: remove id from yaml --- .github/workflows/rust.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 67b0285..4b7297b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -22,7 +22,6 @@ jobs: build: runs-on: ubuntu-latest - id: build needs: typos steps: - name: Clone this repository @@ -55,7 +54,6 @@ jobs: test: name: Run Tests runs-on: ubuntu-latest - id: test needs: build steps: - name: Clone this repository