Use helpers instead of fixtures (#3888)
Move to using test helper method everywhere.
This commit is contained in:
@@ -74,6 +74,39 @@ pub fn ev_function_call(call_id: &str, name: &str, arguments: &str) -> Value {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convenience: SSE event for an `apply_patch` custom tool call with raw patch
|
||||||
|
/// text. This mirrors the payload produced by the Responses API when the model
|
||||||
|
/// invokes `apply_patch` directly (before we convert it to a function call).
|
||||||
|
pub fn ev_apply_patch_custom_tool_call(call_id: &str, patch: &str) -> Value {
|
||||||
|
serde_json::json!({
|
||||||
|
"type": "response.output_item.done",
|
||||||
|
"item": {
|
||||||
|
"type": "custom_tool_call",
|
||||||
|
"name": "apply_patch",
|
||||||
|
"input": patch,
|
||||||
|
"call_id": call_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience: SSE event for an `apply_patch` function call. The Responses API
|
||||||
|
/// wraps the patch content in a JSON string under the `input` key; we recreate
|
||||||
|
/// the same structure so downstream code exercises the full parsing path.
|
||||||
|
pub fn ev_apply_patch_function_call(call_id: &str, patch: &str) -> Value {
|
||||||
|
let arguments = serde_json::json!({ "input": patch });
|
||||||
|
let arguments = serde_json::to_string(&arguments).expect("serialize apply_patch arguments");
|
||||||
|
|
||||||
|
serde_json::json!({
|
||||||
|
"type": "response.output_item.done",
|
||||||
|
"item": {
|
||||||
|
"type": "function_call",
|
||||||
|
"name": "apply_patch",
|
||||||
|
"arguments": arguments,
|
||||||
|
"call_id": call_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sse_response(body: String) -> ResponseTemplate {
|
pub fn sse_response(body: String) -> ResponseTemplate {
|
||||||
ResponseTemplate::new(200)
|
ResponseTemplate::new(200)
|
||||||
.insert_header("content-type", "text/event-stream")
|
.insert_header("content-type", "text/event-stream")
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "response.output_item.done",
|
|
||||||
"item": {
|
|
||||||
"type": "custom_tool_call",
|
|
||||||
"name": "apply_patch",
|
|
||||||
"input": "*** Begin Patch\n*** Add File: test.md\n+Hello world\n*** End Patch",
|
|
||||||
"call_id": "__ID__"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "__ID__",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 0,
|
|
||||||
"input_tokens_details": null,
|
|
||||||
"output_tokens": 0,
|
|
||||||
"output_tokens_details": null,
|
|
||||||
"total_tokens": 0
|
|
||||||
},
|
|
||||||
"output": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "response.output_item.done",
|
|
||||||
"item": {
|
|
||||||
"type": "custom_tool_call",
|
|
||||||
"name": "apply_patch",
|
|
||||||
"input": "*** Begin Patch\n*** Add File: app.py\n+class BaseClass:\n+ def method():\n+ return False\n*** End Patch",
|
|
||||||
"call_id": "__ID__"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "__ID__",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 0,
|
|
||||||
"input_tokens_details": null,
|
|
||||||
"output_tokens": 0,
|
|
||||||
"output_tokens_details": null,
|
|
||||||
"total_tokens": 0
|
|
||||||
},
|
|
||||||
"output": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "response.output_item.done",
|
|
||||||
"item": {
|
|
||||||
"type": "custom_tool_call",
|
|
||||||
"name": "apply_patch",
|
|
||||||
"input": "*** Begin Patch\n*** Update File: app.py\n@@ def method():\n- return False\n+\n+ return True\n*** End Patch",
|
|
||||||
"call_id": "__ID__"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "__ID__",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 0,
|
|
||||||
"input_tokens_details": null,
|
|
||||||
"output_tokens": 0,
|
|
||||||
"output_tokens_details": null,
|
|
||||||
"total_tokens": 0
|
|
||||||
},
|
|
||||||
"output": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "response.output_item.done",
|
|
||||||
"item": {
|
|
||||||
"type": "function_call",
|
|
||||||
"name": "apply_patch",
|
|
||||||
"arguments": "{\n \"input\": \"*** Begin Patch\\n*** Update File: test.md\\n@@\\n-Hello world\\n+Final text\\n*** End Patch\"\n}",
|
|
||||||
"call_id": "__ID__"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "__ID__",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 0,
|
|
||||||
"input_tokens_details": null,
|
|
||||||
"output_tokens": 0,
|
|
||||||
"output_tokens_details": null,
|
|
||||||
"total_tokens": 0
|
|
||||||
},
|
|
||||||
"output": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type": "response.completed",
|
|
||||||
"response": {
|
|
||||||
"id": "__ID__",
|
|
||||||
"usage": {
|
|
||||||
"input_tokens": 0,
|
|
||||||
"input_tokens_details": null,
|
|
||||||
"output_tokens": 0,
|
|
||||||
"output_tokens_details": null,
|
|
||||||
"total_tokens": 0
|
|
||||||
},
|
|
||||||
"output": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
#![allow(clippy::expect_used, clippy::unwrap_used)]
|
#![allow(clippy::expect_used, clippy::unwrap_used, unused_imports)]
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::prelude::*;
|
||||||
use codex_core::CODEX_APPLY_PATCH_ARG1;
|
use codex_core::CODEX_APPLY_PATCH_ARG1;
|
||||||
|
use core_test_support::responses::ev_apply_patch_custom_tool_call;
|
||||||
|
use core_test_support::responses::ev_apply_patch_function_call;
|
||||||
|
use core_test_support::responses::ev_completed;
|
||||||
|
use core_test_support::responses::sse;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
@@ -55,15 +59,28 @@ async fn test_apply_patch_tool() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let tmp_cwd = tempdir().expect("failed to create temp dir");
|
let tmp_cwd = tempdir().expect("failed to create temp dir");
|
||||||
let tmp_path = tmp_cwd.path().to_path_buf();
|
let tmp_path = tmp_cwd.path().to_path_buf();
|
||||||
run_e2e_exec_test(
|
let add_patch = r#"*** Begin Patch
|
||||||
tmp_cwd.path(),
|
*** Add File: test.md
|
||||||
vec![
|
+Hello world
|
||||||
include_str!("../fixtures/sse_apply_patch_add.json").to_string(),
|
*** End Patch"#;
|
||||||
include_str!("../fixtures/sse_apply_patch_update.json").to_string(),
|
let update_patch = r#"*** Begin Patch
|
||||||
include_str!("../fixtures/sse_response_completed.json").to_string(),
|
*** Update File: test.md
|
||||||
],
|
@@
|
||||||
)
|
-Hello world
|
||||||
.await;
|
+Final text
|
||||||
|
*** End Patch"#;
|
||||||
|
let response_streams = vec![
|
||||||
|
sse(vec![
|
||||||
|
ev_apply_patch_custom_tool_call("request_0", add_patch),
|
||||||
|
ev_completed("request_0"),
|
||||||
|
]),
|
||||||
|
sse(vec![
|
||||||
|
ev_apply_patch_function_call("request_1", update_patch),
|
||||||
|
ev_completed("request_1"),
|
||||||
|
]),
|
||||||
|
sse(vec![ev_completed("request_2")]),
|
||||||
|
];
|
||||||
|
run_e2e_exec_test(tmp_cwd.path(), response_streams).await;
|
||||||
|
|
||||||
let final_path = tmp_path.join("test.md");
|
let final_path = tmp_path.join("test.md");
|
||||||
let contents = std::fs::read_to_string(&final_path)
|
let contents = std::fs::read_to_string(&final_path)
|
||||||
@@ -86,15 +103,31 @@ async fn test_apply_patch_freeform_tool() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tmp_cwd = tempdir().expect("failed to create temp dir");
|
let tmp_cwd = tempdir().expect("failed to create temp dir");
|
||||||
run_e2e_exec_test(
|
let freeform_add_patch = r#"*** Begin Patch
|
||||||
tmp_cwd.path(),
|
*** Add File: app.py
|
||||||
vec![
|
+class BaseClass:
|
||||||
include_str!("../fixtures/sse_apply_patch_freeform_add.json").to_string(),
|
+ def method():
|
||||||
include_str!("../fixtures/sse_apply_patch_freeform_update.json").to_string(),
|
+ return False
|
||||||
include_str!("../fixtures/sse_response_completed.json").to_string(),
|
*** End Patch"#;
|
||||||
],
|
let freeform_update_patch = r#"*** Begin Patch
|
||||||
)
|
*** Update File: app.py
|
||||||
.await;
|
@@ def method():
|
||||||
|
- return False
|
||||||
|
+
|
||||||
|
+ return True
|
||||||
|
*** End Patch"#;
|
||||||
|
let response_streams = vec![
|
||||||
|
sse(vec![
|
||||||
|
ev_apply_patch_custom_tool_call("request_0", freeform_add_patch),
|
||||||
|
ev_completed("request_0"),
|
||||||
|
]),
|
||||||
|
sse(vec![
|
||||||
|
ev_apply_patch_custom_tool_call("request_1", freeform_update_patch),
|
||||||
|
ev_completed("request_1"),
|
||||||
|
]),
|
||||||
|
sse(vec![ev_completed("request_2")]),
|
||||||
|
];
|
||||||
|
run_e2e_exec_test(tmp_cwd.path(), response_streams).await;
|
||||||
|
|
||||||
// Verify final file contents
|
// Verify final file contents
|
||||||
let final_path = tmp_cwd.path().join("app.py");
|
let final_path = tmp_cwd.path().join("app.py");
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::prelude::*;
|
||||||
use core_test_support::load_sse_fixture_with_id_from_str;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
@@ -27,10 +26,7 @@ impl Respond for SeqResponder {
|
|||||||
match self.responses.get(call_num) {
|
match self.responses.get(call_num) {
|
||||||
Some(body) => wiremock::ResponseTemplate::new(200)
|
Some(body) => wiremock::ResponseTemplate::new(200)
|
||||||
.insert_header("content-type", "text/event-stream")
|
.insert_header("content-type", "text/event-stream")
|
||||||
.set_body_raw(
|
.set_body_string(body.clone()),
|
||||||
load_sse_fixture_with_id_from_str(body, &format!("request_{call_num}")),
|
|
||||||
"text/event-stream",
|
|
||||||
),
|
|
||||||
None => panic!("no response for {call_num}"),
|
None => panic!("no response for {call_num}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user