use std::io::{Read, Write};
use std::process::{Command, ExitCode};
use lifeloop::{
AcceptablePlacement, CallbackResponse, DispatchEnvelope, LifecycleEventKind, PayloadEnvelope,
PlacementClass, ReceiptStatus, RequirementLevel, SCHEMA_VERSION,
};
const MAX_STDIN_BYTES: u64 = 16 * 1024 * 1024;
fn main() -> ExitCode {
let behavior = std::env::args().nth(1).unwrap_or_else(|| "ok".into());
if behavior == "hang" {
std::thread::sleep(std::time::Duration::from_secs(30));
return ExitCode::SUCCESS;
}
if behavior == "nonzero" {
eprintln!("fake ccd client: simulated transport failure");
return ExitCode::from(7);
}
if behavior == "exit_zero_no_read" {
return ExitCode::SUCCESS;
}
if behavior == "huge_stdout" {
let chunk = vec![b'x'; 1024 * 1024];
for _ in 0..17 {
if std::io::stdout().write_all(&chunk).is_err() {
return ExitCode::from(4);
}
}
return ExitCode::SUCCESS;
}
let mut buf = Vec::new();
if let Err(e) = std::io::stdin()
.take(MAX_STDIN_BYTES + 1)
.read_to_end(&mut buf)
{
eprintln!("fake ccd client: stdin read failed: {e}");
return ExitCode::from(1);
}
if buf.len() as u64 > MAX_STDIN_BYTES {
eprintln!("fake ccd client: stdin exceeds {MAX_STDIN_BYTES} bytes");
return ExitCode::from(1);
}
if behavior == "malformed" {
let _ = std::io::stdout().write_all(b"not json at all\n");
return ExitCode::SUCCESS;
}
let envelope: DispatchEnvelope = match serde_json::from_slice(&buf) {
Ok(e) => e,
Err(e) => {
eprintln!("fake ccd client: could not parse dispatch envelope: {e}");
return ExitCode::from(2);
}
};
let request = envelope.request;
let payloads = envelope.payloads;
if behavior == "hold_stdout_open" {
let _ = Command::new("sh").arg("-c").arg("sleep 30").spawn();
}
let response = match request.event {
LifecycleEventKind::FrameOpening => {
let mut resp = CallbackResponse::ok(ReceiptStatus::Delivered);
let (body, kind) = match payloads.first() {
Some(p) => (
p.body
.clone()
.unwrap_or_else(|| "hello from fake ccd".into()),
p.payload_kind.clone(),
),
None => ("hello from fake ccd".into(), "ccd.instruction_frame".into()),
};
let body_size = body.len() as u64;
resp.client_payloads.push(PayloadEnvelope {
schema_version: SCHEMA_VERSION.to_string(),
payload_id: "pay-fake-ccd-1".into(),
client_id: "ccd".into(),
payload_kind: kind,
format: "client-defined".into(),
content_encoding: "utf8".into(),
body: Some(body),
body_ref: None,
byte_size: body_size,
content_digest: None,
acceptable_placements: vec![AcceptablePlacement {
placement: PlacementClass::PrePromptFrame,
requirement: RequirementLevel::Preferred,
}],
idempotency_key: request.idempotency_key.clone(),
expires_at_epoch_s: None,
redaction: None,
metadata: serde_json::Map::new(),
});
resp
}
_ => CallbackResponse::ok(ReceiptStatus::Delivered),
};
let bytes = match serde_json::to_vec(&response) {
Ok(b) => b,
Err(e) => {
eprintln!("fake ccd client: could not serialize response: {e}");
return ExitCode::from(3);
}
};
if let Err(e) = std::io::stdout().write_all(&bytes) {
eprintln!("fake ccd client: stdout write failed: {e}");
return ExitCode::from(4);
}
ExitCode::SUCCESS
}