private void CollectCoverage(byte[] instrumentedAssembly) { AppDomain domain = AppDomain.CreateDomain("Instrumentation", null, new AppDomainSetup() { ConfigurationFile = appConfigPath, ApplicationBase = outputPath }); AssemblyLoader handler = (AssemblyLoader)domain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName); handler.Setup(dependencies, instrumentedAssembly, testAssembly); MSTestRunner test = (MSTestRunner)domain.CreateInstanceFromAndUnwrap(typeof(MSTestRunner).Assembly.Location, typeof(MSTestRunner).FullName); test.SetupCoverage(CoverageData.GetInstance().LineLocatorIDs, CoverageData.GetInstance().reverseLineLocatorIDs); Dictionary <string, Dictionary <int, long> > lineCountsByTests = test.RunTestsForCoverage(testAssembly); testCaseCoverageByLineID = new Dictionary <int, List <string> >(); foreach (var pair in lineCountsByTests) { foreach (var pair2 in pair.Value) { int lineID = pair2.Key; if (!testCaseCoverageByLineID.ContainsKey(lineID)) { testCaseCoverageByLineID[lineID] = new List <string>(); } testCaseCoverageByLineID[lineID].Add(pair.Key); } } AppDomain.Unload(domain); }
private MutationResult MutateDocumentAndTestProject(SyntaxTree tree) { List <ExportedMutantInfo> killedMutants = new List <ExportedMutantInfo>(); List <ExportedMutantInfo> liveMutants = new List <ExportedMutantInfo>(); Task <SyntaxNode> getTree = tree.GetRootAsync(); int appdomainid = 0; getTree.ContinueWith((Task <SyntaxNode> task) => { // TODO: create a Walker that calls a Decorator yield chain to produce mutants. SyntaxNode root = task.Result; MutatingWalker walker = new MutatingWalker(new BaseMutatorImpl(projectCompiler), (mutantInfo) => { // TODO: need to separate OnMutant into per-test-runner classes SyntaxNode original = mutantInfo.original; SyntaxNode mutant = mutantInfo.mutant; var newRoot = root.ReplaceNode(original, mutant); byte[] mutatedAssembly = null; try { var mutantCompiler = projectCompiler .ReplaceSyntaxTree(root.SyntaxTree, newRoot.SyntaxTree); mutatedAssembly = CompileAssembly(mutantCompiler); } catch (Exception e) { // Compile errors are a really bad sign and are indicative of bugs in the mutation. // ALWAYS debug these. Debug.Print("Compile error trying to mutate " + original.ToString() + " to " + mutant.ToString() + " , reason: " + e.ToString()); return(false); } // build app domain AppDomain mutantDomain = AppDomain.CreateDomain("Mutant " + appdomainid++, null, new AppDomainSetup() { ConfigurationFile = appConfigPath, ApplicationBase = outputPath }); AssemblyLoader handler = (AssemblyLoader) mutantDomain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName); handler.Setup(dependencies, mutatedAssembly, testAssembly); // run mstestrunner in special abort mode MSTestRunner mutantTest = (MSTestRunner) mutantDomain.CreateInstanceFromAndUnwrap(typeof(MSTestRunner).Assembly.Location, typeof(MSTestRunner).FullName); mutantTest.SetupCoverage(CoverageData.GetInstance().LineLocatorIDs, CoverageData.GetInstance().reverseLineLocatorIDs); bool allPassed = true; // Ensure only one thread runs tests at a time. lock (_locker) { try { // TODO: create a fixed number of worker threads and give each thread its own directory. // Lock is needed because certain tests are writing files and are writing to the same locations. allPassed = mutantTest.RunTests(testAssembly, testCaseCoverageByLineID[mutantInfo.lineID]); } catch (Exception e) { Debug.Print(e.ToString()); return(true); // keep going to next mutation } } // TODO: need to be collecting tons of data about tests or RIP ExportedMutantInfo exportedInfo = new ExportedMutantInfo(mutantInfo); if (allPassed) { Task.Run(() => _onMutantLived(exportedInfo)); liveMutants.Add(exportedInfo); } else { Task.Run(() => _onMutantKilled(exportedInfo)); killedMutants.Add(exportedInfo); } AppDomain.Unload(mutantDomain); return(allPassed); }, CoverageData.GetInstance(), testCaseCoverageByLineID); walker.Visit(root); }).Wait(); return(new MutationResult(killedMutants.ToList(), liveMutants.ToList())); }