Skip to content

Commit e7b779a

Browse files
Copilotstephentoub
andauthored
Add CloneResourceMetadataClonesAllProperties test using public reflection (#1343)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> Co-authored-by: Stephen Toub <stoub@microsoft.com>
1 parent 774a1db commit e7b779a

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

  • tests/ModelContextProtocol.AspNetCore.Tests/OAuth

tests/ModelContextProtocol.AspNetCore.Tests/OAuth/AuthTests.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,101 @@ public async Task ResourceMetadata_DoesNotAddTrailingSlash()
893893
transport, loggerFactory: LoggerFactory, cancellationToken: TestContext.Current.CancellationToken);
894894
}
895895

896+
[Fact]
897+
public void CloneResourceMetadataClonesAllProperties()
898+
{
899+
var propertyNames = typeof(ProtectedResourceMetadata).GetProperties().Select(property => property.Name).ToList();
900+
901+
// Set metadata properties to non-default values to verify they're copied.
902+
var metadata = new ProtectedResourceMetadata
903+
{
904+
Resource = "https://example.com/resource",
905+
AuthorizationServers = ["https://auth1.example.com", "https://auth2.example.com"],
906+
BearerMethodsSupported = ["header", "body", "query"],
907+
ScopesSupported = ["read", "write", "admin"],
908+
JwksUri = "https://example.com/.well-known/jwks.json",
909+
ResourceSigningAlgValuesSupported = ["RS256", "ES256"],
910+
ResourceName = "Test Resource",
911+
ResourceDocumentation = "https://docs.example.com",
912+
ResourcePolicyUri = "https://example.com/policy",
913+
ResourceTosUri = "https://example.com/terms",
914+
TlsClientCertificateBoundAccessTokens = true,
915+
AuthorizationDetailsTypesSupported = ["payment_initiation", "account_information"],
916+
DpopSigningAlgValuesSupported = ["RS256", "PS256"],
917+
DpopBoundAccessTokensRequired = true
918+
};
919+
920+
var clonedMetadata = metadata.Clone();
921+
922+
// Ensure the cloned metadata is not the same instance
923+
Assert.NotSame(metadata, clonedMetadata);
924+
925+
// Verify Resource property
926+
Assert.Equal(metadata.Resource, clonedMetadata.Resource);
927+
Assert.True(propertyNames.Remove(nameof(metadata.Resource)));
928+
929+
// Verify AuthorizationServers list is cloned and contains the same values
930+
Assert.NotSame(metadata.AuthorizationServers, clonedMetadata.AuthorizationServers);
931+
Assert.Equal(metadata.AuthorizationServers, clonedMetadata.AuthorizationServers);
932+
Assert.True(propertyNames.Remove(nameof(metadata.AuthorizationServers)));
933+
934+
// Verify BearerMethodsSupported list is cloned and contains the same values
935+
Assert.NotSame(metadata.BearerMethodsSupported, clonedMetadata.BearerMethodsSupported);
936+
Assert.Equal(metadata.BearerMethodsSupported, clonedMetadata.BearerMethodsSupported);
937+
Assert.True(propertyNames.Remove(nameof(metadata.BearerMethodsSupported)));
938+
939+
// Verify ScopesSupported list is cloned and contains the same values
940+
Assert.NotSame(metadata.ScopesSupported, clonedMetadata.ScopesSupported);
941+
Assert.Equal(metadata.ScopesSupported, clonedMetadata.ScopesSupported);
942+
Assert.True(propertyNames.Remove(nameof(metadata.ScopesSupported)));
943+
944+
// Verify JwksUri property
945+
Assert.Equal(metadata.JwksUri, clonedMetadata.JwksUri);
946+
Assert.True(propertyNames.Remove(nameof(metadata.JwksUri)));
947+
948+
// Verify ResourceSigningAlgValuesSupported list is cloned (nullable list)
949+
Assert.NotSame(metadata.ResourceSigningAlgValuesSupported, clonedMetadata.ResourceSigningAlgValuesSupported);
950+
Assert.Equal(metadata.ResourceSigningAlgValuesSupported, clonedMetadata.ResourceSigningAlgValuesSupported);
951+
Assert.True(propertyNames.Remove(nameof(metadata.ResourceSigningAlgValuesSupported)));
952+
953+
// Verify ResourceName property
954+
Assert.Equal(metadata.ResourceName, clonedMetadata.ResourceName);
955+
Assert.True(propertyNames.Remove(nameof(metadata.ResourceName)));
956+
957+
// Verify ResourceDocumentation property
958+
Assert.Equal(metadata.ResourceDocumentation, clonedMetadata.ResourceDocumentation);
959+
Assert.True(propertyNames.Remove(nameof(metadata.ResourceDocumentation)));
960+
961+
// Verify ResourcePolicyUri property
962+
Assert.Equal(metadata.ResourcePolicyUri, clonedMetadata.ResourcePolicyUri);
963+
Assert.True(propertyNames.Remove(nameof(metadata.ResourcePolicyUri)));
964+
965+
// Verify ResourceTosUri property
966+
Assert.Equal(metadata.ResourceTosUri, clonedMetadata.ResourceTosUri);
967+
Assert.True(propertyNames.Remove(nameof(metadata.ResourceTosUri)));
968+
969+
// Verify TlsClientCertificateBoundAccessTokens property
970+
Assert.Equal(metadata.TlsClientCertificateBoundAccessTokens, clonedMetadata.TlsClientCertificateBoundAccessTokens);
971+
Assert.True(propertyNames.Remove(nameof(metadata.TlsClientCertificateBoundAccessTokens)));
972+
973+
// Verify AuthorizationDetailsTypesSupported list is cloned (nullable list)
974+
Assert.NotSame(metadata.AuthorizationDetailsTypesSupported, clonedMetadata.AuthorizationDetailsTypesSupported);
975+
Assert.Equal(metadata.AuthorizationDetailsTypesSupported, clonedMetadata.AuthorizationDetailsTypesSupported);
976+
Assert.True(propertyNames.Remove(nameof(metadata.AuthorizationDetailsTypesSupported)));
977+
978+
// Verify DpopSigningAlgValuesSupported list is cloned (nullable list)
979+
Assert.NotSame(metadata.DpopSigningAlgValuesSupported, clonedMetadata.DpopSigningAlgValuesSupported);
980+
Assert.Equal(metadata.DpopSigningAlgValuesSupported, clonedMetadata.DpopSigningAlgValuesSupported);
981+
Assert.True(propertyNames.Remove(nameof(metadata.DpopSigningAlgValuesSupported)));
982+
983+
// Verify DpopBoundAccessTokensRequired property
984+
Assert.Equal(metadata.DpopBoundAccessTokensRequired, clonedMetadata.DpopBoundAccessTokensRequired);
985+
Assert.True(propertyNames.Remove(nameof(metadata.DpopBoundAccessTokensRequired)));
986+
987+
// Ensure we've checked every property. When new properties get added, we'll have to update this test along with the Clone implementation.
988+
Assert.Empty(propertyNames);
989+
}
990+
896991
[Fact]
897992
public async Task ResourceMetadata_PreservesExplicitTrailingSlash()
898993
{

0 commit comments

Comments
 (0)