Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptPrivateImplementationDetails.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/DelegateBeginInvokeEndInvokePair.cs3
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs3
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs1
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs82
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/GenericInterfaceWithEvent.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/SimpleEvent.cs2
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/ExpressionCallString.cs1
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs2
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs80
18 files changed, 181 insertions, 34 deletions
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs
index 52fe49618..b3638b01a 100644
--- a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs
@@ -8,10 +8,12 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
public class KeptDelegateCacheFieldAttribute : KeptAttribute
{
- public KeptDelegateCacheFieldAttribute (string uniquePartOfName)
+ public KeptDelegateCacheFieldAttribute (string classIndex, string fieldName)
{
- if (string.IsNullOrEmpty (uniquePartOfName))
- throw new ArgumentNullException (nameof (uniquePartOfName));
+ if (string.IsNullOrEmpty (classIndex))
+ throw new ArgumentNullException (nameof (classIndex));
+ if (string.IsNullOrEmpty (fieldName))
+ throw new ArgumentNullException (nameof (fieldName));
}
}
}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptPrivateImplementationDetails.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptPrivateImplementationDetails.cs
new file mode 100644
index 000000000..a410eb2f5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptPrivateImplementationDetails.cs
@@ -0,0 +1,17 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.Class)]
+ public sealed class KeptPrivateImplementationDetailsAttribute : KeptAttribute
+ {
+ public KeptPrivateImplementationDetailsAttribute (string methodName)
+ {
+ if (string.IsNullOrEmpty (methodName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (methodName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
index 6b9c5ff8e..eaf9a4866 100644
--- a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
@@ -14,7 +14,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Csc
[KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
[RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
[KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (FooOnMyEvent))]
public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
index 9026e6048..d069585c0 100644
--- a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
@@ -15,7 +15,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Csc
[RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
[KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
[KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (FooOnMyEvent))]
public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
index 5f1791948..83466e847 100644
--- a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
@@ -15,7 +15,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Csc
[RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
[KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
[KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (FooOnMyEvent))]
public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs
index ff8775974..c05e9ad30 100644
--- a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs
@@ -5,7 +5,7 @@ using Mono.Linker.Tests.Cases.Expectations.Metadata;
namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
{
[SetupLinkerArgument ("--used-attrs-only", "true")]
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (Tmp_Something))]
class UnusedAttributeTypeOnEventIsRemoved
{
static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs
index 27d50d3cd..0a5e3cfe3 100644
--- a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs
@@ -5,7 +5,7 @@ using Mono.Linker.Tests.Cases.Expectations.Metadata;
namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
{
[SetupLinkerArgument ("--used-attrs-only", "true")]
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (Tmp_Something))]
class UsedAttributeTypeOnEventIsKept
{
static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Basic/DelegateBeginInvokeEndInvokePair.cs b/test/Mono.Linker.Tests.Cases/Basic/DelegateBeginInvokeEndInvokePair.cs
index d39ab89d9..99e8e90ae 100644
--- a/test/Mono.Linker.Tests.Cases/Basic/DelegateBeginInvokeEndInvokePair.cs
+++ b/test/Mono.Linker.Tests.Cases/Basic/DelegateBeginInvokeEndInvokePair.cs
@@ -5,6 +5,9 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Basic
{
+ [KeptDelegateCacheField ("0", nameof (Method))]
+ [KeptDelegateCacheField ("1", nameof (Method))]
+ [KeptDelegateCacheField ("2", nameof (Method))]
class DelegateBeginInvokeEndInvokePair
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs
index 8453f1624..490ffa348 100644
--- a/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs
@@ -3,8 +3,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Basic
{
- [KeptDelegateCacheField ("0")]
- [KeptDelegateCacheField ("1")]
+ [KeptDelegateCacheField ("0", nameof (Tmp_Bar))]
class UsedEventIsKept
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs
index 099b92ab2..47e45e75e 100644
--- a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs
@@ -3,7 +3,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Basic
{
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (Bar_Ping))]
class UsedEventOnInterfaceIsKept
{
static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs
index 464db7008..10555f041 100644
--- a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs
@@ -3,7 +3,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Basic
{
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (Bar_Ping))]
class UsedEventOnInterfaceIsRemovedWhenUsedFromClass
{
static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
index d19a1fb82..90c24fd9f 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs
@@ -11,6 +11,7 @@ using DAMT = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
namespace Mono.Linker.Tests.Cases.DataFlow
{
[ExpectedNoWarnings]
+ [KeptPrivateImplementationDetails ("ThrowSwitchExpressionException")]
class NullableAnnotations
{
[Kept]
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
index 2128b8e41..15508baca 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs
@@ -45,6 +45,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
BasePropertyAccess.Test ();
AccessReturnedInstanceProperty.Test ();
+
+ ExplicitIndexerAccess.Test ();
+ ImplicitIndexerAccess.Test ();
}
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
@@ -653,6 +656,85 @@ namespace Mono.Linker.Tests.Cases.DataFlow
}
}
+ class ExplicitIndexerAccess
+ {
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type this[Index idx] {
+ get => throw new NotImplementedException ();
+ set => throw new NotImplementedException ();
+ }
+
+ [ExpectedWarning ("IL2072", "this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Trimmer)]
+ static void TestRead (ExplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)].RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Index].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestWrite (ExplicitIndexerAccess instance = null)
+ {
+ instance[^1] = GetTypeWithPublicConstructors ();
+ }
+
+ public static void Test ()
+ {
+ TestRead ();
+ TestWrite ();
+ }
+ }
+
+ class ImplicitIndexerAccess
+ {
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type this[int idx] {
+ get => throw new NotImplementedException ();
+ set => throw new NotImplementedException ();
+ }
+
+ int Length => throw new NotImplementedException ();
+
+ [ExpectedWarning ("IL2072", "this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = ProducedBy.Trimmer)]
+ static void TestRead (ImplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)].RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Int32].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestWrite (ImplicitIndexerAccess instance = null)
+ {
+ instance[^1] = GetTypeWithPublicConstructors ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetUnknownType), "this[Int32].set", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2072", nameof (GetUnknownType), "Item.set", ProducedBy = ProducedBy.Trimmer)]
+ static void TestNullCoalescingAssignment (ImplicitIndexerAccess instance = null)
+ {
+ instance[new Index (1)] ??= GetUnknownType ();
+ }
+
+ [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))]
+ static void TestSpanIndexerAccess (int start = 0, int end = 3)
+ {
+ Span<byte> bytes = stackalloc byte[4] { 1, 2, 3, 4 };
+ bytes[^4] = 0; // This calls the get indexer which has a ref return.
+ int index = bytes[0];
+ Type[] types = new Type[] { GetUnknownType () };
+ types[index].RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ TestRead ();
+ TestWrite ();
+ TestNullCoalescingAssignment ();
+ TestSpanIndexerAccess ();
+ }
+ }
+
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
private static Type GetTypeWithPublicParameterlessConstructor ()
{
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/GenericInterfaceWithEvent.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/GenericInterfaceWithEvent.cs
index e8856be3b..ec4a75670 100644
--- a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/GenericInterfaceWithEvent.cs
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/GenericInterfaceWithEvent.cs
@@ -2,7 +2,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.BaseProvidesInterfaceMember
{
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (EventMethod))]
public class GenericInterfaceWithEvent
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/SimpleEvent.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/SimpleEvent.cs
index 11e5860a6..98597a4b2 100644
--- a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/SimpleEvent.cs
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/BaseProvidesInterfaceMember/SimpleEvent.cs
@@ -2,7 +2,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions;
namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.BaseProvidesInterfaceMember
{
- [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("0", nameof (EventMethod))]
public class SimpleEvent
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionCallString.cs b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionCallString.cs
index 10ac90435..5489497a8 100644
--- a/test/Mono.Linker.Tests.Cases/Reflection/ExpressionCallString.cs
+++ b/test/Mono.Linker.Tests.Cases/Reflection/ExpressionCallString.cs
@@ -10,6 +10,7 @@ namespace Mono.Linker.Tests.Cases.Reflection
[SetupCSharpCompilerToUse ("csc")]
[Reference ("System.Core.dll")]
[ExpectedNoWarnings]
+ [KeptPrivateImplementationDetails ("ThrowSwitchExpressionException")]
public class ExpressionCallString
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs
index 906f56ab4..5bec60d50 100644
--- a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs
@@ -9,6 +9,8 @@ namespace Mono.Linker.Tests.Cases.Reflection
{
[KeptMember (".cctor()")]
[ExpectedNoWarnings ()]
+ [KeptDelegateCacheField ("0", nameof (AssemblyResolver))]
+ [KeptDelegateCacheField ("1", nameof (GetTypeFromAssembly))]
public class TypeUsedViaReflection
{
public static void Main ()
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs
index f7e6df662..96c037778 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs
@@ -146,6 +146,10 @@ namespace Mono.Linker.Tests.TestCasesRunner
VerifyFixedBufferFields (original, linked);
+ // Need to check delegate cache fields before the normal field check
+ VerifyDelegateBackingFields (original, linked);
+ VerifyPrivateImplementationDetails (original, linked);
+
foreach (var td in original.NestedTypes) {
VerifyTypeDefinition (td, linked?.NestedTypes.FirstOrDefault (l => td.FullName == l.FullName));
linkedMembers.Remove (td.FullName);
@@ -162,9 +166,6 @@ namespace Mono.Linker.Tests.TestCasesRunner
linkedMembers.Remove (e.FullName);
}
- // Need to check delegate cache fields before the normal field check
- VerifyDelegateBackingFields (original, linked);
-
foreach (var f in original.Fields) {
if (verifiedGeneratedFields.Contains (f.FullName))
continue;
@@ -712,6 +713,41 @@ namespace Mono.Linker.Tests.TestCasesRunner
Assert.That (linkedAttrs, Is.EquivalentTo (expectedAttrs), $"Security attributes on `{src}' are not matching");
}
+ void VerifyPrivateImplementationDetails (TypeDefinition original, TypeDefinition linked)
+ {
+ var expectedImplementationDetailsMethods = GetCustomAttributeCtorValues<string> (original, nameof (KeptPrivateImplementationDetailsAttribute))
+ .Select (attr => attr.ToString ())
+ .ToList ();
+
+ if (expectedImplementationDetailsMethods.Count == 0)
+ return;
+
+ VerifyPrivateImplementationDetailsType (original.Module, linked.Module, out TypeDefinition srcImplementationDetails, out TypeDefinition linkedImplementationDetails);
+ foreach (var methodName in expectedImplementationDetailsMethods) {
+ var originalMethod = srcImplementationDetails.Methods.FirstOrDefault (m => m.Name == methodName);
+ if (originalMethod == null)
+ Assert.Fail ($"Could not locate original private implementation details method {methodName}");
+
+ var linkedMethod = linkedImplementationDetails.Methods.FirstOrDefault (m => m.Name == methodName);
+ VerifyMethodKept (originalMethod, linkedMethod);
+ linkedMembers.Remove (linkedMethod.FullName);
+ }
+ verifiedGeneratedTypes.Add (srcImplementationDetails.FullName);
+ }
+
+ static void VerifyPrivateImplementationDetailsType (ModuleDefinition src, ModuleDefinition linked, out TypeDefinition srcImplementationDetails, out TypeDefinition linkedImplementationDetails)
+ {
+ srcImplementationDetails = src.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
+
+ if (srcImplementationDetails == null)
+ Assert.Fail ("Could not locate <PrivateImplementationDetails> in the original assembly. Does your test use initializers?");
+
+ linkedImplementationDetails = linked.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
+
+ if (linkedImplementationDetails == null)
+ Assert.Fail ("Could not locate <PrivateImplementationDetails> in the linked assembly");
+ }
+
protected virtual void VerifyArrayInitializers (MethodDefinition src, MethodDefinition linked)
{
var expectedIndicies = GetCustomAttributeCtorValues<object> (src, nameof (KeptInitializerData))
@@ -726,15 +762,7 @@ namespace Mono.Linker.Tests.TestCasesRunner
if (!src.HasBody)
Assert.Fail ($"`{nameof (KeptInitializerData)}` cannot be used on methods that don't have bodies");
- var srcImplementationDetails = src.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
-
- if (srcImplementationDetails == null)
- Assert.Fail ("Could not locate <PrivateImplementationDetails> in the original assembly. Does your test use initializers?");
-
- var linkedImplementationDetails = linked.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
-
- if (linkedImplementationDetails == null)
- Assert.Fail ("Could not locate <PrivateImplementationDetails> in the linked assembly");
+ VerifyPrivateImplementationDetailsType (src.Module, linked.Module, out TypeDefinition srcImplementationDetails, out TypeDefinition linkedImplementationDetails);
var possibleInitializerFields = src.Body.Instructions
.Where (ins => IsLdtokenOnPrivateImplementationDetails (srcImplementationDetails, ins))
@@ -874,21 +902,33 @@ namespace Mono.Linker.Tests.TestCasesRunner
void VerifyDelegateBackingFields (TypeDefinition src, TypeDefinition linked)
{
- var expectedFieldNames = GetCustomAttributeCtorValues<string> (src, nameof (KeptDelegateCacheFieldAttribute))
- .Select (unique => $"<>f__mg$cache{unique}")
+ var expectedFieldNames = src.CustomAttributes
+ .Where (a => a.AttributeType.Name == nameof (KeptDelegateCacheFieldAttribute))
+ .Select (a => (a.ConstructorArguments[0].Value as string, a.ConstructorArguments[1].Value as string))
+ .Select (indexAndField => $"<{indexAndField.Item1}>__{indexAndField.Item2}")
.ToList ();
if (expectedFieldNames.Count == 0)
return;
- foreach (var srcField in src.Fields) {
- if (!expectedFieldNames.Contains (srcField.Name))
+ foreach (var nestedType in src.NestedTypes) {
+ if (nestedType.Name != "<>O")
continue;
- var linkedField = linked?.Fields.FirstOrDefault (l => l.Name == srcField.Name);
- VerifyFieldKept (srcField, linkedField);
- verifiedGeneratedFields.Add (srcField.FullName);
- linkedMembers.Remove (srcField.FullName);
+ var linkedNestedType = linked.NestedTypes.FirstOrDefault (t => t.Name == nestedType.Name);
+ foreach (var expectedFieldName in expectedFieldNames) {
+ var originalField = nestedType.Fields.FirstOrDefault (f => f.Name == expectedFieldName);
+ if (originalField is null)
+ Assert.Fail ($"Invalid expected delegate backing field {expectedFieldName} in {src}. This member was not in the unlinked assembly");
+
+ var linkedField = linkedNestedType?.Fields.FirstOrDefault (f => f.Name == expectedFieldName);
+ VerifyFieldKept (originalField, linkedField);
+ verifiedGeneratedFields.Add (linkedField.FullName);
+ linkedMembers.Remove (linkedField.FullName);
+ }
+
+ VerifyTypeDefinitionKept (nestedType, linkedNestedType);
+ verifiedGeneratedTypes.Add (linkedNestedType.FullName);
}
}