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);
                    }
                }
            }
        }