Exemple #1
0
        private static void CopyFiles(RunStartParams rsp, string solutionGrandParentPath, string folder, SearchOption searchOpt)
        {
            if (!new DirectoryInfo(folder).Exists)
            {
                return;
            }

            foreach (var src in Directory.EnumerateFiles(folder, "*", searchOpt))
            {
                var shouldExlclude = rsp.Config.SnapshotExcludePatterns.Any(item => src.IndexOf(item, 0, StringComparison.OrdinalIgnoreCase) >= 0);
                if (shouldExlclude)
                {
                    continue;
                }

                var dst     = src.ToUpperInvariant().Replace(solutionGrandParentPath.ToUpperInvariant(), rsp.Config.SnapShotRoot);
                var srcInfo = new FileInfo(src);
                var dstInfo = new FileInfo(dst);

                if (srcInfo.LastWriteTimeUtc > dstInfo.LastWriteTimeUtc)
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(dst));
                    Logger.LogInfo("Copying: {0} - {1}.", src, dst);
                    File.Copy(src, dst, true);
                }
            }
        }
Exemple #2
0
        private static RunStepResult DiscoverUnitTests(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            if (!host.CanContinue())
            {
                throw new OperationCanceledException();
            }

            var output = RunTestHost("discover", rsp);

            RunStepStatus rss = RunStepStatus.Succeeded;

            if (output.Item1 != 0)
            {
                rss = RunStepStatus.Failed;
            }

            var testsPerAssembly = PerDocumentLocationDTestCases.Deserialize(FilePath.NewFilePath(rsp.DataFiles.DiscoveredUnitDTestsStore.Item));

            var totalTests = testsPerAssembly.Values.Aggregate(0, (acc, e) => acc + e.Count);

            TelemetryClient.TrackEvent(rsi.name.Item, new Dictionary <string, string>(), new Dictionary <string, double> {
                { "TestCount", totalTests }
            });

            return(rss.ToRSR(RunData.NewTestCases(testsPerAssembly), "Unit Tests Discovered - which ones - TBD"));
        }
Exemple #3
0
 public void OnRunEnded(RunStartParams rsp)
 {
     DispatcherHelper.CheckBeginInvokeOnUI(
         () =>
     {
         AddTextToConsole(sb => sb.AppendFormat("### Ended run."));
         EngineLoader.EnableEngine();
     });
 }
Exemple #4
0
        private static Tuple <int, string> RunTestHost(string command, RunStartParams rsp)
        {
            string testRunnerPath = rsp.TestHostPath.Item;
            var    output         = ExecuteProcess(
                testRunnerPath,
                Core.TestHost.buildCommandLine(command, rsp)
                );

            return(output);
        }
 public static void Instrument(IRunExecutorHost host, RunStartParams rsp, Func <DocumentLocation, IEnumerable <DTestCase> > findTest)
 {
     try
     {
         InstrumentImpl(host, rsp, findTest);
     }
     catch (Exception e)
     {
         Logger.LogError("Failed to instrument. Exception: {0}", e);
     }
 }
Exemple #6
0
 public void OnRunStarting(RunStartParams rd)
 {
     DispatcherHelper.CheckBeginInvokeOnUI(
         () =>
     {
         RaisePropertyChanged(() => IsRunInProgress);
         ClearTextFields();
         AddTextToConsole(
             sb => sb.AppendFormat("### Starting new run..."));
     });
 }
Exemple #7
0
        private static RunStepResult DiscoverSequencePoints(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            var sequencePoint = Instrumentation.GenerateSequencePointInfo(host, rsp);

            if (sequencePoint != null)
            {
                sequencePoint.Serialize(rsp.DataFiles.SequencePointStore);
            }

            var totalSP = sequencePoint.Values.Aggregate(0, (acc, e) => acc + e.Count);

            TelemetryClient.TrackEvent(rsi.name.Item, new Dictionary <string, string>(), new Dictionary <string, double> {
                { "SequencePointCount", totalSP }
            });

            return(RunStepStatus.Succeeded.ToRSR(RunData.NewSequencePoints(sequencePoint), "Binaries Instrumented - which ones - TBD"));
        }
