mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
122 lines
3.7 KiB
Rust
122 lines
3.7 KiB
Rust
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
fn encode_commands(commands: &[&[&str]]) -> String {
|
|
let mut bytes = Vec::new();
|
|
bytes.extend_from_slice(&u32::try_from(commands.len()).unwrap().to_le_bytes());
|
|
for command in commands {
|
|
bytes.extend_from_slice(&u32::try_from(command.len()).unwrap().to_le_bytes());
|
|
for word in *command {
|
|
bytes.extend_from_slice(&u32::try_from(word.len()).unwrap().to_le_bytes());
|
|
bytes.extend_from_slice(word.as_bytes());
|
|
}
|
|
}
|
|
BASE64_STANDARD.encode(bytes)
|
|
}
|
|
|
|
#[test]
|
|
fn framed_protocol_preserves_ids_and_command_words() {
|
|
for (id, payload, expected) in [
|
|
(
|
|
42,
|
|
"RwBlAHQALQBDAG8AbgB0AGUAbgB0AA==",
|
|
"42\tRwBlAHQALQBDAG8AbgB0AGUAbgB0AA==",
|
|
),
|
|
(43, "", "43\t"),
|
|
] {
|
|
assert_eq!(
|
|
serialize_request(&PowershellParserRequest {
|
|
id,
|
|
payload: payload.into()
|
|
})
|
|
.unwrap(),
|
|
expected,
|
|
);
|
|
}
|
|
|
|
let payload = encode_commands(&[&["Get-Content", "fóó.txt"], &["Measure-Object"]]);
|
|
assert_eq!(
|
|
deserialize_response(&format!("42\tok\t{payload}\r\n")).unwrap(),
|
|
PowershellParserResponse {
|
|
id: 42,
|
|
status: "ok".into(),
|
|
commands: Some(vec![
|
|
["Get-Content", "fóó.txt"].map(str::to_string).to_vec(),
|
|
vec!["Measure-Object".into()],
|
|
]),
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn framed_protocol_rejects_malformed_command_payloads() {
|
|
let encode = |bytes| format!("1\tok\t{}", BASE64_STANDARD.encode(bytes));
|
|
for response in [
|
|
"missing-fields".into(),
|
|
"1\tok".into(),
|
|
"x\tunsupported\t".into(),
|
|
"1\tunsupported\tnot-empty".into(),
|
|
"1\tunsupported\t\textra".into(),
|
|
"1\tok\tnot-base64!".into(),
|
|
encode(vec![1, 0, 0]),
|
|
encode(vec![u8::MAX; 4]),
|
|
encode(vec![1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, u8::MAX]),
|
|
encode(vec![1, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255]),
|
|
encode(vec![0, 0, 0, 0, u8::MAX]),
|
|
] {
|
|
assert!(
|
|
deserialize_response(&response).is_err(),
|
|
"accepted {response:?}"
|
|
);
|
|
}
|
|
assert!(
|
|
serialize_request(&PowershellParserRequest {
|
|
id: 1,
|
|
payload: "bad\tpayload".into(),
|
|
})
|
|
.is_err()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn framed_protocol_bounds_lines_and_distinguishes_outcomes() {
|
|
let mut complete = std::io::Cursor::new(b"1\tunsupported\t\n".as_slice());
|
|
assert_eq!(
|
|
read_bounded_response_line(&mut complete, /*max_bytes*/ 32).unwrap(),
|
|
"1\tunsupported\t\n"
|
|
);
|
|
for bytes in [b"123456789\n".as_slice(), b"unterminated".as_slice()] {
|
|
assert!(
|
|
read_bounded_response_line(&mut std::io::Cursor::new(bytes), /*max_bytes*/ 8,).is_err()
|
|
);
|
|
}
|
|
|
|
for (status, commands, expected) in [
|
|
("unsupported", None, PowershellParseOutcome::Unsupported),
|
|
("ok", Some(Vec::new()), PowershellParseOutcome::Unsupported),
|
|
(
|
|
"ok",
|
|
Some(vec![Vec::new()]),
|
|
PowershellParseOutcome::Unsupported,
|
|
),
|
|
(
|
|
"ok",
|
|
Some(vec![vec![String::new()]]),
|
|
PowershellParseOutcome::Unsupported,
|
|
),
|
|
("parse_failed", None, PowershellParseOutcome::Failed),
|
|
("parse_errors", None, PowershellParseOutcome::Failed),
|
|
("unknown", None, PowershellParseOutcome::Failed),
|
|
] {
|
|
assert_eq!(
|
|
PowershellParserResponse {
|
|
id: 0,
|
|
status: status.into(),
|
|
commands
|
|
}
|
|
.into_outcome(),
|
|
expected,
|
|
);
|
|
}
|
|
}
|