From 0b759deadbe9966f7d275013da335a434981afb4 Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Wed, 22 May 2024 15:12:45 +0100 Subject: [PATCH] fix(pact_verifier_cli): strip ANSI escapes from JUnit output When coloured output is enabled, output strings contain ANSI escapes, sequences of binary data that communicate with a terminal to control colours. Remove these sequences when producing a JUnit report, because the ESC bytecode (0x1B) is not a valid codepoint in XML documents. --- rust/Cargo.lock | 1 + rust/pact_verifier_cli/Cargo.toml | 5 +++-- rust/pact_verifier_cli/src/reports.rs | 7 +++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 197c5f9f7..d445d7ff2 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -2219,6 +2219,7 @@ dependencies = [ "regex", "reqwest 0.12.4", "serde_json", + "strip-ansi-escapes", "time", "tokio", "tracing", diff --git a/rust/pact_verifier_cli/Cargo.toml b/rust/pact_verifier_cli/Cargo.toml index 02a8230b9..81e8657ad 100644 --- a/rust/pact_verifier_cli/Cargo.toml +++ b/rust/pact_verifier_cli/Cargo.toml @@ -18,8 +18,8 @@ default = ["datetime", "xml", "plugins", "multipart", "junit"] datetime = ["pact_models/datetime", "pact_verifier/datetime"] # Support for date/time matchers and expressions xml = ["pact_models/xml", "pact_verifier/xml"] # support for matching XML documents plugins = ["pact_verifier/plugins"] -multipart = ["pact_verifier/multipart"] # suport for MIME multipart bodies -junit = ["dep:junit-report"] # suport for MIME multipart bodies +multipart = ["pact_verifier/multipart"] # support for MIME multipart bodies +junit = ["dep:junit-report", "dep:strip-ansi-escapes"] # support for Junit format reports [dependencies] ansi_term = "0.12.1" @@ -34,6 +34,7 @@ pact_verifier = { version = "~1.2.1", path = "../pact_verifier", default-feature regex = "1.10.2" reqwest = { version = "0.12.4", default-features = false, features = ["rustls-tls-native-roots", "blocking", "json"] } serde_json = "1.0.108" +strip-ansi-escapes = { version = "0.2.0", optional = true } time = "0.3.31" tokio = { version = "1.35.1", features = ["full"] } tracing = "0.1.40" diff --git a/rust/pact_verifier_cli/src/reports.rs b/rust/pact_verifier_cli/src/reports.rs index a66ab99d4..0df2b0048 100644 --- a/rust/pact_verifier_cli/src/reports.rs +++ b/rust/pact_verifier_cli/src/reports.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::Write; #[cfg(feature = "junit")] use junit_report::{ReportBuilder, TestCaseBuilder, TestSuiteBuilder}; +#[cfg(feature = "junit")] use strip_ansi_escapes; use serde_json::Value; use tracing::debug; @@ -22,7 +23,8 @@ pub(crate) fn write_junit_report(result: &VerificationExecutionResult, file_name let mut f = File::create(file_name)?; let mut test_suite = TestSuiteBuilder::new(provider); - test_suite.set_system_out(result.output.join("\n").as_str()); + let stripped_system_out = strip_ansi_escapes::strip_str(result.output.join("\n")); + test_suite.set_system_out(&stripped_system_out); for interaction_result in &result.interaction_results { let duration = time::Duration::try_from(interaction_result.duration).unwrap_or_default(); let test_case = match &interaction_result.result { @@ -42,7 +44,8 @@ pub(crate) fn write_junit_report(result: &VerificationExecutionResult, file_name "", "Verification for interaction failed" ); - builder.set_system_out(output_buffer.join("\n").as_str()); + let stripped_output = strip_ansi_escapes::strip_str(output_buffer.join("\n")); + builder.set_system_out(&stripped_output); builder }, MismatchResult::Error(error, _) => TestCaseBuilder::error(