feat: harden community production foundation through story 1.5
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
use crank_core::{CorrelationContext, RequestId, TraceContext, TraceId};
|
||||
use uuid::Version;
|
||||
|
||||
const VALID_TRACEPARENT: &str = "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01";
|
||||
|
||||
#[test]
|
||||
fn generated_identities_are_distinct_and_canonical() {
|
||||
let context = CorrelationContext::generate();
|
||||
|
||||
assert_eq!(
|
||||
uuid::Uuid::parse_str(context.request_id().as_str())
|
||||
.unwrap()
|
||||
.get_version(),
|
||||
Some(Version::SortRand)
|
||||
);
|
||||
assert_eq!(context.trace_id().as_str().len(), 32);
|
||||
assert!(
|
||||
context
|
||||
.trace_id()
|
||||
.as_str()
|
||||
.bytes()
|
||||
.all(|byte| byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase())
|
||||
);
|
||||
assert_ne!(
|
||||
context.request_id().as_str().replace('-', ""),
|
||||
context.trace_id().as_str()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_id_preserves_one_valid_opaque_value_and_replaces_invalid_values() {
|
||||
assert_eq!(
|
||||
RequestId::resolve(Some("gateway-request-42")).as_str(),
|
||||
"gateway-request-42"
|
||||
);
|
||||
for invalid in ["", "bad value", "bad,value", "bad;value"] {
|
||||
let replacement = RequestId::resolve(Some(invalid));
|
||||
assert_ne!(replacement.as_str(), invalid);
|
||||
assert_eq!(
|
||||
uuid::Uuid::parse_str(replacement.as_str())
|
||||
.unwrap()
|
||||
.get_version(),
|
||||
Some(Version::SortRand)
|
||||
);
|
||||
}
|
||||
assert!(RequestId::is_valid(&"a".repeat(RequestId::MAX_LEN)));
|
||||
assert!(!RequestId::is_valid(&"a".repeat(RequestId::MAX_LEN + 1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn traceparent_parser_is_strict_and_never_accepts_zero_ids() {
|
||||
let context = TraceContext::parse(VALID_TRACEPARENT).unwrap();
|
||||
assert_eq!(
|
||||
context.trace_id().as_str(),
|
||||
"0af7651916cd43dd8448eb211c80319c"
|
||||
);
|
||||
assert_eq!(context.traceparent(), VALID_TRACEPARENT);
|
||||
|
||||
for invalid in [
|
||||
"00-00000000000000000000000000000000-b7ad6b7169203331-01",
|
||||
"00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01",
|
||||
"00-0AF7651916CD43DD8448EB211C80319C-b7ad6b7169203331-01",
|
||||
"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-0z",
|
||||
"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-02",
|
||||
"ff-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
|
||||
"canary-invalid-traceparent",
|
||||
] {
|
||||
assert!(TraceContext::parse(invalid).is_err(), "accepted {invalid}");
|
||||
}
|
||||
assert!(TraceId::parse("00000000000000000000000000000000").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn durable_parent_envelope_roundtrips_without_conflating_ids() {
|
||||
let context = CorrelationContext::new(
|
||||
RequestId::resolve(Some("request-opaque-1")),
|
||||
TraceContext::parse(VALID_TRACEPARENT).unwrap(),
|
||||
);
|
||||
let encoded = serde_json::to_vec(&context).unwrap();
|
||||
let decoded: CorrelationContext = serde_json::from_slice(&encoded).unwrap();
|
||||
|
||||
assert_eq!(decoded, context);
|
||||
assert_eq!(decoded.request_id().as_str(), "request-opaque-1");
|
||||
assert_eq!(
|
||||
decoded.trace_id().as_str(),
|
||||
"0af7651916cd43dd8448eb211c80319c"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn durable_parent_envelope_rejects_invalid_or_inconsistent_identities() {
|
||||
for candidate in [
|
||||
serde_json::json!({
|
||||
"request_id": "bad request",
|
||||
"trace_context": {
|
||||
"trace_id": "0af7651916cd43dd8448eb211c80319c",
|
||||
"traceparent": VALID_TRACEPARENT,
|
||||
}
|
||||
}),
|
||||
serde_json::json!({
|
||||
"request_id": "request-1",
|
||||
"trace_context": {
|
||||
"trace_id": "00000000000000000000000000000000",
|
||||
"traceparent": VALID_TRACEPARENT,
|
||||
}
|
||||
}),
|
||||
serde_json::json!({
|
||||
"request_id": "request-1",
|
||||
"trace_context": {
|
||||
"trace_id": "1af7651916cd43dd8448eb211c80319c",
|
||||
"traceparent": VALID_TRACEPARENT,
|
||||
}
|
||||
}),
|
||||
] {
|
||||
assert!(serde_json::from_value::<CorrelationContext>(candidate).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn caller_state_and_baggage_budgets_are_closed_and_bounded() {
|
||||
assert!(TraceContext::tracestate_within_budget("vendor=value"));
|
||||
assert!(!TraceContext::tracestate_within_budget(&"x".repeat(513)));
|
||||
assert!(!TraceContext::tracestate_within_budget(
|
||||
&std::iter::repeat_n("a=b", 33).collect::<Vec<_>>().join(",")
|
||||
));
|
||||
assert!(TraceContext::baggage_within_budget("key=value"));
|
||||
assert!(!TraceContext::baggage_within_budget(&"x".repeat(8_193)));
|
||||
assert!(!TraceContext::baggage_within_budget(
|
||||
&std::iter::repeat_n("a=b", 65).collect::<Vec<_>>().join(",")
|
||||
));
|
||||
}
|
||||
Reference in New Issue
Block a user