/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Symbols/Metadata/PE/LoadingEvents.cs
619 строк
24 KB
Jason Malinowski
Switch code that was using Assert.True/False as a replacement for .Fail
21 апр 2026, 23:28
21 апр 2026, 23:28
3bf59ba
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using System; using System.Linq; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Metadata.PE { public class LoadingEvents : CSharpTestBase { [Fact] public void LoadNonGenericEvents() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("NonGeneric"); CheckInstanceAndStaticEvents(@class, "System.Action"); } [Fact] public void LoadGenericEvents() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("Generic"); CheckInstanceAndStaticEvents(@class, "System.Action<T>"); } [Fact] public void LoadClosedGenericEvents() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("ClosedGeneric"); CheckInstanceAndStaticEvents(@class, "System.Action<System.Int32>"); } private static void CheckInstanceAndStaticEvents(NamedTypeSymbol @class, string eventTypeDisplayString) { var instanceEvent = @class.GetMember<EventSymbol>("InstanceEvent"); Assert.Equal(SymbolKind.Event, instanceEvent.Kind); Assert.False(instanceEvent.IsStatic); Assert.Equal(eventTypeDisplayString, instanceEvent.Type.ToTestDisplayString()); CheckAccessorShape(instanceEvent.AddMethod, instanceEvent); CheckAccessorShape(instanceEvent.RemoveMethod, instanceEvent); var staticEvent = @class.GetMember<EventSymbol>("StaticEvent"); Assert.Equal(SymbolKind.Event, staticEvent.Kind); Assert.True(staticEvent.IsStatic); Assert.Equal(eventTypeDisplayString, staticEvent.Type.ToTestDisplayString()); CheckAccessorShape(staticEvent.AddMethod, staticEvent); CheckAccessorShape(staticEvent.RemoveMethod, staticEvent); } private static void CheckAccessorShape(MethodSymbol accessor, EventSymbol @event) { Assert.Same(@event, accessor.AssociatedSymbol); switch (accessor.MethodKind) { case MethodKind.EventAdd: Assert.Same(@event.AddMethod, accessor); break; case MethodKind.EventRemove: Assert.Same(@event.RemoveMethod, accessor); break; default: Assert.Fail(string.Format("Accessor {0} has unexpected MethodKind {1}", accessor, accessor.MethodKind)); break; } Assert.Equal(@event.IsAbstract, accessor.IsAbstract); Assert.Equal(@event.IsOverride, @accessor.IsOverride); Assert.Equal(@event.IsVirtual, @accessor.IsVirtual); Assert.Equal(@event.IsSealed, @accessor.IsSealed); Assert.Equal(@event.IsExtern, @accessor.IsExtern); Assert.Equal(SpecialType.System_Void, accessor.ReturnType.SpecialType); Assert.Equal(@event.Type, accessor.Parameters.Single().Type); } [Fact] public void LoadSignatureMismatchEvents() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("SignatureMismatch"); var mismatchedAddEvent = @class.GetMember<EventSymbol>("AddMismatch"); var mismatchedRemoveEvent = @class.GetMember<EventSymbol>("RemoveMismatch"); Assert.NotEqual(mismatchedAddEvent.Type, mismatchedAddEvent.AddMethod.Parameters.Single().Type); Assert.True(mismatchedAddEvent.MustCallMethodsDirectly); Assert.NotEqual(mismatchedRemoveEvent.Type, mismatchedRemoveEvent.RemoveMethod.Parameters.Single().Type); Assert.True(mismatchedRemoveEvent.MustCallMethodsDirectly); } [Fact] public void LoadMissingParameterEvents() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("AccessorMissingParameter"); var noParamAddEvent = @class.GetMember<EventSymbol>("AddNoParam"); var noParamRemoveEvent = @class.GetMember<EventSymbol>("RemoveNoParam"); Assert.Equal(0, noParamAddEvent.AddMethod.Parameters.Length); Assert.True(noParamAddEvent.MustCallMethodsDirectly); Assert.Equal(0, noParamRemoveEvent.RemoveMethod.Parameters.Length); Assert.True(noParamRemoveEvent.MustCallMethodsDirectly); } [Fact] public void LoadNonDelegateEvent() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.Events, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @class = globalNamespace.GetMember<NamedTypeSymbol>("NonDelegateEvent"); var nonDelegateEvent = @class.GetMember<EventSymbol>("NonDelegate"); Assert.Equal(SpecialType.System_Int32, nonDelegateEvent.Type.SpecialType); } [Fact] public void TestExplicitImplementationSimple() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.ExplicitInterfaceImplementation.Events.CSharp, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @interface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Interface").Single(); Assert.Equal(TypeKind.Interface, @interface.TypeKind); var interfaceEvent = (EventSymbol)@interface.GetMembers("Event").Single(); var @class = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Class").Single(); Assert.Equal(TypeKind.Class, @class.TypeKind); Assert.True(@class.Interfaces().Contains(@interface)); var classEvent = (EventSymbol)@class.GetMembers("Interface.Event").Single(); var explicitImpl = classEvent.ExplicitInterfaceImplementations.Single(); Assert.Equal(interfaceEvent, explicitImpl); } [Fact] public void TestExplicitImplementationGeneric() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.ExplicitInterfaceImplementation.Events.CSharp, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @interface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("IGeneric").Single(); Assert.Equal(TypeKind.Interface, @interface.TypeKind); var interfaceEvent = (EventSymbol)@interface.GetMembers("Event").Single(); var @class = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Generic").Single(); Assert.Equal(TypeKind.Class, @class.TypeKind); var substitutedInterface = @class.Interfaces().Single(); Assert.Equal(@interface, substitutedInterface.ConstructedFrom); var substitutedInterfaceEvent = (EventSymbol)substitutedInterface.GetMembers("Event").Single(); Assert.Equal(interfaceEvent, substitutedInterfaceEvent.OriginalDefinition); var classEvent = (EventSymbol)@class.GetMembers("IGeneric<S>.Event").Single(); var explicitImpl = classEvent.ExplicitInterfaceImplementations.Single(); Assert.Equal(substitutedInterfaceEvent, explicitImpl); } [Fact] public void TestExplicitImplementationConstructed() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.ExplicitInterfaceImplementation.Events.CSharp, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var @interface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("IGeneric").Single(); Assert.Equal(TypeKind.Interface, @interface.TypeKind); var interfaceEvent = (EventSymbol)@interface.GetMembers("Event").Single(); var @class = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Constructed").Single(); Assert.Equal(TypeKind.Class, @class.TypeKind); var substitutedInterface = @class.Interfaces().Single(); Assert.Equal(@interface, substitutedInterface.ConstructedFrom); var substitutedInterfaceEvent = (EventSymbol)substitutedInterface.GetMembers("Event").Single(); Assert.Equal(interfaceEvent, substitutedInterfaceEvent.OriginalDefinition); var classEvent = (EventSymbol)@class.GetMembers("IGeneric<System.Int32>.Event").Single(); var explicitImpl = classEvent.ExplicitInterfaceImplementations.Single(); Assert.Equal(substitutedInterfaceEvent, explicitImpl); } /// <summary> /// A type def explicitly implements an interface, also a type def, but only /// indirectly, via a type ref. /// </summary> [Fact] public void TestExplicitImplementationDefRefDef() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.ExplicitInterfaceImplementation.Events.CSharp, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var defInterface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Interface").Single(); Assert.Equal(TypeKind.Interface, defInterface.TypeKind); var defInterfaceEvent = (EventSymbol)defInterface.GetMembers("Event").Single(); var refInterface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("IGenericInterface").Single(); Assert.Equal(TypeKind.Interface, defInterface.TypeKind); Assert.True(refInterface.Interfaces().Contains(defInterface)); var @class = (NamedTypeSymbol)globalNamespace.GetTypeMembers("IndirectImplementation").Single(); Assert.Equal(TypeKind.Class, @class.TypeKind); var classInterfacesConstructedFrom = @class.Interfaces().Select(i => i.ConstructedFrom); Assert.Equal(2, classInterfacesConstructedFrom.Count()); Assert.Contains(defInterface, classInterfacesConstructedFrom); Assert.Contains(refInterface, classInterfacesConstructedFrom); var classEvent = (EventSymbol)@class.GetMembers("Interface.Event").Single(); var explicitImpl = classEvent.ExplicitInterfaceImplementations.Single(); Assert.Equal(defInterfaceEvent, explicitImpl); } /// <summary> /// In metadata, nested types implicitly share all type parameters of their containing types. /// This results in some extra computations when mapping a type parameter position to a type /// parameter symbol. /// </summary> [Fact] public void TestTypeParameterPositions() { var assemblies = MetadataTestHelpers.GetSymbolsForReferences( new[] { NetFramework.mscorlib, TestReferences.SymbolsTests.ExplicitInterfaceImplementation.Events.CSharp, }); var globalNamespace = assemblies.ElementAt(1).GlobalNamespace; var outerInterface = (NamedTypeSymbol)globalNamespace.GetTypeMembers("IGeneric2").Single(); Assert.Equal(1, outerInterface.Arity); Assert.Equal(TypeKind.Interface, outerInterface.TypeKind); var outerInterfaceEvent = outerInterface.GetMembers().Single(m => m.Kind == SymbolKind.Event); var outerClass = (NamedTypeSymbol)globalNamespace.GetTypeMembers("Outer").Single(); Assert.Equal(1, outerClass.Arity); Assert.Equal(TypeKind.Class, outerClass.TypeKind); var innerInterface = (NamedTypeSymbol)outerClass.GetTypeMembers("IInner").Single(); Assert.Equal(1, innerInterface.Arity); Assert.Equal(TypeKind.Interface, innerInterface.TypeKind); var innerInterfaceEvent = innerInterface.GetMembers().Single(m => m.Kind == SymbolKind.Event); var innerClass1 = (NamedTypeSymbol)outerClass.GetTypeMembers("Inner1").Single(); CheckInnerClassHelper(innerClass1, "IGeneric2<A>.Event", outerInterfaceEvent); var innerClass2 = (NamedTypeSymbol)outerClass.GetTypeMembers("Inner2").Single(); CheckInnerClassHelper(innerClass2, "IGeneric2<T>.Event", outerInterfaceEvent); var innerClass3 = (NamedTypeSymbol)outerClass.GetTypeMembers("Inner3").Single(); CheckInnerClassHelper(innerClass3, "Outer<T>.IInner<C>.Event", innerInterfaceEvent); var innerClass4 = (NamedTypeSymbol)outerClass.GetTypeMembers("Inner4").Single(); CheckInnerClassHelper(innerClass4, "Outer<T>.IInner<T>.Event", innerInterfaceEvent); } private static void CheckInnerClassHelper(NamedTypeSymbol innerClass, string methodName, Symbol interfaceEvent) { var @interface = interfaceEvent.ContainingType; Assert.Equal(1, innerClass.Arity); Assert.Equal(TypeKind.Class, innerClass.TypeKind); Assert.Equal(@interface, innerClass.Interfaces().Single().ConstructedFrom); var innerClassEvent = (EventSymbol)innerClass.GetMembers(methodName).Single(); var innerClassImplementingEvent = innerClassEvent.ExplicitInterfaceImplementations.Single(); Assert.Equal(interfaceEvent, innerClassImplementingEvent.OriginalDefinition); Assert.Equal(@interface, innerClassImplementingEvent.ContainingType.ConstructedFrom); } // NOTE: results differ from corresponding property test. [WorkItem(543263, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543263")] [Fact] public void TestMixedAccessorModifiers() { var assembly = MetadataTestHelpers.GetSymbolForReference(TestReferences.SymbolsTests.Events); var globalNamespace = assembly.GlobalNamespace; var type = globalNamespace.GetMember<NamedTypeSymbol>("AccessorModifierMismatch"); const VirtualnessModifiers @none = VirtualnessModifiers.None; const VirtualnessModifiers @abstract = VirtualnessModifiers.Abstract; const VirtualnessModifiers @virtual = VirtualnessModifiers.Virtual; const VirtualnessModifiers @override = VirtualnessModifiers.Override; const VirtualnessModifiers @sealed = VirtualnessModifiers.Sealed; VirtualnessModifiers[] modList = new[] { @none, @abstract, @virtual, @override, @sealed, }; int length = 1 + modList.Cast<int>().Max(); VirtualnessModifiers[,] expected = new VirtualnessModifiers[length, length]; expected[(int)@none, (int)@none] = @none; expected[(int)@none, (int)@abstract] = @abstract; expected[(int)@none, (int)@virtual] = @virtual; expected[(int)@none, (int)@override] = @override; expected[(int)@none, (int)@sealed] = @sealed; expected[(int)@abstract, (int)@none] = @abstract; expected[(int)@abstract, (int)@abstract] = @abstract; expected[(int)@abstract, (int)@virtual] = @abstract; expected[(int)@abstract, (int)@override] = @abstract | @override; expected[(int)@abstract, (int)@sealed] = @abstract | @sealed; expected[(int)@virtual, (int)@none] = @virtual; expected[(int)@virtual, (int)@abstract] = @abstract; expected[(int)@virtual, (int)@virtual] = @virtual; expected[(int)@virtual, (int)@override] = @override; expected[(int)@virtual, (int)@sealed] = @sealed; expected[(int)@override, (int)@none] = @override; expected[(int)@override, (int)@abstract] = @override | @abstract; expected[(int)@override, (int)@virtual] = @override; expected[(int)@override, (int)@override] = @override; expected[(int)@override, (int)@sealed] = @sealed; expected[(int)@sealed, (int)@none] = @sealed; expected[(int)@sealed, (int)@abstract] = @abstract | @sealed; expected[(int)@sealed, (int)@virtual] = @sealed; expected[(int)@sealed, (int)@override] = @sealed; expected[(int)@sealed, (int)@sealed] = @sealed; // Table should be symmetrical. for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { Assert.Equal(expected[i, j], expected[j, i]); } } foreach (var mod1 in modList) { foreach (var mod2 in modList) { var @event = type.GetMember<EventSymbol>(mod1.ToString() + mod2.ToString()); var addMethod = @event.AddMethod; var removeMethod = @event.RemoveMethod; Assert.Equal(mod1, GetVirtualnessModifiers(addMethod)); Assert.Equal(mod2, GetVirtualnessModifiers(removeMethod)); Assert.Equal(expected[(int)mod1, (int)mod2], GetVirtualnessModifiers(@event)); } } } [Fact] [WorkItem(1055825, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1055825")] public void AssociatedField() { var source = @" public class C { public event System.Action E; } "; var reference = CreateCompilation(source).EmitToImageReference(); var comp = CreateCompilation("", new[] { reference }, TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var @event = type.GetMember<PEEventSymbol>("E"); Assert.True(@event.HasAssociatedField); var field = @event.AssociatedField; Assert.NotNull(field); Assert.Equal(@event, field.AssociatedSymbol); } [Fact] [WorkItem(1055825, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1055825")] public void AssociatedField_MultipleFields() { var ilSource = @" .class public auto ansi beforefieldinit C extends [mscorlib]System.Object { .field private int32 E .field private class [mscorlib]System.Action E .method public hidebysig specialname instance void add_E(class [mscorlib]System.Action 'value') cil managed { ldnull throw } .method public hidebysig specialname instance void remove_E(class [mscorlib]System.Action 'value') cil managed { ldnull throw } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ldarg.0 call instance void [mscorlib]System.Object::.ctor() ret } .event [mscorlib]System.Action E { .addon instance void C::add_E(class [mscorlib]System.Action) .removeon instance void C::remove_E(class [mscorlib]System.Action) } // end of event C::E } // end of class C "; var ilRef = CompileIL(ilSource); var comp = CreateCompilation("", new[] { ilRef }, TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); comp.VerifyDiagnostics(); var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var @event = type.GetMembers().OfType<PEEventSymbol>().Single(); Assert.True(@event.HasAssociatedField); var field = @event.AssociatedField; Assert.NotNull(field); Assert.Equal(@event, field.AssociatedSymbol); Assert.Equal(@event.Type, field.Type); } [Fact] [WorkItem(1055825, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1055825")] public void AssociatedField_DuplicateEvents() { var ilSource = @" .class public auto ansi beforefieldinit C extends [mscorlib]System.Object { .field private class [mscorlib]System.Action E .method public hidebysig specialname instance void add_E(class [mscorlib]System.Action 'value') cil managed { ldnull throw } .method public hidebysig specialname instance void remove_E(class [mscorlib]System.Action 'value') cil managed { ldnull throw } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ldarg.0 call instance void [mscorlib]System.Object::.ctor() ret } .event [mscorlib]System.Action E { .addon instance void C::add_E(class [mscorlib]System.Action) .removeon instance void C::remove_E(class [mscorlib]System.Action) } // end of event C::E .event [mscorlib]System.Action E { .addon instance void C::add_E(class [mscorlib]System.Action) .removeon instance void C::remove_E(class [mscorlib]System.Action) } // end of event C::E } // end of class C "; var ilRef = CompileIL(ilSource); var comp = CreateCompilation("", new[] { ilRef }, TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); comp.VerifyDiagnostics(); var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var events = type.GetMembers().OfType<PEEventSymbol>(); Assert.Equal(2, events.Count()); AssertEx.All(events, e => e.HasAssociatedField); var field = events.First().AssociatedField; Assert.NotNull(field); AssertEx.All(events, e => e.AssociatedField == field); Assert.Contains(field.AssociatedSymbol, events); } [Flags] private enum VirtualnessModifiers { None = 0, Abstract = 1, Virtual = 2, Override = 4, Sealed = 8, //actually indicates sealed override } private static VirtualnessModifiers GetVirtualnessModifiers(Symbol symbol) { VirtualnessModifiers mods = VirtualnessModifiers.None; if (symbol.IsAbstract) mods |= VirtualnessModifiers.Abstract; if (symbol.IsVirtual) mods |= VirtualnessModifiers.Virtual; if (symbol.IsSealed) mods |= VirtualnessModifiers.Sealed; else if (symbol.IsOverride) mods |= VirtualnessModifiers.Override; return mods; } } }