public bool GetBranchPointsForFunction(string modulePath, int functionToken, out BranchPoint[] branchPoints) { branchPoints = new BranchPoint[0]; Class @class; var method = GetMethod(modulePath, functionToken, out @class); if (method != null && method.BranchPoints != null) { System.Diagnostics.Debug.WriteLine("Getting Branch points for {0}({1})", method.Name, method.MetadataToken); branchPoints = method.BranchPoints.ToArray(); return true; } return false; }
public void CanLoadExistingFileWhenInitialising() { // arrange var moduleHash = Guid.NewGuid().ToString(); var persistence = new FilePersistance(_mockCommandLine.Object, _mockLogger.Object); persistence.Initialise(_filePath, false); var point = new SequencePoint() // BranchPoints within SequencePoint shorther than 3 characters will be removed {StartLine = 1, EndLine = 1, StartColumn = 1, EndColumn = 4}; var branchPoint = new BranchPoint{Path = 0, OffsetPoints = new List<int>()}; var branchPoint2 = new BranchPoint { Path = 1, OffsetPoints = new List<int>{1,2}}; var file = new OpenCover.Framework.Model.File(); var filref = new FileRef() {UniqueId = file.UniqueId}; persistence.PersistModule(new Module { Summary = new Summary {NumSequencePoints = 1}, Files = new[] {file}, ModuleHash = moduleHash, Classes = new[] { new Class { Summary = new Summary {NumSequencePoints = 1}, Files = new[] {file}, Methods = new[] { new Method { FileRef = filref, MetadataToken = 1234, Summary = new Summary {NumSequencePoints = 1}, MethodPoint = point, SequencePoints = new[] {point}, BranchPoints = new[] {branchPoint, branchPoint2} } } } } }); persistence.Commit(); var persistence2 = new FilePersistance(_mockCommandLine.Object, _mockLogger.Object); // act persistence2.Initialise(_filePath, true); // assert Assert.IsNotNull(persistence2.CoverageSession); Assert.AreEqual(moduleHash, persistence2.CoverageSession.Modules[0].ModuleHash); Assert.AreEqual(point.UniqueSequencePoint, persistence2.CoverageSession.Modules[0].Classes[0].Methods[0].SequencePoints[0].UniqueSequencePoint); Assert.AreEqual(point.UniqueSequencePoint, persistence2.CoverageSession.Modules[0].Classes[0].Methods[0].MethodPoint.UniqueSequencePoint); var method = persistence2.CoverageSession.Modules[0].Classes[0].Methods[0]; var br1 = persistence2.CoverageSession.Modules[0].Classes[0].Methods[0].BranchPoints[0]; var br2 = persistence2.CoverageSession.Modules[0].Classes[0].Methods[0].BranchPoints[1]; Assert.AreEqual(branchPoint.UniqueSequencePoint, br1.UniqueSequencePoint); Assert.AreEqual(branchPoint2.UniqueSequencePoint, br2.UniqueSequencePoint); Assert.AreEqual(0, br1.OffsetPoints.Count); Assert.AreEqual(2, br2.OffsetPoints.Count); Assert.AreEqual(1, br2.OffsetPoints[0]); Assert.AreEqual(2, br2.OffsetPoints[1]); // the method and sequence point if point to same offset need to merge Assert.AreSame(method.MethodPoint, method.SequencePoints[0]); // the loaded summary object needs to be cleared Assert.AreEqual(0, persistence2.CoverageSession.Summary.NumSequencePoints); Assert.AreEqual(0, persistence2.CoverageSession.Modules[0].Summary.NumSequencePoints); Assert.AreEqual(0, persistence2.CoverageSession.Modules[0].Classes[0].Summary.NumSequencePoints); Assert.AreEqual(0, persistence2.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumSequencePoints); }
private void GetBranchPointsForToken(int token, List<BranchPoint> list) { var methodDefinition = GetMethodDefinition(token); if (methodDefinition == null) return; UInt32 ordinal = 0; int branchOffset = 0; int pathCounter = 0; List<int> PathOffsetList; foreach ( var instruction in methodDefinition.Body.Instructions ) { if ( instruction.OpCode.FlowControl != FlowControl.Cond_Branch ) continue; pathCounter = 0; // store branch origin offset branchOffset = instruction.Offset; Debug.Assert(!Object.ReferenceEquals(null, instruction.Next)); if ( Object.ReferenceEquals(null, instruction.Next) ) { return; } // Add Default branch (Path=0) Debug.Assert(pathCounter == 0); // Follow else/default instruction Instruction @else = instruction.Next; PathOffsetList = GetBranchPath(@else); Debug.Assert(PathOffsetList.Count > 0); // add Path 0 BranchPoint path0 = new BranchPoint() { Offset = branchOffset, Ordinal = ordinal++, Path = pathCounter++, OffsetPoints = PathOffsetList.Count > 1 ? PathOffsetList.GetRange(0, PathOffsetList.Count - 1) : new List<int>(), EndOffset = PathOffsetList.Last() }; Debug.Assert(!Object.ReferenceEquals(null, path0.OffsetPoints)); list.Add(path0); Debug.Assert(ordinal != 0); Debug.Assert(pathCounter != 0); // Add Conditional Branch (Path=1) if ( instruction.OpCode.Code != Code.Switch ) { // Follow instruction at operand Instruction @then = instruction.Operand as Instruction; Debug.Assert(!Object.ReferenceEquals(null, @then)); if ( Object.ReferenceEquals(null, @then) ) { return; } PathOffsetList = GetBranchPath(@then); Debug.Assert(PathOffsetList.Count > 0); // Add path 1 BranchPoint path1 = new BranchPoint() { Offset = branchOffset, Ordinal = ordinal++, Path = pathCounter++, OffsetPoints = PathOffsetList.Count > 1 ? PathOffsetList.GetRange(0, PathOffsetList.Count - 1) : new List<int>(), EndOffset = PathOffsetList.Last() }; Debug.Assert(!Object.ReferenceEquals(null, path1.OffsetPoints)); list.Add( path1 ); } else // instruction.OpCode.Code == Code.Switch { Instruction[] branchInstructions = instruction.Operand as Instruction[]; Debug.Assert(!Object.ReferenceEquals(null, branchInstructions)); Debug.Assert(branchInstructions.Length != 0); if ( Object.ReferenceEquals(null, branchInstructions) || branchInstructions.Length == 0 ) { return; } // Add Conditional Branches (Path>0) foreach ( var @case in branchInstructions ) { // Follow operand istruction PathOffsetList = GetBranchPath(@case); Debug.Assert(PathOffsetList.Count > 0); // add paths 1..n BranchPoint path1toN = new BranchPoint() { Offset = branchOffset, Ordinal = ordinal++, Path = pathCounter++, OffsetPoints = PathOffsetList.Count > 1 ? PathOffsetList.GetRange(0, PathOffsetList.Count - 1) : new List<int>(), EndOffset = PathOffsetList.Last() }; Debug.Assert(!Object.ReferenceEquals(null, path1toN.OffsetPoints)); list.Add(path1toN); } } } }