From 53a6e23772c170e30f5c932321adcb7e789d6751 Mon Sep 17 00:00:00 2001 From: mimir-d Date: Sat, 12 Oct 2024 14:18:56 +0100 Subject: [PATCH] refactor scopes for step + measurement series - similar to previous commit, this removes the dependency on boxed futures; remove the cargo dependency as well, and the feature flag Signed-off-by: mimir-d --- Cargo.toml | 36 ------- examples/diagnosis.rs | 15 +-- examples/error_with_dut.rs | 1 - examples/extensions.rs | 5 +- examples/file.rs | 5 +- examples/measurement_series.rs | 16 ++- examples/measurement_single.rs | 5 +- examples/measurement_subcomponent.rs | 14 +-- examples/measurement_validators.rs | 16 +-- examples/simple_step_fail.rs | 12 +-- src/output/measure.rs | 64 ++++++++---- src/output/mod.rs | 2 +- src/output/run.rs | 2 + src/output/step.rs | 144 ++++++++++++++++++--------- tests/output/diagnosis.rs | 11 +- tests/output/error.rs | 99 ++++++++---------- tests/output/file.rs | 29 ++---- tests/output/fixture.rs | 45 ++++----- tests/output/log.rs | 73 ++++++-------- tests/output/measure.rs | 104 ++++++++----------- tests/output/run.rs | 1 - tests/output/step.rs | 91 +++++++++-------- 22 files changed, 372 insertions(+), 418 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1635da7..35f5686 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,11 @@ repository = "https://github.com/opencomputeproject/ocp-diag-core-rust" license = "MIT" edition = "2021" -[features] -boxed-scopes = [] - [dependencies] async-trait = "0.1.83" chrono = "0.4.38" chrono-tz = "0.10.0" delegate = "0.13.1" -futures = "0.3.30" maplit = "1.0.2" mime = "0.3.17" serde = { version = "1.0.210", features = ["derive"] } @@ -47,35 +43,3 @@ rand = "0.8.5" unexpected_cfgs = { level = "warn", check-cfg = [ 'cfg(coverage,coverage_nightly)', ] } - -[[example]] -name = "extensions" -required-features = ["boxed-scopes"] - -[[example]] -name = "measurement_series" -required-features = ["boxed-scopes"] - -[[example]] -name = "measurement_single" -required-features = ["boxed-scopes"] - -[[example]] -name = "measurement_subcomponent" -required-features = ["boxed-scopes"] - -[[example]] -name = "measurement_validators" -required-features = ["boxed-scopes"] - -[[example]] -name = "simple_step_fail" -required-features = ["boxed-scopes"] - -[[example]] -name = "diagnosis" -required-features = ["boxed-scopes"] - -[[example]] -name = "file" -required-features = ["boxed-scopes"] diff --git a/examples/diagnosis.rs b/examples/diagnosis.rs index f351df6..59c23a6 100644 --- a/examples/diagnosis.rs +++ b/examples/diagnosis.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use ocptv::output as tv; use ocptv::{ocptv_diagnosis_fail, ocptv_diagnosis_pass}; @@ -17,7 +16,7 @@ fn get_fan_speed() -> i32 { rng.gen_range(1500..1700) } -async fn run_diagnosis_step(step: &tv::StartedTestStep) -> Result { +async fn run_diagnosis_step(step: tv::ScopedTestStep) -> Result { let fan_speed = get_fan_speed(); if fan_speed >= 1600 { @@ -31,9 +30,7 @@ async fn run_diagnosis_step(step: &tv::StartedTestStep) -> Result Result { +async fn run_diagnosis_macros_step(step: tv::ScopedTestStep) -> Result { let fan_speed = get_fan_speed(); if fan_speed >= 1600 { @@ -53,12 +50,8 @@ async fn main() -> Result<()> { tv::TestRun::builder("simple measurement", "1.0") .build() .scope(dut, |r| async move { - r.add_step("step0") - .scope(|s| run_diagnosis_step(s).boxed()) - .await?; - r.add_step("step1") - .scope(|s| run_diagnosis_macros_step(s).boxed()) - .await?; + r.add_step("step0").scope(run_diagnosis_step).await?; + r.add_step("step1").scope(run_diagnosis_macros_step).await?; Ok(tv::TestRunOutcome { status: TestStatus::Complete, diff --git a/examples/error_with_dut.rs b/examples/error_with_dut.rs index c855d7d..9194802 100644 --- a/examples/error_with_dut.rs +++ b/examples/error_with_dut.rs @@ -20,7 +20,6 @@ async fn main() -> Result<()> { .build(), ); - #[cfg(feature = "boxed-scopes")] tv::TestRun::builder("run error with dut", "1.0") .build() .scope(dut, |r| async move { diff --git a/examples/extensions.rs b/examples/extensions.rs index d718069..f78886f 100644 --- a/examples/extensions.rs +++ b/examples/extensions.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde::Serialize; use ocptv::output as tv; @@ -25,7 +24,7 @@ struct ComplexExtension { subtypes: Vec, } -async fn step0(s: &tv::StartedTestStep) -> Result { +async fn step0(s: tv::ScopedTestStep) -> Result { s.add_extension("simple", "extension_identifier").await?; s.add_extension( @@ -49,7 +48,7 @@ async fn main() -> Result<()> { tv::TestRun::builder("extensions", "1.0") .build() .scope(dut, |r| async move { - r.add_step("step0").scope(|s| step0(s).boxed()).await?; + r.add_step("step0").scope(step0).await?; Ok(tv::TestRunOutcome { status: TestStatus::Complete, diff --git a/examples/file.rs b/examples/file.rs index 2bef304..4ee475e 100644 --- a/examples/file.rs +++ b/examples/file.rs @@ -7,12 +7,11 @@ use std::str::FromStr; use anyhow::Result; -use futures::FutureExt; use ocptv::output as tv; use tv::{TestResult, TestStatus}; -async fn run_file_step(step: &tv::StartedTestStep) -> Result { +async fn run_file_step(step: tv::ScopedTestStep) -> Result { let uri = tv::Uri::from_str("file:///root/mem_cfg_log").unwrap(); step.add_file("mem_cfg_log", uri).await?; @@ -28,7 +27,7 @@ async fn main() -> Result<()> { .build() .scope(dut, |r| async move { r.add_step("step0") - .scope(|s| run_file_step(s).boxed()) + .scope(run_file_step) .await?; Ok(tv::TestRunOutcome { diff --git a/examples/measurement_series.rs b/examples/measurement_series.rs index 70b5e33..7a325b9 100644 --- a/examples/measurement_series.rs +++ b/examples/measurement_series.rs @@ -7,12 +7,11 @@ use anyhow::Result; use chrono::Duration; -use futures::FutureExt; use ocptv::output::{self as tv}; use tv::{TestResult, TestStatus}; -async fn step0_measurements(step: &tv::StartedTestStep) -> Result { +async fn step0_measurements(step: tv::ScopedTestStep) -> Result { let fan_speed = step .add_measurement_series_detail( tv::MeasurementSeriesDetail::builder("fan_speed") @@ -30,8 +29,7 @@ async fn step0_measurements(step: &tv::StartedTestStep) -> Result Result { +async fn step1_measurements(step: tv::ScopedTestStep) -> Result { step.add_measurement_series_detail( tv::MeasurementSeriesDetail::builder("temp0") .unit("C") @@ -51,14 +49,13 @@ async fn step1_measurements(step: &tv::StartedTestStep) -> Result Result { +async fn step2_measurements(step: tv::ScopedTestStep) -> Result { let freq0 = step .add_measurement_series_detail( tv::MeasurementSeriesDetail::builder("freq0") @@ -99,16 +96,15 @@ async fn main() -> Result<()> { .build() .scope(dut, |r| async move { r.add_step("step0") - .scope(|s| step0_measurements(s).boxed()) + .scope(step0_measurements) .await?; - #[cfg(feature = "boxed-scopes")] r.add_step("step1") - .scope(|s| step1_measurements(s).boxed()) + .scope(step1_measurements) .await?; r.add_step("step2") - .scope(|s| step2_measurements(s).boxed()) + .scope(step2_measurements) .await?; Ok(tv::TestRunOutcome { diff --git a/examples/measurement_single.rs b/examples/measurement_single.rs index 5a64527..c39b984 100644 --- a/examples/measurement_single.rs +++ b/examples/measurement_single.rs @@ -5,12 +5,11 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use ocptv::output as tv; use tv::{TestResult, TestStatus}; -async fn run_measure_step(step: &tv::StartedTestStep) -> Result { +async fn run_measure_step(step: tv::ScopedTestStep) -> Result { step.add_measurement("temperature", 42.5.into()).await?; step.add_measurement_detail( tv::Measurement::builder("fan_speed", 1200.into()) @@ -31,7 +30,7 @@ async fn main() -> Result<()> { .build() .scope(dut, |r| async move { r.add_step("step0") - .scope(|s| run_measure_step(s).boxed()) + .scope(run_measure_step) .await?; Ok(tv::TestRunOutcome { diff --git a/examples/measurement_subcomponent.rs b/examples/measurement_subcomponent.rs index 61aeb7a..755547a 100644 --- a/examples/measurement_subcomponent.rs +++ b/examples/measurement_subcomponent.rs @@ -7,12 +7,11 @@ use anyhow::Result; -use futures::FutureExt; use ocptv::output as tv; use tv::{SubcomponentType, TestResult, TestStatus}; async fn run_measure_step( - step: &tv::StartedTestStep, + step: tv::ScopedTestStep, ram0: tv::DutHardwareInfo, ) -> Result { step.add_measurement_detail( @@ -40,13 +39,10 @@ async fn run_measure_step( ); chip1_temp - .scope(|s| { - async move { - s.add_measurement(79.into()).await?; + .scope(|s| async move { + s.add_measurement(79.into()).await?; - Ok(()) - } - .boxed() + Ok(()) }) .await?; @@ -90,7 +86,7 @@ async fn main() -> Result<()> { .build() .scope(dut, |r| async move { r.add_step("step0") - .scope(|s| run_measure_step(s, ram0).boxed()) + .scope(|s| run_measure_step(s, ram0)) .await?; Ok(tv::TestRunOutcome { diff --git a/examples/measurement_validators.rs b/examples/measurement_validators.rs index 20bac17..f8655cd 100644 --- a/examples/measurement_validators.rs +++ b/examples/measurement_validators.rs @@ -6,12 +6,11 @@ // #![allow(warnings)] use anyhow::Result; -use futures::FutureExt; use ocptv::output as tv; use tv::{TestResult, TestStatus, ValidatorType}; -async fn run_measure_step(step: &tv::StartedTestStep) -> Result { +async fn run_measure_step(step: tv::ScopedTestStep) -> Result { step.add_measurement_detail( tv::Measurement::builder("temp", 40.into()) .add_validator( @@ -31,13 +30,10 @@ async fn run_measure_step(step: &tv::StartedTestStep) -> Result Result<()> { tv::TestRun::builder("simple measurement", "1.0") .build() .scope(dut, |r| async move { - r.add_step("step0") - .scope(|s| run_measure_step(s).boxed()) - .await?; + r.add_step("step0").scope(run_measure_step).await?; Ok(tv::TestRunOutcome { status: TestStatus::Complete, diff --git a/examples/simple_step_fail.rs b/examples/simple_step_fail.rs index af6387e..eba2402 100644 --- a/examples/simple_step_fail.rs +++ b/examples/simple_step_fail.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use ocptv::ocptv_log_info; use ocptv::output as tv; @@ -21,17 +20,14 @@ async fn main() -> Result<()> { .build() .scope(dut, |r| async move { r.add_step("step0") - .scope(|s| { - async move { - ocptv_log_info!(s, "info log").await?; - Ok(TestStatus::Complete) - } - .boxed() + .scope(|s| async move { + ocptv_log_info!(s, "info log").await?; + Ok(TestStatus::Complete) }) .await?; r.add_step("step1") - .scope(|_s| async move { Ok(TestStatus::Error) }.boxed()) + .scope(|_s| async move { Ok(TestStatus::Error) }) .await?; Ok(tv::TestRunOutcome { diff --git a/src/output/measure.rs b/src/output/measure.rs index 11620de..f397a01 100644 --- a/src/output/measure.rs +++ b/src/output/measure.rs @@ -5,11 +5,11 @@ // https://opensource.org/licenses/MIT. use std::collections::BTreeMap; +use std::future::Future; use std::sync::atomic::{self, Ordering}; use std::sync::Arc; -#[cfg(feature = "boxed-scopes")] -use futures::future::BoxFuture; +use delegate::delegate; use crate::output as tv; use crate::output::trait_ext::{MapExt, VecExt}; @@ -117,14 +117,17 @@ impl MeasurementSeries { /// # Ok::<(), OcptvError>(()) /// # }); /// ``` - #[cfg(feature = "boxed-scopes")] - pub async fn scope(self, func: F) -> Result<(), tv::OcptvError> + pub async fn scope(self, func: F) -> Result<(), tv::OcptvError> where - F: FnOnce(&StartedMeasurementSeries) -> BoxFuture<'_, Result<(), tv::OcptvError>>, + R: Future> + Send + 'static, + F: FnOnce(ScopedMeasurementSeries) -> R + Send + 'static, { - let series = self.start().await?; - func(&series).await?; - series.end().await?; + let series = Arc::new(self.start().await?); + func(ScopedMeasurementSeries { + series: Arc::clone(&series), + }) + .await?; + series.end_impl().await?; Ok(()) } @@ -142,6 +145,22 @@ impl StartedMeasurementSeries { self.seqno.fetch_add(1, Ordering::AcqRel) } + // note: keep the self-consuming method for crate api, but use this one internally, + // since `StartedMeasurementSeries::end` only needs to take ownership for syntactic reasons + async fn end_impl(&self) -> Result<(), tv::OcptvError> { + let end = spec::MeasurementSeriesEnd { + series_id: self.parent.id.clone(), + total_count: self.seqno.load(Ordering::Acquire), + }; + + self.parent + .emitter + .emit(&spec::TestStepArtifactImpl::MeasurementSeriesEnd(end)) + .await?; + + Ok(()) + } + /// Ends the measurement series. /// /// ref: @@ -162,17 +181,7 @@ impl StartedMeasurementSeries { /// # }); /// ``` pub async fn end(self) -> Result<(), tv::OcptvError> { - let end = spec::MeasurementSeriesEnd { - series_id: self.parent.id.clone(), - total_count: self.seqno.load(Ordering::Acquire), - }; - - self.parent - .emitter - .emit(&spec::TestStepArtifactImpl::MeasurementSeriesEnd(end)) - .await?; - - Ok(()) + self.end_impl().await } /// Adds a measurement element to the measurement series. @@ -248,6 +257,23 @@ impl StartedMeasurementSeries { } } +/// TODO: docs +pub struct ScopedMeasurementSeries { + series: Arc, +} + +impl ScopedMeasurementSeries { + delegate! { + to self.series { + pub async fn add_measurement(&self, value: tv::Value) -> Result<(), tv::OcptvError>; + pub async fn add_measurement_detail( + &self, + element: MeasurementElementDetail, + ) -> Result<(), tv::OcptvError>; + } + } +} + /// TODO: docs #[derive(Default)] pub struct MeasurementElementDetail { diff --git a/src/output/mod.rs b/src/output/mod.rs index 101ad0b..39668e1 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -39,7 +39,7 @@ pub use measure::{ StartedMeasurementSeries, Validator, ValidatorBuilder, }; pub use run::{ScopedTestRun, StartedTestRun, TestRun, TestRunBuilder, TestRunOutcome}; -pub use step::{StartedTestStep, TestStep}; +pub use step::{ScopedTestStep, StartedTestStep, TestStep}; pub use writer::{BufferWriter, FileWriter, StdoutWriter, Writer}; // re-export these as a public types we present diff --git a/src/output/run.rs b/src/output/run.rs index 0245a20..4bd0f41 100644 --- a/src/output/run.rs +++ b/src/output/run.rs @@ -528,9 +528,11 @@ impl ScopedTestRun { to self.run { pub async fn add_log(&self, severity: spec::LogSeverity, msg: &str) -> Result<(), tv::OcptvError>; pub async fn add_log_detail(&self, log: log::Log) -> Result<(), tv::OcptvError>; + pub async fn add_error(&self, symptom: &str) -> Result<(), tv::OcptvError>; pub async fn add_error_msg(&self, symptom: &str, msg: &str) -> Result<(), tv::OcptvError>; pub async fn add_error_detail(&self, error: error::Error) -> Result<(), tv::OcptvError>; + pub fn add_step(&self, name: &str) -> TestStep; } } diff --git a/src/output/step.rs b/src/output/step.rs index ec27871..67c322a 100644 --- a/src/output/step.rs +++ b/src/output/step.rs @@ -4,12 +4,12 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +use std::future::Future; use std::io; use std::sync::atomic::{self, Ordering}; use std::sync::Arc; -#[cfg(feature = "boxed-scopes")] -use futures::future::BoxFuture; +use delegate::delegate; use crate::output as tv; use crate::spec::{self, TestStepArtifactImpl}; @@ -97,14 +97,17 @@ impl TestStep { /// # Ok::<(), OcptvError>(()) /// # }); /// ``` - #[cfg(feature = "boxed-scopes")] - pub async fn scope(self, func: F) -> Result<(), tv::OcptvError> + pub async fn scope(self, func: F) -> Result<(), tv::OcptvError> where - F: FnOnce(&StartedTestStep) -> BoxFuture<'_, Result>, + R: Future> + Send + 'static, + F: FnOnce(ScopedTestStep) -> R + Send + 'static, { - let step = self.start().await?; - let status = func(&step).await?; - step.end(status).await?; + let step = Arc::new(self.start().await?); + let status = func(ScopedTestStep { + step: Arc::clone(&step), + }) + .await?; + step.end_impl(status).await?; Ok(()) } @@ -117,6 +120,15 @@ pub struct StartedTestStep { } impl StartedTestStep { + // note: keep the self-consuming method for crate api, but use this one internally, + // since `StartedTestStep::end` only needs to take ownership for syntactic reasons + async fn end_impl(&self, status: tv::TestStatus) -> Result<(), tv::OcptvError> { + let end = TestStepArtifactImpl::TestStepEnd(spec::TestStepEnd { status }); + + self.step.emitter.emit(&end).await?; + Ok(()) + } + /// Ends the test step. /// /// ref: @@ -135,11 +147,8 @@ impl StartedTestStep { /// # Ok::<(), OcptvError>(()) /// # }); /// ``` - pub async fn end(self, status: spec::TestStatus) -> Result<(), tv::OcptvError> { - let end = TestStepArtifactImpl::TestStepEnd(spec::TestStepEnd { status }); - - self.step.emitter.emit(&end).await?; - Ok(()) + pub async fn end(self, status: tv::TestStatus) -> Result<(), tv::OcptvError> { + self.end_impl(status).await } /// Emits Log message. @@ -367,41 +376,6 @@ impl StartedTestStep { Ok(()) } - /// Emits an extension message; - /// - /// ref: - /// - /// # Examples - /// - /// ```rust - /// # tokio_test::block_on(async { - /// # use ocptv::output::*; - /// let dut = DutInfo::new("my_dut"); - /// let run = TestRun::new("diagnostic_name", "1.0").start(dut).await?; - /// let step = run.add_step("step_name").start().await?; - /// - /// #[derive(serde::Serialize)] - /// struct Ext { i: u32 } - /// - /// step.add_extension("ext_name", Ext { i: 42 }).await?; - /// - /// # Ok::<(), OcptvError>(()) - /// # }); - /// ``` - pub async fn add_extension( - &self, - name: &str, - any: S, - ) -> Result<(), tv::OcptvError> { - let ext = TestStepArtifactImpl::Extension(spec::Extension { - name: name.to_owned(), - content: serde_json::to_value(&any).map_err(|e| OcptvError::Format(Box::new(e)))?, - }); - - self.step.emitter.emit(&ext).await?; - Ok(()) - } - /// Emits a Measurement message. /// /// ref: @@ -684,6 +658,80 @@ impl StartedTestStep { Ok(()) } + + /// Emits an extension message; + /// + /// ref: + /// + /// # Examples + /// + /// ```rust + /// # tokio_test::block_on(async { + /// # use ocptv::output::*; + /// let dut = DutInfo::new("my_dut"); + /// let run = TestRun::new("diagnostic_name", "1.0").start(dut).await?; + /// let step = run.add_step("step_name").start().await?; + /// + /// #[derive(serde::Serialize)] + /// struct Ext { i: u32 } + /// + /// step.add_extension("ext_name", Ext { i: 42 }).await?; + /// + /// # Ok::<(), OcptvError>(()) + /// # }); + /// ``` + pub async fn add_extension( + &self, + name: &str, + any: S, + ) -> Result<(), tv::OcptvError> { + let ext = TestStepArtifactImpl::Extension(spec::Extension { + name: name.to_owned(), + content: serde_json::to_value(&any).map_err(|e| OcptvError::Format(Box::new(e)))?, + }); + + self.step.emitter.emit(&ext).await?; + Ok(()) + } +} + +/// TODO: docs +pub struct ScopedTestStep { + step: Arc, +} + +impl ScopedTestStep { + delegate! { + to self.step { + pub async fn add_log(&self, severity: spec::LogSeverity, msg: &str) -> Result<(), tv::OcptvError>; + pub async fn add_log_detail(&self, log: log::Log) -> Result<(), tv::OcptvError>; + + pub async fn add_error(&self, symptom: &str) -> Result<(), tv::OcptvError>; + pub async fn add_error_msg(&self, symptom: &str, msg: &str) -> Result<(), tv::OcptvError>; + pub async fn add_error_detail(&self, error: error::Error) -> Result<(), tv::OcptvError>; + + pub async fn add_measurement(&self, name: &str, value: tv::Value) -> Result<(), tv::OcptvError>; + pub async fn add_measurement_detail(&self, detail: measure::Measurement) -> Result<(), tv::OcptvError>; + + pub fn add_measurement_series(&self, name: &str) -> tv::MeasurementSeries; + pub fn add_measurement_series_detail( + &self, + detail: measure::MeasurementSeriesDetail, + ) -> tv::MeasurementSeries; + + pub async fn add_diagnosis( + &self, + verdict: &str, + diagnosis_type: spec::DiagnosisType, + ) -> Result<(), tv::OcptvError>; + pub async fn add_diagnosis_detail(&self, diagnosis: diagnosis::Diagnosis) -> Result<(), tv::OcptvError>; + + pub async fn add_file(&self, name: &str, uri: tv::Uri) -> Result<(), tv::OcptvError>; + pub async fn add_file_detail(&self, file: file::File) -> Result<(), tv::OcptvError>; + + pub async fn add_extension(&self, name: &str, any: S) -> Result<(), tv::OcptvError>; + } + } } pub struct StepEmitter { diff --git a/tests/output/diagnosis.rs b/tests/output/diagnosis.rs index b2e7786..ecd439a 100644 --- a/tests/output/diagnosis.rs +++ b/tests/output/diagnosis.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde_json::json; use ocptv::output::{Diagnosis, DiagnosisType, Subcomponent}; @@ -33,13 +32,10 @@ async fn test_step_with_diagnosis() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_diagnosis("verdict", DiagnosisType::Pass).await?; + check_output_step(&expected, |s, _| async move { + s.add_diagnosis("verdict", DiagnosisType::Pass).await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -81,7 +77,6 @@ async fn test_step_with_diagnosis_builder() -> Result<()> { Ok(()) } - .boxed() }) .await } diff --git a/tests/output/error.rs b/tests/output/error.rs index 2134c26..19e55b4 100644 --- a/tests/output/error.rs +++ b/tests/output/error.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde_json::json; use ocptv::output::Error; @@ -29,9 +28,10 @@ async fn test_testrun_with_error() -> Result<()> { json_run_pass(3), ]; - check_output_run(&expected, |r, _| { - async move { r.add_error("symptom").await }.boxed() - }) + check_output_run( + &expected, + |r, _| async move { r.add_error("symptom").await }, + ) .await } @@ -53,8 +53,8 @@ async fn test_testrun_with_error_with_message() -> Result<()> { json_run_pass(3), ]; - check_output_run(&expected, |r, _| { - async move { r.add_error_msg("symptom", "Error message").await }.boxed() + check_output_run(&expected, |r, _| async move { + r.add_error_msg("symptom", "Error message").await }) .await } @@ -95,7 +95,6 @@ async fn test_testrun_with_error_with_details() -> Result<()> { ) .await } - .boxed() }) .await } @@ -115,14 +114,11 @@ async fn test_testrun_with_error_before_start() -> Result<()> { }), ]; - check_output(&expected, |run_builder, _| { - async move { - let run = run_builder.build(); - run.add_error("no-dut").await?; + check_output(&expected, |run_builder, _| async move { + let run = run_builder.build(); + run.add_error("no-dut").await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -143,14 +139,11 @@ async fn test_testrun_with_error_with_message_before_start() -> Result<()> { }), ]; - check_output(&expected, |run_builder, _| { - async move { - let run = run_builder.build(); - run.add_error_msg("no-dut", "failed to find dut").await?; + check_output(&expected, |run_builder, _| async move { + let run = run_builder.build(); + run.add_error_msg("no-dut", "failed to find dut").await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -175,20 +168,17 @@ async fn test_testrun_with_error_with_details_before_start() -> Result<()> { }), ]; - check_output(&expected, |run_builder, _| { - async move { - let run = run_builder.build(); - run.add_error_detail( - Error::builder("no-dut") - .message("failed to find dut") - .source("file", 1) - .build(), - ) - .await?; + check_output(&expected, |run_builder, _| async move { + let run = run_builder.build(); + run.add_error_detail( + Error::builder("no-dut") + .message("failed to find dut") + .source("file", 1) + .build(), + ) + .await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -213,13 +203,10 @@ async fn test_testrun_step_error() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_error("symptom").await?; + check_output_step(&expected, |s, _| async move { + s.add_error("symptom").await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -245,13 +232,10 @@ async fn test_testrun_step_error_with_message() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_error_msg("symptom", "Error message").await?; + check_output_step(&expected, |s, _| async move { + s.add_error_msg("symptom", "Error message").await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -284,20 +268,17 @@ async fn test_testrun_step_error_with_details() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, dut| { - async move { - s.add_error_detail( - Error::builder("symptom") - .message("Error message") - .source("file", 1) - .add_software_info(dut.software_info("sw0").unwrap()) - .build(), - ) - .await?; + check_output_step(&expected, |s, dut| async move { + s.add_error_detail( + Error::builder("symptom") + .message("Error message") + .source("file", 1) + .add_software_info(dut.software_info("sw0").unwrap()) + .build(), + ) + .await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } diff --git a/tests/output/file.rs b/tests/output/file.rs index d9d9065..bc0ce98 100644 --- a/tests/output/file.rs +++ b/tests/output/file.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde_json::json; use ocptv::output::{File, Uri}; @@ -35,13 +34,10 @@ async fn test_step_with_file() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_file("name", uri).await?; + check_output_step(&expected, |s, _| async move { + s.add_file("name", uri).await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -74,18 +70,15 @@ async fn test_step_with_file_builder() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - let file = File::builder("name", uri) - .content_type(mime::TEXT_PLAIN) - .description("description") - .add_metadata("key", "value".into()) - .build(); - s.add_file_detail(file).await?; + check_output_step(&expected, |s, _| async move { + let file = File::builder("name", uri) + .content_type(mime::TEXT_PLAIN) + .description("description") + .add_metadata("key", "value".into()) + .build(); + s.add_file_detail(file).await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } diff --git a/tests/output/fixture.rs b/tests/output/fixture.rs index 5c038b8..1c25a8c 100644 --- a/tests/output/fixture.rs +++ b/tests/output/fixture.rs @@ -8,16 +8,14 @@ use std::sync::Arc; use anyhow::Result; use assert_json_diff::assert_json_eq; -use futures::future::BoxFuture; use futures::future::Future; -use ocptv::output::TestRunOutcome; use serde_json::json; use tokio::sync::Mutex; use ocptv::output::{ - Config, DutInfo, HardwareInfo, Ident, OcptvError, ScopedTestRun, SoftwareInfo, SoftwareType, - StartedTestStep, TestResult, TestRun, TestRunBuilder, TestStatus, TimestampProvider, - SPEC_VERSION, + Config, DutInfo, HardwareInfo, Ident, OcptvError, ScopedTestRun, ScopedTestStep, SoftwareInfo, + SoftwareType, TestResult, TestRun, TestRunBuilder, TestRunOutcome, TestStatus, + TimestampProvider, SPEC_VERSION, }; pub const DATETIME: chrono::DateTime = @@ -159,34 +157,35 @@ where F: FnOnce(ScopedTestRun, DutInfo) -> R + Send + 'static, { check_output(expected, |run_builder, dut| async move { - let run = run_builder.build(); - - run.scope(dut.clone(), |run| async move { - test_fn(run, dut).await?; - Ok(TestRunOutcome { - status: TestStatus::Complete, - result: TestResult::Pass, + run_builder + .build() + .scope(dut.clone(), |run| async move { + test_fn(run, dut).await?; + Ok(TestRunOutcome { + status: TestStatus::Complete, + result: TestResult::Pass, + }) }) - }) - .await?; + .await?; Ok(()) }) .await } -pub async fn check_output_step(expected: &[serde_json::Value], test_fn: F) -> Result<()> +pub async fn check_output_step(expected: &[serde_json::Value], test_fn: F) -> Result<()> where - F: for<'a> FnOnce(&'a StartedTestStep, DutInfo) -> BoxFuture<'a, Result<(), OcptvError>>, + R: Future> + Send + 'static, + F: FnOnce(ScopedTestStep, DutInfo) -> R + Send + 'static, { - check_output(expected, |run_builder, dut| async move { - let run = run_builder.build().start(dut.clone()).await?; + check_output_run(expected, |run, dut| async move { + run.add_step("first step") + .scope(|step| async move { + test_fn(step, dut).await?; - let step = run.add_step("first step").start().await?; - test_fn(&step, dut).await?; - step.end(TestStatus::Complete).await?; - - run.end(TestStatus::Complete, TestResult::Pass).await?; + Ok(TestStatus::Complete) + }) + .await?; Ok(()) }) diff --git a/tests/output/log.rs b/tests/output/log.rs index 0a1826b..cc8fc2c 100644 --- a/tests/output/log.rs +++ b/tests/output/log.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde_json::json; use ocptv::output::{Log, LogSeverity}; @@ -30,15 +29,12 @@ async fn test_testrun_with_log() -> Result<()> { json_run_pass(3), ]; - check_output_run(&expected, |r, _| { - async move { - r.add_log( - LogSeverity::Info, - "This is a log message with INFO severity", - ) - .await - } - .boxed() + check_output_run(&expected, |r, _| async move { + r.add_log( + LogSeverity::Info, + "This is a log message with INFO severity", + ) + .await }) .await } @@ -65,17 +61,14 @@ async fn test_testrun_with_log_with_details() -> Result<()> { json_run_pass(3), ]; - check_output_run(&expected, |r, _| { - async move { - r.add_log_detail( - Log::builder("This is a log message with INFO severity") - .severity(LogSeverity::Info) - .source("file", 1) - .build(), - ) - .await - } - .boxed() + check_output_run(&expected, |r, _| async move { + r.add_log_detail( + Log::builder("This is a log message with INFO severity") + .severity(LogSeverity::Info) + .source("file", 1) + .build(), + ) + .await }) .await } @@ -101,17 +94,14 @@ async fn test_testrun_step_log() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_log( - LogSeverity::Info, - "This is a log message with INFO severity", - ) - .await?; + check_output_step(&expected, |s, _| async move { + s.add_log( + LogSeverity::Info, + "This is a log message with INFO severity", + ) + .await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -141,19 +131,16 @@ async fn test_testrun_step_log_with_details() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_log_detail( - Log::builder("This is a log message with INFO severity") - .severity(LogSeverity::Info) - .source("file", 1) - .build(), - ) - .await?; + check_output_step(&expected, |s, _| async move { + s.add_log_detail( + Log::builder("This is a log message with INFO severity") + .severity(LogSeverity::Info) + .source("file", 1) + .build(), + ) + .await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } diff --git a/tests/output/measure.rs b/tests/output/measure.rs index 61b037d..e3da99b 100644 --- a/tests/output/measure.rs +++ b/tests/output/measure.rs @@ -5,7 +5,6 @@ // https://opensource.org/licenses/MIT. use anyhow::Result; -use futures::FutureExt; use serde_json::json; use ocptv::output::{ @@ -36,13 +35,10 @@ async fn test_step_with_measurement() -> Result<()> { json_run_pass(5), ]; - check_output_step(&expected, |s, _| { - async { - s.add_measurement("name", 50.into()).await?; + check_output_step(&expected, |s, _| async move { + s.add_measurement("name", 50.into()).await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -95,7 +91,6 @@ async fn test_step_with_measurement_builder() -> Result<()> { Ok(()) } - .boxed() }) .await } @@ -132,14 +127,11 @@ async fn test_step_with_measurement_series() -> Result<()> { json_run_pass(6), ]; - check_output_step(&expected, |s, _| { - async { - let series = s.add_measurement_series("name").start().await?; - series.end().await?; + check_output_step(&expected, |s, _| async move { + let series = s.add_measurement_series("name").start().await?; + series.end().await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -198,17 +190,14 @@ async fn test_step_with_multiple_measurement_series() -> Result<()> { json_run_pass(8), ]; - check_output_step(&expected, |s, _| { - async { - let series = s.add_measurement_series("name").start().await?; - series.end().await?; + check_output_step(&expected, |s, _| async move { + let series = s.add_measurement_series("name").start().await?; + series.end().await?; - let series_2 = s.add_measurement_series("name").start().await?; - series_2.end().await?; + let series_2 = s.add_measurement_series("name").start().await?; + series_2.end().await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -280,7 +269,6 @@ async fn test_step_with_measurement_series_with_details() -> Result<()> { Ok(()) } - .boxed() }) .await } @@ -330,15 +318,12 @@ async fn test_step_with_measurement_series_element() -> Result<()> { json_run_pass(7), ]; - check_output_step(&expected, |s, _| { - async { - let series = s.add_measurement_series("name").start().await?; - series.add_measurement(60.into()).await?; - series.end().await?; + check_output_step(&expected, |s, _| async move { + let series = s.add_measurement_series("name").start().await?; + series.add_measurement(60.into()).await?; + series.end().await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } @@ -415,7 +400,7 @@ async fn test_step_with_measurement_series_element_index_no() -> Result<()> { ]; check_output_step(&expected, |s, _| { - async { + async move { let series = s.add_measurement_series("name").start().await?; // add more than one element to check the index increments correctly series.add_measurement(60.into()).await?; @@ -425,7 +410,6 @@ async fn test_step_with_measurement_series_element_index_no() -> Result<()> { Ok(()) } - .boxed() }) .await } @@ -479,11 +463,10 @@ async fn test_step_with_measurement_series_element_with_details() -> Result<()> json_run_pass(7), ]; - check_output_step(&expected, |s, _| { - async { - let series = s.add_measurement_series("name").start().await?; - series - .add_measurement_detail( + check_output_step(&expected, |s, _| async move { + s.add_measurement_series("name") + .scope(|s| async move { + s.add_measurement_detail( MeasurementElementDetail::builder(60.into()) .timestamp(DATETIME.with_timezone(&chrono_tz::UTC)) .add_metadata("key", "value".into()) @@ -491,11 +474,12 @@ async fn test_step_with_measurement_series_element_with_details() -> Result<()> .build(), ) .await?; - series.end().await?; - Ok(()) - } - .boxed() + Ok(()) + }) + .await?; + + Ok(()) }) .await } @@ -575,7 +559,7 @@ async fn test_step_with_measurement_series_element_with_metadata_index_no() -> R ]; check_output_step(&expected, |s, _| { - async { + async move { let series = s.add_measurement_series("name").start().await?; // add more than one element to check the index increments correctly series @@ -603,12 +587,10 @@ async fn test_step_with_measurement_series_element_with_metadata_index_no() -> R Ok(()) } - .boxed() }) .await } -#[cfg(feature = "boxed-scopes")] #[tokio::test] async fn test_step_with_measurement_series_scope() -> Result<()> { let expected = [ @@ -680,25 +662,19 @@ async fn test_step_with_measurement_series_scope() -> Result<()> { json_run_pass(9), ]; - check_output_step(&expected, |s, _| { - async { - let series = s.add_measurement_series("name"); - series - .scope(|s| { - async move { - s.add_measurement(60.into()).await?; - s.add_measurement(70.into()).await?; - s.add_measurement(80.into()).await?; + check_output_step(&expected, |s, _| async move { + let series = s.add_measurement_series("name"); + series + .scope(|s| async move { + s.add_measurement(60.into()).await?; + s.add_measurement(70.into()).await?; + s.add_measurement(80.into()).await?; - Ok(()) - } - .boxed() - }) - .await?; + Ok(()) + }) + .await?; - Ok(()) - } - .boxed() + Ok(()) }) .await } diff --git a/tests/output/run.rs b/tests/output/run.rs index bf0ac79..3ca1677 100644 --- a/tests/output/run.rs +++ b/tests/output/run.rs @@ -26,7 +26,6 @@ async fn test_testrun_start_and_end() -> Result<()> { check_output_run(&expected, |_, _| async { Ok(()) }).await } -#[cfg(feature = "boxed-scopes")] #[tokio::test] async fn test_testrun_with_scope() -> Result<()> { use ocptv::output::{LogSeverity, TestResult, TestRunOutcome, TestStatus}; diff --git a/tests/output/step.rs b/tests/output/step.rs index bd9c3a3..bf0b358 100644 --- a/tests/output/step.rs +++ b/tests/output/step.rs @@ -7,11 +7,10 @@ use std::sync::Arc; use anyhow::Result; -use futures::FutureExt; use serde_json::json; use tokio::sync::Mutex; -use ocptv::output::{Config, DutInfo, OcptvError, TestRun}; +use ocptv::output::{Config, DutInfo, OcptvError, TestRun, TestStatus}; use super::fixture::*; @@ -20,15 +19,38 @@ async fn test_testrun_with_step() -> Result<()> { let expected = [ json_schema_version(), json_run_default_start(), - json_step_default_start(), - json_step_complete(3), + json!({ + "testStepArtifact": { + "testStepId": "step0", + "testStepStart": { + "name": "first step" + } + }, + "sequenceNumber": 2, + "timestamp": DATETIME_FORMATTED + }), + json!({ + "testStepArtifact": { + "testStepId": "step0", + "testStepEnd": { + "status": "COMPLETE" + } + }, + "sequenceNumber": 3, + "timestamp": DATETIME_FORMATTED + }), json_run_pass(4), ]; - check_output_step(&expected, |_, _| async { Ok(()) }.boxed()).await + check_output_run(&expected, |r, _| async move { + let step = r.add_step("first step").start().await?; + step.end(TestStatus::Complete).await?; + + Ok(()) + }) + .await } -#[cfg(feature = "boxed-scopes")] #[tokio::test] async fn test_testrun_step_scope_log() -> Result<()> { use ocptv::output::{LogSeverity, TestStatus}; @@ -52,24 +74,18 @@ async fn test_testrun_step_scope_log() -> Result<()> { json_run_pass(5), ]; - check_output_run(&expected, |r, _| { - async move { - r.add_step("first step") - .scope(|s| { - async move { - s.add_log( - LogSeverity::Info, - "This is a log message with INFO severity", - ) - .await?; - - Ok(TestStatus::Complete) - } - .boxed() - }) - .await - } - .boxed() + check_output_run(&expected, |r, _| async move { + r.add_step("first step") + .scope(|s| async move { + s.add_log( + LogSeverity::Info, + "This is a log message with INFO severity", + ) + .await?; + + Ok(TestStatus::Complete) + }) + .await }) .await } @@ -109,21 +125,18 @@ async fn test_step_with_extension() -> Result<()> { number_field: u32, } - check_output_step(&expected, |s, _| { - async { - s.add_extension( - "extension", - Ext { - r#type: "TestExtension".to_owned(), - string_field: "string".to_owned(), - number_field: 42, - }, - ) - .await?; - - Ok(()) - } - .boxed() + check_output_step(&expected, |s, _| async move { + s.add_extension( + "extension", + Ext { + r#type: "TestExtension".to_owned(), + string_field: "string".to_owned(), + number_field: 42, + }, + ) + .await?; + + Ok(()) }) .await }