-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Fix MVC Core tests for CoreCLR GetCustomAttributes consistency #62872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes two test methods in the MVC Core test suite to align with CoreCLR's corrected behavior for typeof(object).GetCustomAttributes()
. Previously, CoreCLR had inconsistent behavior where GetCustomAttributes(inherit: true)
and GetCustomAttributes(inherit: false)
returned different numbers of attributes for the object
type. The fix ensures both calls consistently return all 5 pseudo-attributes.
- Updates test assertions to expect 5 attributes instead of 1
- Adds explicit checks for all pseudo-attributes on the
object
type - Ensures ASP.NET Core tests pass with the fixed CoreCLR runtime
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
File | Description |
---|---|
ModelAttributesTest.cs | Updates GetAttributesForParameter_NoAttributes test to expect all 5 pseudo-attributes |
DefaultModelMetadataProviderTest.cs | Updates GetMetadataForParameter_SuppliesEmptyAttributes_WhenParameterHasNoAttributes test to expect all 5 pseudo-attributes |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == Type.GetType("System.Runtime.CompilerServices.NullableContextAttribute")); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ClassInterfaceAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ComVisibleAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.Serialization.TypeForwardedFromAttribute)); |
Copilot uses AI. Check for mistakes.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(NullableContextAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(ClassInterfaceAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(ComVisibleAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(TypeForwardedFromAttribute)); |
Copilot uses AI. Check for mistakes.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(NullableContextAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(ClassInterfaceAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(ComVisibleAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(TypeForwardedFromAttribute)); |
Copilot uses AI. Check for mistakes.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == Type.GetType("System.Runtime.CompilerServices.NullableContextAttribute")); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ClassInterfaceAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ComVisibleAttribute)); | |
Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.CompilerServices.TypeForwardedFromAttribute)); |
Copilot uses AI. Check for mistakes.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is NullableContextAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is ClassInterfaceAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is ComVisibleAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is TypeForwardedFromAttribute); |
Copilot uses AI. Check for mistakes.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType() == typeof(NullableContextAttribute)); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType() == typeof(ClassInterfaceAttribute)); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType() == typeof(ComVisibleAttribute)); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType() == typeof(TypeForwardedFromAttribute)); |
Copilot uses AI. Check for mistakes.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is NullableContextAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is ClassInterfaceAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is ComVisibleAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is TypeForwardedFromAttribute); |
Copilot uses AI. Check for mistakes.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | ||
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute"); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is System.Runtime.CompilerServices.NullableContextAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is System.Runtime.InteropServices.ClassInterfaceAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is System.Runtime.InteropServices.ComVisibleAttribute); | |
Assert.Contains(defaultMetadata.Attributes.Attributes, attr => attr is System.Runtime.CompilerServices.TypeForwardedFromAttribute); |
Copilot uses AI. Check for mistakes.
// Not exactly "no attributes" due to SerializableAttribute on object. | ||
Assert.IsType<SerializableAttribute>(Assert.Single(defaultMetadata.Attributes.Attributes)); | ||
// Not exactly "no attributes" due to pseudo-attributes on object. | ||
// After CoreCLR consistency fix, object.GetCustomAttributes() returns all pseudo-attributes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this test be deleted instead? It does not make sense for ASP.NET to test internal implementation details of CoreCLR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but looking at the name of the testcase
GetMetadataForParameter_SuppliesEmptyAttributes_WhenParameterHasNoAttributes
and GetAttributesForParameter_NoAttributes
the intent seems to be testing that a parameter with "no attributes" behaves correctly, so in this situation we either could just remove this testscase or Change the test to just verify that ParameterAttributes
is empty (thats what I feel is the actual ASP.NET Core concern)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way sounds good to me.
…assertions Signed-off-by: Medha Tiwari <medhavns1@gmail.com>
src/Mvc/Mvc.Core/test/ModelBinding/Metadata/DefaultModelMetadataProviderTest.cs
Outdated
Show resolved
Hide resolved
…taProviderTest.cs
src/Mvc/Mvc.Core/test/ModelBinding/Metadata/ModelAttributesTest.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@Minimal-APIs PTLA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM -- thanks!
Fix MVC Core tests for CoreCLR GetCustomAttributes consistency
here
Fix MVC Core tests for CoreCLR GetCustomAttributes consistency
Description
This PR updates two test methods in the MVC Core test suite that were expecting CoreCLR's old inconsistent behavior for
typeof(object).GetCustomAttributes()
.Background:
CoreCLR had a bug where
typeof(object).GetCustomAttributes(inherit: true)
andtypeof(object).GetCustomAttributes(inherit: false)
returned different numbers of attributes (1 vs 5). This inconsistency caused ASP.NET Core tests to fail when running on Mono, which correctly returned 5 attributes for both cases.Changes:
Updates two test methods that were written expecting the old buggy behavior:
ModelAttributesTest.GetAttributesForParameter_NoAttributes
DefaultModelMetadataProviderTest.GetMetadataForParameter_SuppliesEmptyAttributes_WhenParameterHasNoAttributes
Both tests now correctly expect 5 attributes (SerializableAttribute, NullableContextAttribute, ClassInterfaceAttribute, ComVisibleAttribute, TypeForwardedFromAttribute) instead of just 1.
Impact:
Related to dotnet/runtime#117864