Esempio n. 1
0
        public static TestResult ExecuteVandelayTestRun(
            this BaseModuleWeaver weaver,
            string assemblyPath,
            bool runPeVerify = true,
            Action <ModuleDefinition> afterExecuteCallback  = null,
            Action <ModuleDefinition> beforeExecuteCallback = null,
            string assemblyName = null,
            IEnumerable <string> ignoreCodes = null,
            bool purgeTempDir = true,
            StrongNameKeyPair strongNameKeyPair = null)
        {
            assemblyPath = Path.Combine(CodeBaseLocation.CurrentDirectory, assemblyPath);
            var fodyTempDir = Path.Combine(Path.GetDirectoryName(assemblyPath), "fodytemp");

            Directory.CreateDirectory(fodyTempDir);

            if (purgeTempDir)
            {
                var info = new DirectoryInfo(fodyTempDir);

                foreach (var file in info.GetFiles())
                {
                    file.Delete();
                }

                foreach (var directory in info.GetDirectories())
                {
                    directory.Delete(true);
                }
            }

            string targetFileName;

            if (assemblyName == null)
            {
                assemblyName   = Path.GetFileNameWithoutExtension(assemblyPath);
                targetFileName = Path.GetFileName(assemblyPath);
            }
            else
            {
                targetFileName = assemblyName + ".dll";
            }

            var targetAssemblyPath = Path.Combine(fodyTempDir, targetFileName);

            using (var assemblyResolver = new TestAssemblyResolver())
            {
                var typeCache = CacheTypes(weaver, assemblyResolver.Resolve);

                var testStatus = new TestResult();

                var addMessageInfo = typeof(TestResult).GetMethod("AddMessage",
                                                                  BindingFlags.NonPublic | BindingFlags.Instance);
                Debug.Assert(addMessageInfo != null, $"{nameof(addMessageInfo)} != null");
                var addMessage = addMessageInfo
                                 .CreateDelegate <Action <string, MessageImportance> >(testStatus);

                var addWarningInfo = typeof(TestResult).GetMethod("AddWarning",
                                                                  BindingFlags.NonPublic | BindingFlags.Instance);
                Debug.Assert(addWarningInfo != null, $"{nameof(addWarningInfo)} != null");
                var addWarning = addWarningInfo
                                 .CreateDelegate <Action <string, SequencePoint> >(testStatus);

                var addErrorInfo = typeof(TestResult).GetMethod("AddError",
                                                                BindingFlags.NonPublic | BindingFlags.Instance);
                Debug.Assert(addErrorInfo != null, $"{nameof(addErrorInfo)} != null");
                var addError = addErrorInfo
                               .CreateDelegate <Action <string, SequencePoint> >(testStatus);

                weaver.LogDebug         = text => addMessage(text, MessageImportanceDefaults.Debug);
                weaver.LogInfo          = text => addMessage(text, MessageImportanceDefaults.Info);
                weaver.LogMessage       = (text, messageImportance) => addMessage(text, messageImportance);
                weaver.LogWarning       = text => addWarning(text, null);
                weaver.LogWarningPoint  = (text, sequencePoint) => addWarning(text, sequencePoint);
                weaver.LogError         = text => addError(text, null);
                weaver.LogErrorPoint    = (text, sequencePoint) => addError(text, sequencePoint);
                weaver.AssemblyFilePath = assemblyPath;
                weaver.FindType         = typeCache.FindType;
                weaver.TryFindType      = typeCache.TryFindType;
                weaver.ResolveAssembly  = assemblyResolver.Resolve;

                var readerProviderType = typeof(BaseModuleWeaver).Assembly
                                         .GetType("SymbolReaderProvider", true);
                var readerProvider = (ISymbolReaderProvider)Activator.CreateInstance(readerProviderType);

                var readerParameters = new ReaderParameters
                {
                    AssemblyResolver     = assemblyResolver,
                    SymbolReaderProvider = readerProvider,
                    ReadWrite            = false,
                    ReadSymbols          = true,
                };

                using (var module = ModuleDefinition.ReadModule(assemblyPath, readerParameters))
                {
                    module.Assembly.Name.Name = assemblyName;
                    weaver.ModuleDefinition   = module;
                    weaver.TypeSystem         = new TypeSystem(typeCache.FindType, module);
                    beforeExecuteCallback?.Invoke(module);

                    weaver.Execute();

                    var referenceCleanerType = typeof(BaseModuleWeaver).Assembly
                                               .GetType("ReferenceCleaner", true);
                    var cleanReferencesInfo = referenceCleanerType.GetMethod("CleanReferences");
                    Debug.Assert(cleanReferencesInfo != null, nameof(cleanReferencesInfo) + " != null");
                    var cleaner = cleanReferencesInfo
                                  .CreateDelegate <Action <ModuleDefinition, BaseModuleWeaver, Action <string> > >();
                    cleaner(module, weaver, weaver.LogDebug);

                    afterExecuteCallback?.Invoke(module);

                    var writerParameters = new WriterParameters
                    {
                        StrongNameKeyPair = strongNameKeyPair,
                        WriteSymbols      = true
                    };

                    module.Write(targetAssemblyPath, writerParameters);
                }

                if (runPeVerify && IsWindows())
                {
                    var ignoreList = ignoreCodes == null ? new List <string>() : ignoreCodes.ToList();

                    PeVerifier.ThrowIfDifferent(assemblyPath, targetAssemblyPath, ignoreList,
                                                Path.GetDirectoryName(assemblyPath));
                }

#if NETSTANDARD
                AppDomain.CurrentDomain.AssemblyResolve += (_, args) =>
                {
                    var tempAssemblyPath = Path.Combine(fodyTempDir, new AssemblyName(args.Name).Name + ".dll");
                    return(!File.Exists(tempAssemblyPath) ? null : Assembly.LoadFrom(tempAssemblyPath));
                };
#endif

                typeof(TestResult).GetMethod("set_Assembly",
                                             BindingFlags.NonPublic | BindingFlags.Instance)
                .Invoke(testStatus, new object[]
                {
                    Assembly.Load(AssemblyName.GetAssemblyName(targetAssemblyPath))
                });
                typeof(TestResult).GetMethod("set_AssemblyPath",
                                             BindingFlags.NonPublic | BindingFlags.Instance)
                .Invoke(testStatus, new object[]
                {
                    targetAssemblyPath
                });
                return(testStatus);
            }
        }