fix(acp): fixtures now raise content mismatch errors (#6912)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -30,7 +30,7 @@ pub async fn run_basic_completion<S: Session>() {
|
||||
let output = session
|
||||
.prompt("what is 1+1", PermissionDecision::Cancel)
|
||||
.await;
|
||||
assert!(output.text.contains("2"));
|
||||
assert_eq!(output.text, "2");
|
||||
expected_session_id.assert_matches(&session.id().0);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ pub async fn run_mcp_http_server<S: Session>() {
|
||||
PermissionDecision::Cancel,
|
||||
)
|
||||
.await;
|
||||
assert!(output.text.contains(FAKE_CODE));
|
||||
assert_eq!(output.text, FAKE_CODE);
|
||||
expected_session_id.assert_matches(&session.id().0);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ pub async fn run_builtin_and_mcp<S: Session>() {
|
||||
include_str!("../test_data/openai_builtin_execute.txt"),
|
||||
),
|
||||
(
|
||||
r#""writeResult": "Successfully wrote to /tmp/result.txt"#.into(),
|
||||
r#"\"writeResult\": \"Successfully wrote to /tmp/result.txt"#.into(),
|
||||
include_str!("../test_data/openai_builtin_final.txt"),
|
||||
),
|
||||
],
|
||||
@@ -104,10 +104,13 @@ pub async fn run_builtin_and_mcp<S: Session>() {
|
||||
let mut session = S::new(config, openai).await;
|
||||
expected_session_id.set(session.id());
|
||||
|
||||
let _ = session.prompt(prompt, PermissionDecision::Cancel).await;
|
||||
let output = session.prompt(prompt, PermissionDecision::Cancel).await;
|
||||
if matches!(output.tool_status, Some(ToolCallStatus::Failed)) || output.text.contains("error") {
|
||||
panic!("{}", output.text);
|
||||
}
|
||||
|
||||
let result = fs::read_to_string("/tmp/result.txt").unwrap_or_default();
|
||||
assert!(result.contains(FAKE_CODE));
|
||||
assert_eq!(result, format!("{FAKE_CODE}\n"));
|
||||
expected_session_id.assert_matches(&session.id().0);
|
||||
}
|
||||
|
||||
@@ -215,6 +218,6 @@ pub async fn run_configured_extension<S: Session>() {
|
||||
expected_session_id.set(session.id());
|
||||
|
||||
let output = session.prompt(prompt, PermissionDecision::Cancel).await;
|
||||
assert!(output.text.contains(FAKE_CODE));
|
||||
assert_eq!(output.text, FAKE_CODE);
|
||||
expected_session_id.assert_matches(&session.id().0);
|
||||
}
|
||||
|
||||
+23
-18
@@ -1,7 +1,6 @@
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(unused_attributes)]
|
||||
|
||||
use assert_json_diff::{assert_json_matches_no_panic, CompareMode, Config};
|
||||
use async_trait::async_trait;
|
||||
use fs_err as fs;
|
||||
use goose::builtin_extension::register_builtin_extensions;
|
||||
@@ -153,8 +152,9 @@ impl OpenAiFixture {
|
||||
let queue = queue.clone();
|
||||
let expected_session_id = expected_session_id.clone();
|
||||
move |req: &wiremock::Request| {
|
||||
let body = String::from_utf8_lossy(&req.body);
|
||||
let body = std::str::from_utf8(&req.body).unwrap_or("");
|
||||
|
||||
// Validate session ID header
|
||||
let actual = req
|
||||
.headers
|
||||
.get(SESSION_ID_HEADER)
|
||||
@@ -174,28 +174,30 @@ impl OpenAiFixture {
|
||||
));
|
||||
}
|
||||
|
||||
let (expected_body, response) = {
|
||||
let mut q = queue.lock().unwrap();
|
||||
q.pop_front().unwrap_or_default()
|
||||
};
|
||||
|
||||
if body.contains(&expected_body) && !expected_body.is_empty() {
|
||||
// See if the actual request matches the expected pattern
|
||||
let mut q = queue.lock().unwrap();
|
||||
let (expected_body, response) = q.front().cloned().unwrap_or_default();
|
||||
if !expected_body.is_empty() && body.contains(&expected_body) {
|
||||
q.pop_front();
|
||||
return ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "text/event-stream")
|
||||
.set_body_string(response);
|
||||
}
|
||||
drop(q);
|
||||
|
||||
// Coerce non-json to allow a uniform JSON diff error response.
|
||||
let exp = serde_json::from_str(&expected_body)
|
||||
.unwrap_or(serde_json::Value::String(expected_body.clone()));
|
||||
let act = serde_json::from_str(&body)
|
||||
.unwrap_or(serde_json::Value::String(body.to_string()));
|
||||
let diff =
|
||||
assert_json_matches_no_panic(&exp, &act, Config::new(CompareMode::Strict))
|
||||
.unwrap_err();
|
||||
// If there was no body, the request was unexpected. Otherwise, it is a mismatch.
|
||||
let message = if expected_body.is_empty() {
|
||||
format!("Unexpected request:\n {}", body)
|
||||
} else {
|
||||
format!(
|
||||
"Expected body to contain:\n {}\n\nActual body:\n {}",
|
||||
expected_body, body
|
||||
)
|
||||
};
|
||||
// Use OpenAI's error response schema so the provider will pass the error through.
|
||||
ResponseTemplate::new(417)
|
||||
.insert_header("content-type", "application/json")
|
||||
.set_body_json(serde_json::json!({"error": {"message": diff}}))
|
||||
.set_body_json(serde_json::json!({"error": {"message": message}}))
|
||||
}
|
||||
})
|
||||
.mount(&mock_server)
|
||||
@@ -464,7 +466,10 @@ where
|
||||
runtime.block_on(fut);
|
||||
})
|
||||
.unwrap();
|
||||
handle.join().unwrap();
|
||||
if let Err(err) = handle.join() {
|
||||
// Re-raise the original panic so the test shows the real failure message.
|
||||
std::panic::resume_unwind(err);
|
||||
}
|
||||
}
|
||||
|
||||
pub mod server;
|
||||
|
||||
Reference in New Issue
Block a user