use super::super::super::UriInner;
use super::super::super::owned::OwnedUriRef;
use super::parse_graceful;
use crate::Protocol;
use crate::address::{Authority, Domain, Host, HostWithOptPort, UserInfo};
use crate::uri::{Fragment, Query, Uri};
use rama_core::bytes::BytesMut;
#[test]
fn lazy_round_trip() {
for input in [
"/",
"/foo",
"/foo/bar",
"/foo?bar=1",
"/foo?bar=1#section",
"/path#frag",
"/?",
"/#",
"https://example.com/",
"https://example.com/path?q=1#f",
"http://user:pass@example.com:8080/p",
"https://[::1]:443/",
"urn:isbn:0451450523",
"mailto:user@example.com",
"data:text/plain",
"http://example.com",
] {
let uri: Uri = parse_graceful(input).unwrap();
assert_eq!(uri.to_string(), input, "round-trip mismatch");
}
}
#[test]
fn asterisk_displays_as_star() {
let uri: Uri = parse_graceful("*").unwrap();
assert_eq!(uri.to_string(), "*");
}
fn owned(o: OwnedUriRef) -> Uri {
Uri {
inner: UriInner::Owned(crate::std::sync::Arc::new(o)),
}
}
fn http_authority(host: &str, port: Option<u16>, userinfo: Option<&str>) -> Authority {
Authority {
user_info: userinfo.map(|s| UserInfo::try_from(s).unwrap()),
address: HostWithOptPort {
host: Host::Name(Domain::try_from(host).unwrap()),
port: port.into(),
},
}
}
#[test]
fn owned_origin_form_path_only() {
let uri = owned(OwnedUriRef {
path: BytesMut::from(&b"/foo"[..]),
..Default::default()
});
assert_eq!(uri.to_string(), "/foo");
}
#[test]
fn owned_origin_form_with_query_and_fragment() {
let uri = owned(OwnedUriRef {
path: BytesMut::from(&b"/p"[..]),
query: Some(Query {
bytes: BytesMut::from(&b"a=1"[..]),
}),
fragment: Some(Fragment {
bytes: BytesMut::from(&b"sec"[..]),
}),
..Default::default()
});
assert_eq!(uri.to_string(), "/p?a=1#sec");
}
#[test]
fn owned_absolute_form_full() {
let uri = owned(OwnedUriRef {
scheme: Some(Protocol::HTTPS),
authority: Some(http_authority("example.com", Some(8443), Some("u:p"))),
path: BytesMut::from(&b"/x"[..]),
query: Some(Query {
bytes: BytesMut::from(&b"q=1"[..]),
}),
fragment: None,
});
assert_eq!(uri.to_string(), "https://u:p@example.com:8443/x?q=1");
}
#[test]
fn owned_opaque_form_scheme_only() {
let uri = owned(OwnedUriRef {
scheme: Some(Protocol::from_static("urn")),
authority: None,
path: BytesMut::from(&b"isbn:0"[..]),
query: None,
fragment: None,
});
assert_eq!(uri.to_string(), "urn:isbn:0");
}
#[test]
fn owned_empty_query_distinguished_from_no_query() {
let with_q = owned(OwnedUriRef {
path: BytesMut::from(&b"/p"[..]),
query: Some(Query {
bytes: BytesMut::new(),
}),
..Default::default()
});
let no_q = owned(OwnedUriRef {
path: BytesMut::from(&b"/p"[..]),
query: None,
..Default::default()
});
assert_eq!(with_q.to_string(), "/p?");
assert_eq!(no_q.to_string(), "/p");
}
#[test]
fn owned_empty_fragment_distinguished_from_no_fragment() {
let with_f = owned(OwnedUriRef {
path: BytesMut::from(&b"/p"[..]),
fragment: Some(Fragment {
bytes: BytesMut::new(),
}),
..Default::default()
});
let no_f = owned(OwnedUriRef {
path: BytesMut::from(&b"/p"[..]),
fragment: None,
..Default::default()
});
assert_eq!(with_f.to_string(), "/p#");
assert_eq!(no_f.to_string(), "/p");
}
#[test]
fn debug_redacts_lazy_uri_password() {
let u = parse_graceful("http://alice:secret@example.com/p").unwrap();
let s = format!("{u:?}");
assert!(!s.contains("secret"), "debug leaked password: {s}");
assert!(s.contains("alice"));
assert!(s.contains("***"));
assert!(s.contains("example.com"));
}
#[test]
fn debug_preserves_userinfo_with_no_password() {
let u = parse_graceful("http://alice@example.com/p").unwrap();
let s = format!("{u:?}");
assert!(s.contains("alice@"), "user-only userinfo dropped: {s}");
assert!(!s.contains("***"), "no password → no redaction marker: {s}");
}
#[test]
fn debug_omits_userinfo_section_when_absent() {
let u = parse_graceful("http://example.com/p").unwrap();
let s = format!("{u:?}");
assert!(!s.contains('@'));
assert!(!s.contains("***"));
assert!(s.contains("example.com"));
}
#[test]
fn debug_redacts_owned_uri_password() {
let mut u = parse_graceful("http://alice:secret@example.com/p").unwrap();
u.set_path("/new");
let s = format!("{u:?}");
assert!(!s.contains("secret"), "debug leaked password (Owned): {s}");
assert!(s.contains("alice"));
assert!(s.contains("***"));
}
#[test]
fn display_remains_wire_faithful_with_userinfo() {
let u = parse_graceful("http://alice:secret@example.com/p").unwrap();
assert_eq!(u.to_string(), "http://alice:secret@example.com/p");
}
#[test]
fn debug_wraps_in_uri_marker() {
let u = parse_graceful("http://example.com/").unwrap();
assert_eq!(format!("{u:?}"), r#"Uri("http://example.com/")"#);
}
#[test]
fn owned_ipv6_no_port_keeps_brackets() {
let mut u = parse_graceful("http://[::1]/path").unwrap();
u.set_path("/other"); assert_eq!(u.to_string(), "http://[::1]/other");
}
#[test]
fn owned_ipv6_with_port_keeps_brackets() {
let mut u = parse_graceful("http://[2001:db8::1]:8080/p").unwrap();
u.set_path("/q");
assert_eq!(u.to_string(), "http://[2001:db8::1]:8080/q");
}
#[test]
fn owned_ipv6_canonicalize_keeps_brackets() {
let u = parse_graceful("https://[::1]:443/p").unwrap();
let canonical = u.canonicalize();
assert_eq!(canonical.to_string(), "https://[::1]/p");
}
#[test]
fn owned_ipv6_userinfo_brackets_correctly() {
let mut u = parse_graceful("http://alice@[::1]/p").unwrap();
u.set_path("/q");
assert_eq!(u.to_string(), "http://alice@[::1]/q");
}