diff options
author | Mateo Torres-Ruiz <mateoatr@users.noreply.github.com> | 2021-04-06 22:59:55 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-06 22:59:55 +0300 |
commit | 2674d7d0c36159aa1aec2fb0a53fffecf50e5780 (patch) | |
tree | 40d94cc97a62f830f5d61c36cbfb64aa12675e20 /test/Mono.Linker.Tests | |
parent | 388fef00320370785b08bbc42dda4a87f3fa38ab (diff) |
Copy action behavior (#1941)
* Stop rewriting scopes for copy assemblies with removed references
* Keep exported types in copy assemblies
Mark dynamically accessed forwarders
Add tests
* Transitive forwarders are linked
* Keep copyused behavior
* Tests
* Mark type if it's exported
* PR feedback
* Transitively mark forwarders when a facade is dynamically accessed and has copy action
* Transitively mark forwarders
* Fix formatting
* Update MarkExportedType
* Keep mscorlib assert
* Mark forwarders when there's a type ref to an exported type in a copy assembly
* Update DependencyKind
* Keep forwarders when member ref is resolved from a copy assembly
* Add more tests, mark forwarded CAs
* Mark forwarded interfaces
* Simplify logic for typerefs
* Clean
* Keep ProcessInternalsVisibleAttributes in process while-loop
* Fix whitespace formatting
* Remove unused param
* Feedback
* Whitespace formatting
* Remove unnecessary assembly
* Add IL2104 warning
* Remove unnecessary marking
* Update comment
* Remove ExportedTypeExtensions
* Remove formatDiagnostics and revert cecil subm change
* Remove warning
* Comment out check for removed warning
* Update more of existing calls
* Reproduce attribute issue
* Update scopes before sweeping forwarders
* Remove my enum from compilation
* Fix formatting
* Keep same behavior for scopes in copyused assemblies
Co-authored-by: Marek Safar <marek.safar@gmail.com>
Co-authored-by: Sven Boemer <sbomer@gmail.com>
Diffstat (limited to 'test/Mono.Linker.Tests')
-rw-r--r-- | test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs | 6 | ||||
-rw-r--r-- | test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs | 57 |
2 files changed, 56 insertions, 7 deletions
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)); } |