Exemple #8
0
        private static RunStepResult DeleteBuildOutput(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            if (Directory.Exists(rsp.Solution.BuildRoot.Item))
            {
                foreach (var file in Directory.EnumerateFiles(rsp.Solution.BuildRoot.Item, "*.pdb"))
                {
                    File.Delete(file);

                    var dll = Path.ChangeExtension(file, "dll");
                    if (File.Exists(dll))
                    {
                        File.Delete(dll);
                    }
                }
            }

            return(RunStepStatus.Succeeded.ToRSR(RunData.NoData, "What was done - TBD"));
        }
Exemple #9
0
        private static RunStepResult TakeSolutionSnapshot(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            var solutionGrandParentPath = Path.GetDirectoryName(Path.GetDirectoryName(rsp.Solution.Path.Item));
            var projects = VsSolution.GetProjects(host.HostVersion, rsp.Solution.Path.Item).ToList();

            var toCopy = new List <Tuple <string, SearchOption> >
            {
                new Tuple <string, SearchOption>(Path.GetDirectoryName(rsp.Solution.Path.Item), SearchOption.TopDirectoryOnly),
            };

            Array.ForEach(rsp.Config.SnapshotIncludeFolders,
                          item =>
            {
                toCopy.Add(new Tuple <string, SearchOption>(Path.Combine(Path.GetDirectoryName(rsp.Solution.Path.Item), item), SearchOption.AllDirectories));
            });

            projects.ForEach(p =>
            {
                var projectFile = Path.Combine(Path.GetDirectoryName(rsp.Solution.Path.Item), p.RelativePath);
                var folder      = Path.GetDirectoryName(projectFile);
                toCopy.Add(new Tuple <string, SearchOption>(folder, SearchOption.AllDirectories));
            });

            toCopy.ForEach(item =>
            {
                if (!host.CanContinue())
                {
                    throw new OperationCanceledException();
                }

                CopyFiles(rsp, solutionGrandParentPath, item.Item1, item.Item2);
            });

            SnapshotGC.mark(FilePath.NewFilePath(Path.GetDirectoryName(rsp.Solution.SnapshotPath.Item)));

            TelemetryClient.TrackEvent(rsi.name.Item, new Dictionary <string, string>(), new Dictionary <string, double> {
                { "ProjectCount", projects.Count }
            });

            return(RunStepStatus.Succeeded.ToRSR(RunData.NoData, "What was done - TBD"));
        }
Exemple #10
0
        private static RunStepResult RunTests(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            if (!host.CanContinue())
            {
                throw new OperationCanceledException();
            }

            var output = RunTestHost("execute", rsp);

            RunStepStatus rss = RunStepStatus.Succeeded;

            if (output.Item1 != 0)
            {
                rss = RunStepStatus.Failed;
            }

            var testResults     = PerTestIdDResults.Deserialize(FilePath.NewFilePath(rsp.DataFiles.TestResultsStore.Item));
            var coverageSession = PerSequencePointIdTestRunId.Deserialize(FilePath.NewFilePath(rsp.DataFiles.CoverageSessionStore.Item));
            var testFailureInfo = PerDocumentLocationTestFailureInfo.Deserialize(FilePath.NewFilePath(rsp.DataFiles.TestFailureInfoStore.Item));

            return(rss.ToRSR(RunData.NewTestRunOutput(testResults, testFailureInfo, coverageSession), output.Item2));
        }
