diff options
author | Mateo Torres-Ruiz <mateoatr@users.noreply.github.com> | 2021-04-01 14:56:37 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-01 14:56:37 +0300 |
commit | 1d96189abb1b2cfe00dff817c63b84b25534746a (patch) | |
tree | 37bb5a8f110a36727054c3f6dc4acc6aa1dccaac /test | |
parent | f4147aa53a425420f725c9cb5dbd36552df99372 (diff) |
Change behavior of copy action to not rewrite assemblies (#1869)
Co-authored-by: Marek Safar <marek.safar@gmail.com>
Diffstat (limited to 'test')
34 files changed, 649 insertions, 47 deletions
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs index 90017d03f..b083b446f 100644 --- a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs +++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs @@ -10,9 +10,9 @@ namespace Mono.Linker.Tests.Cases.LinkXml // Add another assembly in that uses the forwarder just to make things a little more complex [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/CanPreserveAnExportedType_Forwarder.cs" }, references: new[] { "Library.dll" })] - [RemovedAssembly ("Forwarder.dll")] [KeptMemberInAssembly ("Library.dll", typeof (CanPreserveAnExportedType_Library), "Field1", "Method()", ".ctor()")] [SetupLinkerDescriptorFile ("CanPreserveAnExportedType.xml")] + [KeptTypeInAssembly ("Forwarder.dll", typeof (CanPreserveAnExportedType_Library))] class CanPreserveAnExportedType { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs index 9a54cce19..d84f952a0 100644 --- a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs +++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs @@ -10,9 +10,9 @@ namespace Mono.Linker.Tests.Cases.LinkXml // Add another assembly in that uses the forwarder just to make things a little more complex [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/CanPreserveAnExportedType_Forwarder.cs" }, references: new[] { "Library.dll" })] - [RemovedAssembly ("Forwarder.dll")] [KeptMemberInAssembly ("Library.dll", typeof (CanPreserveAnExportedType_Library), "Field1", "Method()", ".ctor()")] [SetupLinkerDescriptorFile ("CanPreserveExportedTypesUsingRegex.xml")] + [KeptTypeInAssembly ("Forwarder.dll", typeof (CanPreserveAnExportedType_Library))] class CanPreserveExportedTypesUsingRegex { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.cs index 44328fb19..c990ddbfa 100644 --- a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.cs +++ b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.cs @@ -5,15 +5,17 @@ namespace Mono.Linker.Tests.Cases.LinkXml { [SetupLinkerDescriptorFile ("UsedNonRequiredExportedTypeIsKept.xml")] - [SetupCompileBefore ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_lib.cs" })] - [SetupCompileAfter ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_lib.cs" })] - [SetupCompileAfter ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_fwd.cs" }, references: new[] { "libfwd.dll" })] + [SetupCompileBefore ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_lib.cs" })] + [SetupCompileAfter ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_lib.cs" })] + [SetupCompileAfter ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKept_fwd.cs" }, references: new[] { "lib.dll" })] + + // Note that forwarders which are referenced from within a descriptor XML file are kept -- any exported type referenced through a type + // name string should be kept. + [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used1), "field")] + [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used2), "Method()")] + [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used3), "Method()")] + [KeptAssembly ("lib.dll")] - [KeptAssembly ("libfwd.dll")] - [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used1), "field", ExpectationAssemblyName = "lib.dll")] - [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used2), "Method()", ExpectationAssemblyName = "lib.dll")] - [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKept_Used3), "Method()", ExpectationAssemblyName = "lib.dll")] - [RemovedAssembly ("lib.dll")] public class UsedNonRequiredExportedTypeIsKept { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.xml index 223744d49..659c05db5 100644 --- a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.xml +++ b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKept.xml @@ -1,5 +1,5 @@ <linker> - <assembly fullname="lib"> + <assembly fullname="libfwd"> <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredExportedTypeIsKept_Used1" preserve="fields" required="false"/> <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredExportedTypeIsKept_Used2" preserve="methods" required="false"/> <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredExportedTypeIsKept_Used3" preserve="all" required="false"/> diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKeptWhenRooted.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKeptWhenRooted.cs index eec9e5bfc..96630532a 100644 --- a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKeptWhenRooted.cs +++ b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredExportedTypeIsKeptWhenRooted.cs @@ -4,16 +4,16 @@ using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.Cases.LinkXml { [SetupLinkerDescriptorFile ("UsedNonRequiredExportedTypeIsKeptWhenRooted.xml")] - [SetupLinkerArgument ("-a", "lib.dll", "visible")] + [SetupLinkerArgument ("-a", "libfwd.dll", "visible")] - [SetupCompileBefore ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_lib.cs" })] - [SetupCompileAfter ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_lib.cs" })] - [SetupCompileAfter ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_fwd.cs" }, references: new[] { "libfwd.dll" })] + [SetupCompileBefore ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_lib.cs" })] + [SetupCompileAfter ("lib.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_lib.cs" })] + [SetupCompileAfter ("libfwd.dll", new[] { "Dependencies/UsedNonRequiredExportedTypeIsKeptWhenRooted_fwd.cs" }, references: new[] { "lib.dll" })] - [KeptAssembly ("libfwd.dll")] [KeptAssembly ("lib.dll")] - [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKeptWhenRooted_Used), "field", ExpectationAssemblyName = "lib.dll")] - [KeptMemberInAssembly ("libfwd.dll", typeof (UsedNonRequiredExportedTypeIsKeptWhenRooted_Used), "Method()", ExpectationAssemblyName = "lib.dll")] + [KeptAssembly ("libfwd.dll")] + [KeptMemberInAssembly ("lib.dll", typeof (UsedNonRequiredExportedTypeIsKeptWhenRooted_Used), "field", ExpectationAssemblyName = "libfwd.dll")] + [KeptMemberInAssembly ("lib.dll", typeof (UsedNonRequiredExportedTypeIsKeptWhenRooted_Used), "Method()", ExpectationAssemblyName = "libfwd.dll")] public class UsedNonRequiredExportedTypeIsKeptWhenRooted { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs index 48b87d074..7be38642a 100644 --- a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs +++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs @@ -1,4 +1,5 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; using Mono.Linker.Tests.Cases.Expectations.Metadata; using Mono.Linker.Tests.Cases.References.Dependencies; @@ -20,11 +21,7 @@ namespace Mono.Linker.Tests.Cases.References // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked [RemovedAssembly ("library.dll")] -#if NETCOREAPP - [KeptReferencesInAssembly ("copied.dll", new[] { "System.Private.CoreLib" })] -#else - [KeptReferencesInAssembly ("copied.dll", new[] { "mscorlib" })] -#endif + [KeptReferencesInAssembly ("copied.dll", new[] { PlatformAssemblies.CoreLib, "library" })] public class AssemblyOnlyUsedByUsingWithCsc { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs index f039dac8f..2fcbb6a6c 100644 --- a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs +++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs @@ -1,4 +1,5 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; using Mono.Linker.Tests.Cases.Expectations.Metadata; using Mono.Linker.Tests.Cases.References.Dependencies; @@ -22,11 +23,7 @@ namespace Mono.Linker.Tests.Cases.References // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked [RemovedAssembly ("library.dll")] -#if NETCOREAPP - [KeptReferencesInAssembly ("copied.dll", new[] { "System.Private.CoreLib" })] -#else - [KeptReferencesInAssembly ("copied.dll", new[] { "mscorlib" })] -#endif + [KeptReferencesInAssembly ("copied.dll", new[] { PlatformAssemblies.CoreLib, "library" })] public class AssemblyOnlyUsedByUsingWithCscWithKeepFacades { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs index 15ee534aa..3be34790d 100644 --- a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs +++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs @@ -8,7 +8,8 @@ namespace Mono.Linker.Tests.Cases.Symbols [SetupLinkerLinkSymbols ("false")] [SetupLinkerAction ("copy", "LibraryWithEmbeddedPdbSymbols")] - [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")] + // Copy assemblies cannot be modified. + [KeptSymbols ("LibraryWithEmbeddedPdbSymbols.dll")] // Copying with symbol linking off is a little more complex for embedded pdbs. // Do a little extra asserting here to make sure the assembly wasn't accidentally linked diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwarded.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwarded.cs index 4c119d473..6e740e717 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwarded.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwarded.cs @@ -5,10 +5,6 @@ using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; namespace Mono.Linker.Tests.Cases.TypeForwarding { - // On .NET FW the built in compiler will drop the reference to the forwarder assembly when compiling the test assembly. - // Use roslyn to give consistent behavior across platforms - [SetupCSharpCompilerToUse ("csc")] - // Actions: // link - This assembly, Forwarder.dll and Implementation.dll [SetupLinkerDefaultAction ("link")] diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwardedWithCopyAction.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwardedWithCopyAction.cs index d67b53fab..0c5d01131 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwardedWithCopyAction.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributeArgumentForwardedWithCopyAction.cs @@ -23,7 +23,7 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] - [RemovedAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] static class AttributeArgumentForwardedWithCopyAction { diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributesScopeUpdated.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributesScopeUpdated.cs index 56e06ac6f..1e01403be 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributesScopeUpdated.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/AttributesScopeUpdated.cs @@ -19,7 +19,7 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] - [RemovedAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] static class AttributesScopeUpdated { diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs index 441a971eb..57aee6ea8 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs @@ -2,3 +2,6 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedTo (typeof (Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo (typeof (Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationStruct))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibraryAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibraryImp))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibraryInterface))] diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs index 86a37fdfc..211e2d14f 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs @@ -6,14 +6,38 @@ using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.Cases.TypeForwarding.Dependencies { + public interface ImplementationLibraryInterface + { + public int GetDefaultImplementation () + { + return 42; + } + } + + public class ImplementationLibraryImp : ImplementationLibraryInterface + { + } + public class ImplementationLibrary { + public class ImplementationLibraryNestedType + { + public static int PropertyOnNestedType { get; set; } + } + + public static int someField = 42; + public string GetSomeValue () { return "Hello"; } } + [AttributeUsage (AttributeTargets.All)] + public class ImplementationLibraryAttribute : Attribute + { + } + public struct ImplementationStruct { public int Field; diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs index 8796effb1..4ec420372 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs @@ -9,13 +9,37 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding.Dependencies } #if INCLUDE_REFERENCE_IMPL + public interface ImplementationLibraryInterface + { + public int GetDefaultImplementation () + { + return 42; + } + } + + public class ImplementationLibraryImp : ImplementationLibraryInterface + { + } + public class ImplementationLibrary { + public class ImplementationLibraryNestedType + { + public static int PropertyOnNestedType { get; set; } + } + + public static int someField = 0; + public string GetSomeValue () { return null; } } + [AttributeUsage (AttributeTargets.All)] + public class ImplementationLibraryAttribute : Attribute + { + } + public struct ImplementationStruct { public int Field; diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/SecurityAttributeScope.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/SecurityAttributeScope.cs index 17744e7bf..47bc346a2 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/SecurityAttributeScope.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/SecurityAttributeScope.cs @@ -16,13 +16,14 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding [SetupLinkerArgument ("--strip-security", "false")] [Define ("IL_ASSEMBLY_AVAILABLE")] [KeepTypeForwarderOnlyAssemblies ("false")] - [SetupLinkerAction ("copy", "Library.dll")] + [SetupLinkerAction ("copy", "Library")] [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/SecurityAttributeForwarderLibrary.cs" })] [SetupCompileBefore ("Library.dll", new[] { "Dependencies/LibraryWithSecurityAttributes.il" }, new[] { "Forwarder.dll" })] // Sanity checks to verify the test was setup correctly [KeptTypeInAssembly ("Library.dll", "LibraryWithSecurityAttributes")] - [RemovedAssembly ("Forwarder.dll")] + // There's a reference to `Forwarder` in the copy assembly `Library`. + [KeptAssembly ("Forwarder.dll")] public class SecurityAttributeScope { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UnusedForwarderWithAssemblyCopyIsKept.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UnusedForwarderWithAssemblyCopyIsKept.cs new file mode 100644 index 000000000..a6a78eeab --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UnusedForwarderWithAssemblyCopyIsKept.cs @@ -0,0 +1,28 @@ +// 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. + +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [SetupLinkerDefaultAction ("link")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [SetupLinkerAction ("copy", "Forwarder")] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + [RemovedAssembly ("Implementation.dll")] + + public class UnusedForwarderWithAssemblyCopyIsKept + { + static void Main () + { + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs index 63f9e70c5..fdd75a7f8 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedAndUnusedForwarderWithAssemblyCopy.cs @@ -19,12 +19,14 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding [SetupCompileAfter ("Unused.dll", new[] { "Dependencies/AnotherLibrary.cs" })] [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary_2.cs" }, references: new[] { "Implementation.dll", "Unused.dll" })] - [KeptAssembly ("Forwarder.dll")] [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + // The whole assembly is kept as is, since it is marked with the `copy` action. [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Forwarder.dll", "Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.AnotherLibrary`1")] + [KeptReferencesInAssembly ("Forwarder.dll", new[] { "System.Private.CoreLib", "Implementation", "Unused" })] + // Even though `Forwarder` references this assembly, none of its members are marked (none is used) and, since `Unused` + // has `link` action, it is removed. [RemovedAssembly ("Unused.dll")] - [RemovedForwarder ("Forwarder.dll", "Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.AnotherLibrary`1")] - [RemovedAssemblyReference ("Forwarder.dll", "Unused")] class UsedAndUnusedForwarderWithAssemblyCopy { static void Main () diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByPreserveDependency.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByPreserveDependency.cs new file mode 100644 index 000000000..4abfabc66 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByPreserveDependency.cs @@ -0,0 +1,33 @@ +using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("FakeSystemAssembly.dll", new[] { "../PreserveDependencies/Dependencies/PreserveDependencyAttribute.cs" })] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByPreserveDependency + { + [Kept] + [KeptAttributeAttribute (typeof (PreserveDependencyAttribute))] + [PreserveDependency ("*", "Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary", "Forwarder")] + public static void Main () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedCustomAttribute.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedCustomAttribute.cs new file mode 100644 index 000000000..5c1230cd6 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedCustomAttribute.cs @@ -0,0 +1,32 @@ +using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibraryAttribute))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibraryAttribute))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedCustomAttribute + { + [Kept] + [KeptAttributeAttribute (typeof (ImplementationLibraryAttribute))] + [ImplementationLibrary] + public static void Main () + { + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedField.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedField.cs new file mode 100644 index 000000000..961cf64f8 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedField.cs @@ -0,0 +1,31 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "someField")] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedField + { + public static void Main () + { + int field = ImplementationLibrary.someField; + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedInterface.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedInterface.cs new file mode 100644 index 000000000..8b87e16a2 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedInterface.cs @@ -0,0 +1,32 @@ +using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibraryImp))] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibraryInterface))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibraryImp))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibraryInterface))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedInterface + { + public static void Main () + { + ImplementationLibraryInterface myInterface = new ImplementationLibraryImp (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedMethod.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedMethod.cs new file mode 100644 index 000000000..7f574762a --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedMethod.cs @@ -0,0 +1,31 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedMethod + { + public static void Main () + { + new ImplementationLibrary ().GetSomeValue (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedNestedType.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedNestedType.cs new file mode 100644 index 000000000..56e952b25 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedNestedType.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary.ImplementationLibraryNestedType))] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary.ImplementationLibraryNestedType))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedNestedType + { + public static void Main () + { + new ImplementationLibrary.ImplementationLibraryNestedType (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedProperty.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedProperty.cs new file mode 100644 index 000000000..e92f5e716 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedProperty.cs @@ -0,0 +1,32 @@ +using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary.ImplementationLibraryNestedType))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary.ImplementationLibraryNestedType))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedProperty + { + public static void Main () + { + var accessPropertyOnNestedType = ImplementationLibrary.ImplementationLibraryNestedType.PropertyOnNestedType; + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedTypeAsGenericArg.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedTypeAsGenericArg.cs new file mode 100644 index 000000000..1693a506e --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderInCopyAssemblyKeptByUsedTypeAsGenericArg.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + // Actions: + // copy - This assembly + // link - Forwarder.dll and Implementation.dll + [SetupLinkerAction ("copy", "test")] + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptAssembly ("Forwarder.dll")] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + + [Kept] + [KeptMember (".ctor()")] + public class UsedForwarderInCopyAssemblyKeptByUsedTypeAsGenericArg + { + public static void Main () + { + _ = new List<ImplementationLibrary> (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderIsDynamicallyAccessedWithAssemblyCopyUsed.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderIsDynamicallyAccessedWithAssemblyCopyUsed.cs new file mode 100644 index 000000000..963d22da9 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderIsDynamicallyAccessedWithAssemblyCopyUsed.cs @@ -0,0 +1,38 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + + [SetupLinkerAction ("copyused", "Forwarder")] + [KeepTypeForwarderOnlyAssemblies ("false")] + + [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary))] + class UsedForwarderIsDynamicallyAccessedWithAssemblyCopyUsed + { + static void Main () + { + PointToTypeInFacade ("Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary, Forwarder"); + } + + [Kept] + static void PointToTypeInFacade ( + [KeptAttributeAttribute (typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName) + { + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderWithAssemblyCopyUsedAndFacadesKept.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderWithAssemblyCopyUsedAndFacadesKept.cs index 9c7b0c769..7698bc70c 100644 --- a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderWithAssemblyCopyUsedAndFacadesKept.cs +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedForwarderWithAssemblyCopyUsedAndFacadesKept.cs @@ -20,6 +20,7 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding [KeptMemberInAssembly ("Forwarder.dll", typeof (ImplementationLibrary))] [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [RemovedAssemblyReference ("test", "Forwarder")] class UsedForwarderWithAssemblyCopyUsedAndFacadesKept { static void Main () diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyAssemblyIsDynamicallyAccessed.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyAssemblyIsDynamicallyAccessed.cs new file mode 100644 index 000000000..4ba936ae6 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyAssemblyIsDynamicallyAccessed.cs @@ -0,0 +1,41 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [SetupCompileBefore ("SecondForwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + [SetupCompileBefore ("FirstForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "SecondForwarder.dll" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("SecondForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + [SetupLinkerAction ("copy", "FirstForwarder")] + + [KeptMemberInAssembly ("FirstForwarder.dll", typeof (ImplementationLibrary))] + // Dynamically accessing a type forwarder will cause the linker to mark the scope + // of type pointed to as well as the resolved type. + [KeptMemberInAssembly ("SecondForwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + class UsedTransitiveForwarderInCopyAssemblyIsDynamicallyAccessed + { + static void Main () + { + // [copy] [link] [link] + // FirstForwarder -> SecondForwarder -> Implementation + PointToTypeInFacade ("Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary, FirstForwarder"); + } + + [Kept] + static void PointToTypeInFacade ( + [KeptAttributeAttribute (typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName) + { + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyUsedAssemblyIsDynamicallyAccessed.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyUsedAssemblyIsDynamicallyAccessed.cs new file mode 100644 index 000000000..9f6b74c0d --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderInCopyUsedAssemblyIsDynamicallyAccessed.cs @@ -0,0 +1,43 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [KeepTypeForwarderOnlyAssemblies ("false")] + + [SetupCompileBefore ("SecondForwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + [SetupCompileBefore ("FirstForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "SecondForwarder.dll" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("SecondForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + [SetupLinkerAction ("copyused", "FirstForwarder")] + + [KeptMemberInAssembly ("FirstForwarder.dll", typeof (ImplementationLibrary))] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [RemovedAssemblyReference ("FirstForwarder.dll", "SecondForwarder.dll")] + [RemovedForwarder ("FirstForwarder.dll", nameof (ImplementationStruct))] + [RemovedAssembly ("SecondForwarder.dll")] + class UsedTransitiveForwarderInCopyUsedAssemblyIsDynamicallyAccessed + { + static void Main () + { + // [copyused] [link] [link] + // FirstForwarder -> SecondForwarder -> Implementation + PointToTypeInFacade ("Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary, FirstForwarder"); + } + + [Kept] + static void PointToTypeInFacade ( + [KeptAttributeAttribute (typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName) + { + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsDynamicallyAccessed.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsDynamicallyAccessed.cs new file mode 100644 index 000000000..d51014d0e --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsDynamicallyAccessed.cs @@ -0,0 +1,41 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [KeepTypeForwarderOnlyAssemblies ("false")] + + [SetupCompileBefore ("SecondForwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + [SetupCompileBefore ("FirstForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "SecondForwarder.dll" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("SecondForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("FirstForwarder.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [RemovedForwarder ("FirstForwarder.dll", nameof (ImplementationStruct))] + [RemovedAssembly ("SecondForwarder.dll")] + class UsedTransitiveForwarderIsDynamicallyAccessed + { + static void Main () + { + // [link] [link] [link] + // FirstForwarder -> SecondForwarder -> Implementation + PointToTypeInFacade ("Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary, FirstForwarder"); + } + + [Kept] + static void PointToTypeInFacade ( + [KeptAttributeAttribute (typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName) + { + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemoved.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemoved.cs new file mode 100644 index 000000000..1c8458eba --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemoved.cs @@ -0,0 +1,31 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [KeepTypeForwarderOnlyAssemblies ("false")] + + [SetupCompileBefore ("SecondForwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + [SetupCompileBefore ("FirstForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "SecondForwarder.dll" })] + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("SecondForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [RemovedMemberInAssembly ("Implementation.dll", nameof (ImplementationStruct))] + [RemovedAssembly ("FirstForwarder.dll")] + [RemovedAssembly ("SecondForwarder.dll")] + class UsedTransitiveForwarderIsResolvedAndFacadeRemoved + { + static void Main () + { + var instance = new ImplementationLibrary (); + instance.GetSomeValue (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemovedInCopyAssembly.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemovedInCopyAssembly.cs new file mode 100644 index 000000000..3472be667 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/UsedTransitiveForwarderIsResolvedAndFacadeRemovedInCopyAssembly.cs @@ -0,0 +1,30 @@ +// 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. + +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies; + +namespace Mono.Linker.Tests.Cases.TypeForwarding +{ + [SetupCompileBefore ("SecondForwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })] + [SetupCompileBefore ("FirstForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "SecondForwarder.dll" })] + + // After compiling the test case we then replace the reference impl with implementation + type forwarder + [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })] + [SetupCompileAfter ("SecondForwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })] + [SetupLinkerAction ("copy", "Implementation")] + + [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")] + [RemovedMemberInAssembly ("Implementation.dll", nameof (ImplementationStruct))] + class UsedTransitiveForwarderIsResolvedAndFacadeRemovedInCopyAssembly + { + static void Main () + { + var instance = new ImplementationLibrary (); + instance.GetSomeValue (); + } + } +}
\ No newline at end of file diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs index 0e87979f4..41bff0e3b 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs @@ -1,5 +1,6 @@ using Mono.Cecil; using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.TestCasesRunner { @@ -8,7 +9,10 @@ namespace Mono.Linker.Tests.TestCasesRunner public static bool IsAssemblyAssertion (CustomAttribute attr) { - return attr.AttributeType.Name == nameof (KeptAssemblyAttribute) || attr.AttributeType.Name == nameof (RemovedAssemblyAttribute); + return attr.AttributeType.Name == nameof (KeptAssemblyAttribute) || + attr.AttributeType.Name == nameof (RemovedAssemblyAttribute) || + attr.AttributeType.Name == nameof (SetupLinkerActionAttribute) || + attr.AttributeType.Name == nameof (SetupLinkerTrimModeAttribute); } public static bool IsSymbolAssertion (CustomAttribute attr) diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index f0e2fd4cb..66ee602a5 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; using Mono.Linker.Tests.Extensions; using NUnit.Framework; @@ -108,6 +109,8 @@ namespace Mono.Linker.Tests.TestCasesRunner void PerformOutputAssemblyChecks (AssemblyDefinition original, NPath outputDirectory) { var assembliesToCheck = original.MainModule.Types.SelectMany (t => t.CustomAttributes).Where (attr => ExpectationsProvider.IsAssemblyAssertion (attr)); + var actionAssemblies = new HashSet<string> (); + bool trimModeIsCopy = false; foreach (var assemblyAttr in assembliesToCheck) { var name = (string) assemblyAttr.ConstructorArguments.First ().Value; @@ -117,9 +120,29 @@ namespace Mono.Linker.Tests.TestCasesRunner Assert.IsFalse (expectedPath.FileExists (), $"Expected the assembly {name} to not exist in {outputDirectory}, but it did"); else if (assemblyAttr.AttributeType.Name == nameof (KeptAssemblyAttribute)) Assert.IsTrue (expectedPath.FileExists (), $"Expected the assembly {name} to exist in {outputDirectory}, but it did not"); - else + else if (assemblyAttr.AttributeType.Name == nameof (SetupLinkerActionAttribute)) { + string assemblyName = (string) assemblyAttr.ConstructorArguments[1].Value; + if ((string) assemblyAttr.ConstructorArguments[0].Value == "copy") { + VerifyCopyAssemblyIsKeptUnmodified (outputDirectory, assemblyName + (assemblyName == "test" ? ".exe" : ".dll")); + } + + actionAssemblies.Add (assemblyName); + } else if (assemblyAttr.AttributeType.Name == nameof (SetupLinkerTrimModeAttribute)) { + // We delay checking that everything was copied after processing all assemblies + // with a specific action, since assembly action wins over trim mode. + if ((string) assemblyAttr.ConstructorArguments[0].Value == "copy") + trimModeIsCopy = true; + } else throw new NotImplementedException ($"Unknown assembly assertion of type {assemblyAttr.AttributeType}"); } + + if (trimModeIsCopy) { + foreach (string assemblyName in Directory.GetFiles (Directory.GetParent (outputDirectory).ToString (), "input")) { + var fileInfo = new FileInfo (assemblyName); + if (fileInfo.Extension == ".dll" && !actionAssemblies.Contains (assemblyName)) + VerifyCopyAssemblyIsKeptUnmodified (outputDirectory, assemblyName + (assemblyName == "test" ? ".exe" : ".dll")); + } + } } void PerformOutputSymbolChecks (AssemblyDefinition original, NPath outputDirectory) @@ -212,12 +235,19 @@ namespace Mono.Linker.Tests.TestCasesRunner } var expectedTypeName = checkAttrInAssembly.ConstructorArguments[1].Value.ToString (); - var linkedType = linkedAssembly.MainModule.GetType (expectedTypeName); + TypeDefinition linkedType = linkedAssembly.MainModule.GetType (expectedTypeName); if (linkedType == null && linkedAssembly.MainModule.HasExportedTypes) { - linkedType = linkedAssembly.MainModule.ExportedTypes - .FirstOrDefault (exported => exported.FullName == expectedTypeName) - ?.Resolve (); + ExportedType exportedType = linkedAssembly.MainModule.ExportedTypes + .FirstOrDefault (exported => exported.FullName == expectedTypeName); + + // Note that copied assemblies could have dangling references. + if (exportedType != null && original.EntryPoint.DeclaringType.CustomAttributes.FirstOrDefault ( + ca => ca.AttributeType.Name == nameof (RemovedAssemblyAttribute) + && ca.ConstructorArguments[0].Value.ToString () == exportedType.Scope.Name + ".dll") != null) + continue; + + linkedType = exportedType?.Resolve (); } switch (attributeTypeName) { @@ -374,6 +404,17 @@ namespace Mono.Linker.Tests.TestCasesRunner Assert.Fail ($"Invalid test assertion. No member named `{memberName}` exists on the original type `{originalType}`"); } + void VerifyCopyAssemblyIsKeptUnmodified (NPath outputDirectory, string assemblyName) + { + string inputAssemblyPath = Path.Combine (Directory.GetParent (outputDirectory).ToString (), "input", assemblyName); + string outputAssemblyPath = Path.Combine (outputDirectory, assemblyName); + Assert.IsTrue (File.ReadAllBytes (inputAssemblyPath).SequenceEqual (File.ReadAllBytes (outputAssemblyPath)), + $"Expected assemblies\n" + + $"\t{inputAssemblyPath}\n" + + $"\t{outputAssemblyPath}\n" + + $"binaries to be equal, since the input assembly has copy action."); + } + void VerifyCustomAttributeKept (ICustomAttributeProvider provider, string expectedAttributeTypeName) { var match = provider.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.FullName == expectedAttributeTypeName); @@ -567,7 +608,11 @@ namespace Mono.Linker.Tests.TestCasesRunner void VerifyKeptReferencesInAssembly (CustomAttribute inAssemblyAttribute) { var assembly = ResolveLinkedAssembly (inAssemblyAttribute.ConstructorArguments[0].Value.ToString ()); - var expectedReferenceNames = ((CustomAttributeArgument[]) inAssemblyAttribute.ConstructorArguments[1].Value).Select (attr => (string) attr.Value); + var expectedReferenceNames = ((CustomAttributeArgument[]) inAssemblyAttribute.ConstructorArguments[1].Value).Select (attr => (string) attr.Value).ToList (); + for (int i = 0; i < expectedReferenceNames.Count (); i++) + if (expectedReferenceNames[i].EndsWith (".dll")) + expectedReferenceNames[i] = expectedReferenceNames[i].Substring (0, expectedReferenceNames[i].LastIndexOf (".")); + Assert.That (assembly.MainModule.AssemblyReferences.Select (asm => asm.Name), Is.EquivalentTo (expectedReferenceNames)); } |