1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using Mono.Cecil; 5 using Mono.Linker.Tests.Cases.Expectations.Assertions; 6 using Mono.Linker.Tests.Cases.Expectations.Metadata; 7 using Mono.Linker.Tests.Extensions; 8 using Mono.Linker.Tests.TestCases; 9 10 namespace Mono.Linker.Tests.TestCasesRunner { 11 public class TestCaseMetadaProvider { 12 protected readonly TestCase _testCase; 13 protected readonly AssemblyDefinition _fullTestCaseAssemblyDefinition; 14 protected readonly TypeDefinition _testCaseTypeDefinition; 15 TestCaseMetadaProvider(TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition)16 public TestCaseMetadaProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition) 17 { 18 _testCase = testCase; 19 _fullTestCaseAssemblyDefinition = fullTestCaseAssemblyDefinition; 20 // The test case types are never nested so we don't need to worry about that 21 _testCaseTypeDefinition = fullTestCaseAssemblyDefinition.MainModule.GetType (_testCase.ReconstructedFullTypeName); 22 23 if (_testCaseTypeDefinition == null) 24 throw new InvalidOperationException ($"Could not find the type definition for {_testCase.Name} in {_testCase.SourceFile}"); 25 } 26 GetLinkerOptions()27 public virtual TestCaseLinkerOptions GetLinkerOptions () 28 { 29 var tclo = new TestCaseLinkerOptions { 30 Il8n = GetOptionAttributeValue (nameof (Il8nAttribute), "none"), 31 IncludeBlacklistStep = GetOptionAttributeValue (nameof (IncludeBlacklistStepAttribute), false), 32 KeepTypeForwarderOnlyAssemblies = GetOptionAttributeValue (nameof (KeepTypeForwarderOnlyAssembliesAttribute), string.Empty), 33 CoreAssembliesAction = GetOptionAttributeValue<string> (nameof (SetupLinkerCoreActionAttribute), null) 34 }; 35 36 foreach (var assemblyAction in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerActionAttribute))) 37 { 38 var ca = assemblyAction.ConstructorArguments; 39 tclo.AssembliesAction.Add (new KeyValuePair<string, string> ((string)ca [0].Value, (string)ca [1].Value)); 40 } 41 42 foreach (var additionalArgumentAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerArgumentAttribute))) 43 { 44 var ca = additionalArgumentAttr.ConstructorArguments; 45 var values = ((CustomAttributeArgument [])ca [1].Value)?.Select (arg => arg.Value.ToString ()).ToArray (); 46 tclo.AdditionalArguments.Add (new KeyValuePair<string, string []> ((string)ca [0].Value, values)); 47 } 48 49 return tclo; 50 } 51 GetReferencedAssemblies(NPath workingDirectory)52 public virtual IEnumerable<string> GetReferencedAssemblies (NPath workingDirectory) 53 { 54 yield return workingDirectory.Combine ("Mono.Linker.Tests.Cases.Expectations.dll").ToString (); 55 yield return "mscorlib.dll"; 56 57 foreach (var referenceAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (ReferenceAttribute))) { 58 yield return (string) referenceAttr.ConstructorArguments.First ().Value; 59 } 60 } 61 GetResources()62 public virtual IEnumerable<SourceAndDestinationPair> GetResources () 63 { 64 return _testCaseTypeDefinition.CustomAttributes 65 .Where (attr => attr.AttributeType.Name == nameof (SetupCompileResourceAttribute)) 66 .Select (GetSourceAndRelativeDestinationValue); 67 } 68 GetExtraLinkerSearchDirectories()69 public virtual IEnumerable<NPath> GetExtraLinkerSearchDirectories () 70 { 71 yield break; 72 } 73 IsIgnored(out string reason)74 public bool IsIgnored (out string reason) 75 { 76 var ignoreAttribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (IgnoreTestCaseAttribute)); 77 if (ignoreAttribute != null) { 78 reason = (string)ignoreAttribute.ConstructorArguments.First ().Value; 79 return true; 80 } 81 82 reason = null; 83 return false; 84 } 85 AdditionalFilesToSandbox()86 public virtual IEnumerable<SourceAndDestinationPair> AdditionalFilesToSandbox () 87 { 88 return _testCaseTypeDefinition.CustomAttributes 89 .Where (attr => attr.AttributeType.Name == nameof (SandboxDependencyAttribute)) 90 .Select (GetSourceAndRelativeDestinationValue); 91 } 92 GetSetupCompileAssembliesBefore()93 public virtual IEnumerable<SetupCompileInfo> GetSetupCompileAssembliesBefore () 94 { 95 return _testCaseTypeDefinition.CustomAttributes 96 .Where (attr => attr.AttributeType.Name == nameof (SetupCompileBeforeAttribute)) 97 .Select (CreateSetupCompileAssemblyInfo); 98 } 99 GetSetupCompileAssembliesAfter()100 public virtual IEnumerable<SetupCompileInfo> GetSetupCompileAssembliesAfter () 101 { 102 return _testCaseTypeDefinition.CustomAttributes 103 .Where (attr => attr.AttributeType.Name == nameof (SetupCompileAfterAttribute)) 104 .Select (CreateSetupCompileAssemblyInfo); 105 } 106 GetDefines()107 public virtual IEnumerable<string> GetDefines () 108 { 109 return _testCaseTypeDefinition.CustomAttributes 110 .Where (attr => attr.AttributeType.Name == nameof (DefineAttribute)) 111 .Select (attr => (string) attr.ConstructorArguments.First ().Value); 112 } 113 GetAssemblyName()114 public virtual string GetAssemblyName () 115 { 116 return GetOptionAttributeValue (nameof (SetupCompileAssemblyNameAttribute), "test.exe"); 117 } 118 GetSetupCompilerArguments()119 public virtual IEnumerable<string> GetSetupCompilerArguments () 120 { 121 return _testCaseTypeDefinition.CustomAttributes 122 .Where (attr => attr.AttributeType.Name == nameof (SetupCompileArgumentAttribute)) 123 .Select (attr => (string) attr.ConstructorArguments.First ().Value); 124 } 125 GetOptionAttributeValue(string attributeName, T defaultValue)126 T GetOptionAttributeValue<T> (string attributeName, T defaultValue) 127 { 128 var attribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == attributeName); 129 if (attribute != null) 130 return (T) attribute.ConstructorArguments.First ().Value; 131 132 return defaultValue; 133 } 134 GetSourceAndRelativeDestinationValue(CustomAttribute attribute)135 SourceAndDestinationPair GetSourceAndRelativeDestinationValue (CustomAttribute attribute) 136 { 137 var relativeSource = (string) attribute.ConstructorArguments.First ().Value; 138 var destinationFileName = (string) attribute.ConstructorArguments [1].Value; 139 var fullSource = _testCase.SourceFile.Parent.Combine (relativeSource); 140 return new SourceAndDestinationPair 141 { 142 Source = fullSource, 143 DestinationFileName = string.IsNullOrEmpty (destinationFileName) ? fullSource.FileName : destinationFileName 144 }; 145 } 146 CreateSetupCompileAssemblyInfo(CustomAttribute attribute)147 private SetupCompileInfo CreateSetupCompileAssemblyInfo (CustomAttribute attribute) 148 { 149 var ctorArguments = attribute.ConstructorArguments; 150 return new SetupCompileInfo 151 { 152 OutputName = (string) ctorArguments [0].Value, 153 SourceFiles = ((CustomAttributeArgument []) ctorArguments [1].Value).Select (arg => _testCase.SourceFile.Parent.Combine (arg.Value.ToString ())).ToArray (), 154 References = ((CustomAttributeArgument []) ctorArguments [2].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), 155 Defines = ((CustomAttributeArgument []) ctorArguments [3].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), 156 AddAsReference = ctorArguments.Count >= 5 ? (bool) ctorArguments [4].Value : true 157 }; 158 } 159 } 160 }