Exemple #11
0
        private static RunStepResult BuildSolutionSnapshot(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            var output = ExecuteProcess(
                Path.Combine(
                    Environment.GetEnvironmentVariable("ProgramFiles(x86)"),
                    string.Format(@"MSBuild\{0}\Bin\msbuild.exe", host.HostVersion)),
                string.Format(
                    @"/m /v:minimal /p:DebugSymbols=true /p:DebugType=full /p:Optimize=false /p:Configuration=Debug /p:CreateVsixContainer=false /p:DeployExtension=false /p:CopyVsixExtensionFiles=false /p:RunCodeAnalysis=false {0} /p:OutDir=""{1}\\"" ""{2}""",
                    string.Join(" ", (rsp.Config.AdditionalMSBuildProperties ?? new string[0]).Select(it => string.Format("/p:{0}", it))),
                    rsp.Solution.BuildRoot.Item,
                    rsp.Solution.SnapshotPath.Item)
                );

            RunStepStatus rss = RunStepStatus.Succeeded;

            if (output.Item1 != 0)
            {
                rss = RunStepStatus.Failed;
            }

            return(rss.ToRSR(RunData.NoData, output.Item2));
        }
        private static Tuple <bool, TestId> IsSequencePointAtStartOfAUnitTest(RunStartParams rsp, Mono.Cecil.Cil.SequencePoint sp, FilePath assemblyPath, Func <DocumentLocation, IEnumerable <DTestCase> > findTest)
        {
            if (sp == null)
            {
                return(new Tuple <bool, TestId>(false, null));
            }

            var dl = new DocumentLocation {
                document = PathBuilder.rebaseCodeFilePath(rsp.Solution.Path, rsp.Solution.SnapshotPath, FilePath.NewFilePath(sp.Document.Url)), line = DocumentCoordinate.NewDocumentCoordinate(sp.StartLine)
            };
            var test = findTest(dl).FirstOrDefault(t => t.Source.Equals(assemblyPath));

            if (test == null)
            {
                return(new Tuple <bool, TestId>(false, null));
            }
            else
            {
                return(new Tuple <bool, TestId>(
                           true,
                           new TestId(assemblyPath, dl)));
            }
        }
        private static void FindSequencePointForType(RunStartParams rsp, PerDocumentSequencePoints perDocSP, ModuleDefinition module, TypeDefinition type)
        {
            foreach (MethodDefinition meth in type.Methods)
            {
                if (IsMethodSkipped(meth))
                {
                    continue;
                }

                var sps = from i in meth.Body.Instructions
                          where i.SequencePoint != null
                          where i.SequencePoint.StartLine != 0xfeefee
                          select new { module, meth, i.SequencePoint };

                int id = 0;
                foreach (var sp in sps)
                {
                    var fp     = PathBuilder.rebaseCodeFilePath(rsp.Solution.Path, rsp.Solution.SnapshotPath, FilePath.NewFilePath(sp.SequencePoint.Document.Url));
                    var seqPts = perDocSP.GetOrAdd(fp, _ => new ConcurrentBag <R4nd0mApps.TddStud10.Common.Domain.SequencePoint>());

                    seqPts.Add(new R4nd0mApps.TddStud10.Common.Domain.SequencePoint
                    {
                        id = new SequencePointId
                        {
                            methodId = new MethodId(AssemblyId.NewAssemblyId(sp.module.Mvid), MdTokenRid.NewMdTokenRid(sp.meth.MetadataToken.RID)),
                            uid      = id++
                        },
                        document    = fp,
                        startLine   = DocumentCoordinate.NewDocumentCoordinate(sp.SequencePoint.StartLine),
                        startColumn = DocumentCoordinate.NewDocumentCoordinate(sp.SequencePoint.StartColumn),
                        endLine     = DocumentCoordinate.NewDocumentCoordinate(sp.SequencePoint.EndLine),
                        endColumn   = DocumentCoordinate.NewDocumentCoordinate(sp.SequencePoint.EndColumn),
                    });
                }
            }
        }
        private static PerDocumentSequencePoints GenerateSequencePointInfoImpl(IRunExecutorHost host, RunStartParams rsp)
        {
            var timeFilter      = rsp.StartTime;
            var buildOutputRoot = rsp.Solution.BuildRoot.Item;

            Logger.LogInfo(
                "Generating sequence point info: Time filter - {0}, Build output root - {1}.",
                timeFilter.ToLocalTime(),
                buildOutputRoot);

            var perDocSP = new PerDocumentSequencePoints();

            Engine.Engine.FindAndExecuteForEachAssembly(
                host,
                buildOutputRoot,
                timeFilter,
                (string assemblyPath) =>
            {
                Logger.LogInfo("Generating sequence point info for {0}.", assemblyPath);

                var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters {
                    ReadSymbols = true
                });

                VisitAllTypes(
                    assembly.Modules,
                    (m, t) =>
                {
                    FindSequencePointForType(rsp, perDocSP, m, t);
                });
            });

            return(perDocSP);
        }
        private static void InstrumentType(RunStartParams rsp, Func <DocumentLocation, IEnumerable <DTestCase> > findTest, string assemblyPath, Func <string, string> rebaseDocument, MethodReference enterSPMR, MethodReference exitUTMR, ModuleDefinition module, TypeDefinition type)
        {
            foreach (MethodDefinition meth in type.Methods)
            {
                if (IsMethodSkipped(meth))
                {
                    continue;
                }

                meth.Body.SimplifyMacros();

                var spi = from i in meth.Body.Instructions
                          where i.SequencePoint != null
                          where i.SequencePoint.StartLine != 0xfeefee
                          select i;

                var spId         = 0;
                var instructions = spi.ToArray();
                foreach (var sp in instructions)
                {
                    if (sp.Previous != null &&
                        (sp.Previous.OpCode.Code == Code.Leave_S ||
                         sp.Previous.OpCode.Code == Code.Leave ||
                         sp.Previous.OpCode.Code == Code.Endfilter ||
                         sp.Previous.OpCode.Code == Code.Endfinally))
                    {
                        continue;
                    }

                    /**********************************************************************************/
                    /*                                PDB Path Replace                                */
                    /**********************************************************************************/
                    sp.SequencePoint.Document.Url = rebaseDocument(sp.SequencePoint.Document.Url);

                    /**********************************************************************************/
                    /*                            Inject Enter Sequence Point                         */
                    /**********************************************************************************/
                    Instruction instrMarker = sp;
                    Instruction instr       = null;
                    var         ilProcessor = meth.Body.GetILProcessor();

                    // IL_000d: call void R4nd0mApps.TddStud10.TestHost.Marker::EnterSequencePoint(string, ldstr, ldstr)
                    instr = ilProcessor.Create(OpCodes.Call, enterSPMR);
                    ilProcessor.InsertBefore(instrMarker, instr);
                    instrMarker = instr;
                    // IL_000b: ldstr <spid>
                    instr = ilProcessor.Create(OpCodes.Ldstr, (spId++).ToString());
                    ilProcessor.InsertBefore(instrMarker, instr);
                    instrMarker = instr;
                    // IL_0006: ldstr <mdtoken>
                    instr = ilProcessor.Create(OpCodes.Ldstr, meth.MetadataToken.RID.ToString());
                    ilProcessor.InsertBefore(instrMarker, instr);
                    instrMarker = instr;
                    // IL_0001: ldstr <assemblyId>
                    instr = ilProcessor.Create(OpCodes.Ldstr, module.Mvid.ToString());
                    ilProcessor.InsertBefore(instrMarker, instr);
                    instrMarker = instr;
                }

                /*************************************************************************************/
                /*                            Inject Exit Unit Test                                  */
                /*************************************************************************************/
                var ret = IsSequencePointAtStartOfAUnitTest(rsp, spi.Select(i => i.SequencePoint).FirstOrDefault(), FilePath.NewFilePath(assemblyPath), findTest);
                if (ret.Item1)
                {
                    // NOTE: Reeeealy need to bring this class under test. Commenting out the void check as Property tests can return boolean.
                    if (!meth.IsConstructor /*&& meth.ReturnType == module.TypeSystem.Void*/ && !meth.IsAsync())
                    {
                        InjectExitUtCallInsideMethodWiseFinally(module, meth, ret.Item2, exitUTMR);
                    }
                    else
                    {
                        Logger.LogError("Instrumentation: Unsupported method type: IsConstructo = {0}, Return Type = {1}, IsAsync = {2}.", meth.IsConstructor, meth.ReturnType, meth.IsAsync());
                    }
                }

                meth.Body.InitLocals = true;
                meth.Body.OptimizeMacros();
            }
        }
        public static PerDocumentSequencePoints GenerateSequencePointInfo(IRunExecutorHost host, RunStartParams rsp)
        {
            try
            {
                return(GenerateSequencePointInfoImpl(host, rsp));
            }
            catch (Exception e)
            {
                Logger.LogError("Failed to instrument. Exception: {0}", e);
            }

            return(null);
        }
        private static void InstrumentImpl(IRunExecutorHost host, RunStartParams rsp, Func <DocumentLocation, IEnumerable <DTestCase> > findTest)
        {
            var timeFilter      = rsp.StartTime;
            var solutionRoot    = Path.GetDirectoryName(rsp.Solution.Path.Item);
            var buildOutputRoot = rsp.Solution.BuildRoot.Item;

            Logger.LogInfo(
                "Instrumenting: Time filter - {0}, Build output root - {1}.",
                timeFilter.ToLocalTime(),
                buildOutputRoot);

            System.Reflection.StrongNameKeyPair snKeyPair = null;
            var snKeyFile = Directory.EnumerateFiles(solutionRoot, "*.snk").FirstOrDefault();

            if (snKeyFile != null)
            {
                snKeyPair = new System.Reflection.StrongNameKeyPair(File.ReadAllBytes(snKeyFile));
                Logger.LogInfo("Using strong name from {0}.", snKeyFile);
            }

            var asmResolver = new DefaultAssemblyResolver();

            Array.ForEach(asmResolver.GetSearchDirectories(), asmResolver.RemoveSearchDirectory);
            asmResolver.AddSearchDirectory(buildOutputRoot);
            var readerParams = new ReaderParameters
            {
                AssemblyResolver = asmResolver,
                ReadSymbols      = true,
            };

            string testRunnerPath = Path.GetFullPath(typeof(R4nd0mApps.TddStud10.TestRuntime.Marker).Assembly.Location);
            var    enterSPMD      = from t in ModuleDefinition.ReadModule(testRunnerPath).GetTypes()
                                    where t.Name == "Marker"
                                    from m in t.Methods
                                    where m.Name == "EnterSequencePoint"
                                    select m;

            var exitUTMD = from t in ModuleDefinition.ReadModule(testRunnerPath).GetTypes()
                           where t.Name == "Marker"
                           from m in t.Methods
                           where m.Name == "ExitUnitTest"
                           select m;

            Func <string, string> rebaseDocument = s => PathBuilder.rebaseCodeFilePath(rsp.Solution.Path, rsp.Solution.SnapshotPath, FilePath.NewFilePath(s)).Item;

            Engine.Engine.FindAndExecuteForEachAssembly(
                host,
                buildOutputRoot,
                timeFilter,
                (string assemblyPath) =>
            {
                Logger.LogInfo("Instrumenting {0}.", assemblyPath);

                var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, readerParams);
                var hasSn    = assembly.Name.HasPublicKey;

                /*
                 * IL_0001: ldstr <assemblyId>
                 * IL_0006: ldstr <mdtoken>
                 * IL_000b: ldstr <spid>
                 * IL_000d: call void R4nd0mApps.TddStud10.TestHost.Marker::ExitUnitTest(string, ldstr, ldstr)
                 */
                MethodReference enterSPMR = assembly.MainModule.Import(enterSPMD.First());
                MethodReference exitUTMR  = assembly.MainModule.Import(exitUTMD.First());

                VisitAllTypes(
                    assembly.Modules,
                    (m, t) =>
                {
                    InstrumentType(rsp, findTest, assemblyPath, rebaseDocument, enterSPMR, exitUTMR, m, t);
                });

                var backupAssemblyPath = Path.ChangeExtension(assemblyPath, ".original");
                File.Delete(backupAssemblyPath);
                File.Move(assemblyPath, backupAssemblyPath);
                try
                {
                    assembly.Write(assemblyPath, new WriterParameters {
                        WriteSymbols = true, StrongNameKeyPair = hasSn ? snKeyPair : null
                    });
                }
                catch
                {
                    Logger.LogInfo("Backing up or instrumentation failed. Attempting to revert back changes to {0}.", assemblyPath);
                    File.Delete(assemblyPath);
                    File.Move(backupAssemblyPath, assemblyPath);
                    throw;
                }
            },
                1);
        }
Exemple #18
0
 public void OnRunStarting(object _, RunStartParams rd)
 {
 }
Exemple #19
0
        private static RunStepResult RefreshTestRuntime(IRunExecutorHost host, RunStartParams rsp, RunStepInfo rsi)
        {
            var output = TestRunTimeInstaller.Install(rsp.Solution.BuildRoot.Item);

            return(RunStepStatus.Succeeded.ToRSR(RunData.NoData, string.Format("Copied Test Runtime: {0}", output)));
        }
Exemple #20
0
 public void OnRunEnded(object _, RunStartParams rsp)
 {
 }