use super::{BearerMethod, ResourceMetadata, ResourceUri, ResourceUriError, WELL_KNOWN};
use crate::domain::ProtocolVersion;
use crate::domain::mcp::authorization::authorization_model;
type TestError = ResourceUriError;
fn canonical(input: &str) -> Option<String> {
ResourceUri::new(input)
.ok()
.map(|uri| uri.as_str().to_owned())
}
#[test]
fn a_trailing_slash_names_the_same_resource() {
for (bare, slashed) in [
("https://example.com/mcp", "https://example.com/mcp/"),
("https://example.com", "https://example.com/"),
("https://example.com/", "https://example.com"),
("https://example.com/a/b", "https://example.com/a/b/"),
] {
assert_eq!(
canonical(bare),
canonical(slashed),
"{bare} and {slashed} must be one resource",
);
}
}
#[test]
fn only_one_trailing_slash_is_dropped() {
assert_eq!(
canonical("https://example.com/mcp//"),
Some("https://example.com/mcp/".to_owned()),
"a doubled trailing slash is a real path",
);
}
#[test]
fn the_scheme_is_folded_but_the_host_is_not() {
assert_eq!(
canonical("HTTPS://example.com/mcp"),
Some("https://example.com/mcp".to_owned()),
);
assert_eq!(
canonical("HtTpS://EXAMPLE.COM/mcp"),
Some("https://EXAMPLE.COM/mcp".to_owned()),
"the host must not be case-folded",
);
}
#[test]
fn a_default_port_is_not_part_of_the_resource() {
for (input, expected) in [
("https://example.com:443/mcp", "https://example.com/mcp"),
("http://example.com:80/mcp", "http://example.com/mcp"),
("HTTPS://example.com:443/mcp", "https://example.com/mcp"),
] {
assert_eq!(canonical(input), Some(expected.to_owned()), "{input}");
}
}
#[test]
fn a_non_default_port_is_part_of_the_resource() {
for input in [
"https://example.com:8443/mcp",
"http://example.com:8080/mcp",
"https://example.com:80/mcp",
] {
assert!(
canonical(input).is_some_and(|uri| uri.contains(':')),
"{input} lost its port",
);
}
assert_ne!(
canonical("https://example.com:8443/mcp"),
canonical("https://example.com:8444/mcp"),
"two ports are two resources",
);
}
#[test]
fn an_ipv6_literal_survives_intact() {
assert_eq!(
canonical("https://[::1]:8443/mcp"),
Some("https://[::1]:8443/mcp".to_owned()),
"a non-default port beside a literal is kept",
);
assert_eq!(
canonical("https://[::1]/mcp"),
Some("https://[::1]/mcp".to_owned()),
);
assert_eq!(
canonical("https://[::1]:443/mcp"),
Some("https://[::1]/mcp".to_owned()),
"a default port beside a literal is still dropped",
);
}
#[test]
fn a_relative_identifier_is_refused() {
for input in [
"",
" ",
"example.com/mcp",
"/mcp",
"://example.com",
"/ /mcp",
] {
assert!(
ResourceUri::new(input).is_err(),
"{input:?} should not parse as a resource identifier",
);
}
}
#[test]
fn the_metadata_path_is_the_resource_path_appended() -> Result<(), TestError> {
for (resource, expected) in [
("https://example.com", WELL_KNOWN),
(
"https://example.com/mcp",
"/.well-known/oauth-protected-resource/mcp",
),
(
"https://example.com/a/b",
"/.well-known/oauth-protected-resource/a/b",
),
] {
let uri = ResourceUri::new(resource)?;
assert_eq!(uri.metadata_path(), expected, "{resource}");
}
Ok(())
}
#[test]
fn the_metadata_url_is_under_the_origin_not_under_the_resource() -> Result<(), TestError> {
let uri = ResourceUri::new("https://example.com:8443/a/mcp")?;
assert_eq!(
uri.metadata_url()?,
"https://example.com:8443/.well-known/oauth-protected-resource/a/mcp",
);
Ok(())
}
#[test]
fn the_challenge_points_at_the_metadata_document() -> Result<(), TestError> {
let resource = ResourceUri::new("https://example.com/mcp")?;
assert_eq!(
ResourceMetadata::new(resource).challenge()?,
"Bearer resource_metadata=\"https://example.com/.well-known/oauth-protected-resource/mcp\"",
);
Ok(())
}
#[test]
fn the_challenge_quotes_its_url() -> Result<(), TestError> {
let resource = ResourceUri::new("https://example.com/mcp")?;
let challenge = ResourceMetadata::new(resource).challenge()?;
assert!(challenge.starts_with("Bearer "));
assert!(challenge.contains("resource_metadata=\""));
assert!(challenge.ends_with('"'));
Ok(())
}
#[test]
fn a_metadata_document_defaults_to_the_header_mechanism() -> Result<(), TestError> {
let resource = ResourceUri::new("https://example.com")?;
let metadata = ResourceMetadata::new(resource);
assert_eq!(metadata.bearer_methods_supported(), &[BearerMethod::Header]);
assert_eq!(BearerMethod::Header.as_str(), "header");
Ok(())
}
#[test]
fn a_metadata_document_starts_with_only_its_required_field() -> Result<(), TestError> {
let resource = ResourceUri::new("https://example.com/mcp")?;
let metadata = ResourceMetadata::new(resource);
assert!(metadata.authorization_servers().is_empty());
assert!(metadata.scopes_supported().is_empty());
Ok(())
}
#[test]
fn the_document_builds_by_chaining() -> Result<(), TestError> {
let resource = ResourceUri::new("https://example.com/mcp")?;
let metadata = ResourceMetadata::new(resource)
.with_name("Example")
.with_authorization_server("https://auth.example.com")
.with_scope("mcp:tools");
assert_eq!(metadata.authorization_servers().len(), 1);
assert_eq!(metadata.scopes_supported(), &["mcp:tools".into()]);
Ok(())
}
#[test]
fn only_revisions_that_publish_metadata_are_eligible_to() {
for version in ProtocolVersion::KNOWN {
let publishes = authorization_model(version).protected_resource_metadata;
assert_eq!(
publishes,
version >= ProtocolVersion::V2025_06_18,
"{version} disagrees with the version table",
);
}
}
#[test]
fn from_parts_joins_without_doubling_slashes() -> Result<(), TestError> {
for (origin, path, expected) in [
("https://example.com/", "/mcp", "https://example.com/mcp"),
("https://example.com", "/mcp", "https://example.com/mcp"),
("https://example.com/", "mcp", "https://example.com/mcp"),
(
"https://example.com:8443",
"/a/b",
"https://example.com:8443/a/b",
),
("https://example.com", "/", "https://example.com"),
("https://example.com/", "", "https://example.com"),
] {
let uri = ResourceUri::from_parts(origin, path)?;
assert_eq!(uri.as_str(), expected, "{origin} + {path}");
}
Ok(())
}
#[test]
fn equality_means_canonically_identical_not_merely_similar() -> Result<(), TestError> {
let slashed = ResourceUri::new("https://example.com/mcp/")?;
let plain = ResourceUri::new("https://example.com/mcp")?;
assert_eq!(slashed, plain);
assert_eq!(slashed.as_str(), plain.as_str());
let upper_host = ResourceUri::new("https://EXAMPLE.com/mcp")?;
assert_ne!(slashed, upper_host);
Ok(())
}