Skip to content

Commit

Permalink
feat(pact_consumer): Improve the mock server error output
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Jul 10, 2024
1 parent f03cd0d commit 2e2580f
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 12 deletions.
12 changes: 12 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/pact_consumer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pact_models = { version = "~1.2.1", default-features = false }
pact-plugin-driver = { version = "~0.6.1", optional = true, default-features = false }
regex = "1.10.4"
serde_json = "1.0.115"
termsize = "0.1.8"
tokio = { version = "1.37.0", features = ["full"] }
tracing = "0.1.40"
tracing-core = "0.1.32"
Expand Down
28 changes: 20 additions & 8 deletions rust/pact_consumer/src/mock_server/http_mock_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{env, thread};
use std::fmt::Write;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use itertools::Itertools;

use pact_models::pact::Pact;
#[cfg(feature = "plugins")] use pact_models::plugins::PluginData;
Expand All @@ -17,6 +18,7 @@ use pact_matching::metrics::{MetricEvent, send_metrics};
use pact_mock_server::matching::MatchResult;
use pact_mock_server::mock_server;
use pact_mock_server::mock_server::{MockServerConfig, MockServerMetrics};
use pact_models::v4::http_parts::HttpRequest;

use crate::mock_server::ValidatingMockServer;
use crate::util::panic_or_print_error;
Expand Down Expand Up @@ -237,36 +239,46 @@ impl ValidatingHttpMockServer {
Ok(())
} else {
// Failure. Format our errors.
let mut msg = format!("mock server {} failed verification:\n", self.description,);
let size = termsize::get().map(|sz| sz.cols).unwrap_or(120) - 2;
let pad = "-".repeat(size as usize);
let mut msg = format!(" {} \nMock server {} failed verification:\n", pad, self.description);
for mismatch in mismatches {
match mismatch {
MatchResult::RequestMatch(..) => {
unreachable!("list of mismatches contains a match");
warn!("list of mismatches contains a match");
}
MatchResult::RequestMismatch(request, _, mismatches) => {
let _ = writeln!(&mut msg, "- request {}:", request);
let _ = writeln!(&mut msg, "\n - request {}:\n", request);
for m in mismatches {
let _ = writeln!(&mut msg, " - {}", m.description());
let _ = writeln!(&mut msg, " - {}", m.description());
}
}
MatchResult::RequestNotFound(request) => {
let _ = writeln!(&mut msg, "- received unexpected request:");
let _ = writeln!(&mut msg, "{:#?}", request);
let _ = writeln!(&mut msg, "\n - received unexpected request {}:\n", short_description(&request));
let debug_str = format!("{:#?}", request);
let _ = writeln!(&mut msg, "{}", debug_str.lines().map(|ln| format!(" {}", ln)).join("\n"));
}
MatchResult::MissingRequest(request) => {
let _ = writeln!(
&mut msg,
"- request {} expected, but never occurred", request,
"\n - request {} expected, but never occurred:\n", short_description(&request),
);
let _ = writeln!(&mut msg, "{:#?}", request);
let debug_str = format!("{:#?}", request);
let _ = writeln!(&mut msg, "{}", debug_str.lines().map(|ln| format!(" {}", ln)).join("\n"));
}
}
}
let _ = writeln!(&mut msg, " {} ", pad);
Err(msg)
}
}
}

// TODO: Implement this in the HTTP request struct
fn short_description(request: &HttpRequest) -> String {
format!("{} {}", request.method.to_uppercase(), request.path)
}

impl ValidatingMockServer for ValidatingHttpMockServer {
fn url(&self) -> Url {
self.url.clone()
Expand Down
7 changes: 3 additions & 4 deletions rust/pact_consumer/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
//! Most of these are `pub(crate)`, which makes them available to the rest of
//! the crate, but prevents them from winding up in our public API.
use std::{io, thread};
use std::io::Write;
use std::thread;

/// Internal helper method for `strip_null_fields`.
fn strip_null_fields_mut(json: &mut serde_json::Value) {
Expand Down Expand Up @@ -93,9 +92,9 @@ pub(crate) fn panic_or_print_error(msg: &str) {
if thread::panicking() {
// The current thread is panicking, so don't try to panic again, because
// double panics don't print useful explanations of why the test failed.
// Instead, just print to `stderr`. Ignore any errors, because there's
// Instead, just print to `stdout`. Ignore any errors, because there's
// not much we can do if we can't panic and we can't write to `stderr`.
let _ = writeln!(io::stderr(), "{}", msg);
let _ = println!("{}", msg);
} else {
panic!("{}", msg);
}
Expand Down
5 changes: 5 additions & 0 deletions rust/pact_models/src/v4/http_parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ impl HttpRequest {
None => None
}
}

/// Brief one-line description of the request
pub fn short_description(&self) -> String {
format!("{} {}", self.method.to_uppercase(), self.path)
}
}

impl PartialEq for HttpRequest {
Expand Down

0 comments on commit 2e2580f

Please sign in to comment.