use prost::Message;
use saddle::Input;
use serde::{Deserialize, Serialize};
#[derive(Input, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct InputRequest {
display_name: String,
rows: Vec<Vec<Option<String>>>,
choice: Choice,
missing: Option<String>,
}
#[derive(Input, Deserialize)]
#[serde(rename_all = "lowercase")]
enum Choice {
Left,
Right,
}
#[derive(Serialize)]
struct UnchangedResponse {
name: String,
}
#[derive(Clone, PartialEq, Message)]
struct UnchangedProto {
#[prost(string, tag = "1")]
name: String,
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
use saddle_admission::{ProcessLedger, ResourceConfig};
use std::{
future::Future,
task::{Context, Poll, Waker},
};
async fn handler(request: &InputRequest) {
let before = request.display_name.as_str();
let mut first = true;
std::future::poll_fn(move |_| {
if first {
first = false;
Poll::Pending
} else {
Poll::Ready(())
}
})
.await;
assert_eq!(before, "read\n中😀");
assert_eq!(request.rows[0][0].as_deref(), Some("a"));
assert!(request.rows[0][1].is_none());
assert!(request.missing.is_none());
assert!(matches!(request.choice, Choice::Right));
}
fn ledger() -> ProcessLedger {
let state = ProcessLedger::minimum_process_state_reserve(1).unwrap();
ProcessLedger::new(ResourceConfig {
managed_capacity: 32768,
entry_reserve: 64,
framework_reserve: 16384,
task_reserve: 8192,
process_state_reserve: state,
system_estimate: 64,
safety_margin: 64,
process_limit: 32768 + 64 + 16384 + 8192 + state + 64 + 64,
max_active_requests: 1,
})
.unwrap()
}
#[test]
fn generated_codec_borrows_across_await_and_cancel() {
for cancel in [false, true] {
let ledger = ledger();
let request=ledger.try_envelope(32768,8192,|memory| {
let raw=memory.try_bytes(br#"{"displayName":"read\n\u4e2d\ud83d\ude00","rows":[["a",null]],"choice":"right"}"#).unwrap();
let document=memory.decode_input(&raw).unwrap();
let input=memory.read_only_input::<InputRequest>(document.root()).unwrap();
drop(document); drop(raw);
async move { handler(input.get()).await; }
}).unwrap();
let mut request = Box::pin(request);
let mut cx = Context::from_waker(Waker::noop());
assert!(request.as_mut().poll(&mut cx).is_pending());
assert!(ledger.snapshot().charged > 0);
if !cancel {
assert!(matches!(request.as_mut().poll(&mut cx), Poll::Ready(Ok(_))));
}
drop(request);
assert_eq!(ledger.snapshot().charged, 0);
assert_eq!(ledger.snapshot().active_accounts, 0);
assert!(ledger.snapshot().healthy);
ledger.try_shutdown().unwrap();
}
}
#[test]
fn managed_boundary_to_typed_borrow_and_cancel() {
use saddle_boundary::ingress::*;
for cancel in [false,true] {
let ledger=ledger();
let identity=IngressIdentity::new("request","call",1_800_000_000_000).unwrap();
let adapter=ProfuseGwListenerAdapter::new("app").unwrap();
let request=ledger.try_envelope(32768,8192,|memory| {
let source=br#"HEAD{"target":{"app":"app","interfaceId":"route"},"profuseGwContext":{"userInfo":{"userId":"u"},"traceInfo":{"rpcId":"0"},"ldcInfo":{"zone":"z","idc":"i","env":"test"}},"requestData":{"displayName":"read\n\u4e2d\ud83d\ude00","rows":[["a",null]],"choice":"right"}}"#;
let raw=memory.try_bytes(source).unwrap();
let document=memory.decode_input_range(&raw,4..raw.len()).unwrap();
let accepted=adapter.accept_managed(METHOD,PATH,MEDIA_TYPE,&identity,&raw.as_slice()[4..],document).unwrap();
assert_eq!(accepted.trace_id,"saddle-request");
assert!(matches!(&accepted.request_data,AcceptedRequestData::Managed(_)));
drop(raw);
let (input,context)=saddle::__private::decode_accepted_profusegw::<InputRequest>(accepted).unwrap();
assert_eq!(context.trace_info().trace_id(),"saddle-request");
async move { handler(input.get()).await; }
}).unwrap();
let mut request=Box::pin(request);
let mut cx=Context::from_waker(Waker::noop());
assert!(request.as_mut().poll(&mut cx).is_pending());
assert!(ledger.snapshot().charged>0);
if !cancel { assert!(matches!(request.as_mut().poll(&mut cx),Poll::Ready(Ok(_)))); }
drop(request);
assert_eq!(ledger.snapshot().charged,0);
assert_eq!(ledger.snapshot().active_accounts,0);
assert!(ledger.snapshot().healthy);
ledger.try_shutdown().unwrap();
}
}
}