Example #1
0
        public void Can_GetBranchPoints_Of_MethodByToken()
        {
            // arrange
            var target = new BranchPoint();

            BranchPoint[] pts;
            var           module = new Module
            {
                FullName = "ModulePath",
                Classes  = new[]
                {
                    new Class
                    {
                        FullName = "namespace.class",
                        Methods  = new[]
                        {
                            new Method
                            {
                                MetadataToken = 1001,
                                BranchPoints  = new[] { target }
                            }
                        }
                    }
                }
            };

            module.Aliases.Add("ModulePath");
            Instance.PersistModule(module);

            // act
            Instance.GetBranchPointsForFunction("ModulePath", 1001, out pts);

            // assert
            Assert.AreEqual(target.UniqueSequencePoint, pts[0].UniqueSequencePoint);
        }
Example #2
0
    Vector3 GetPositionAlongPoints(float val, out float w)
    {
        // Reduce by tiny amount so we can still sample up!
        // Also it gives us less of a chance of hitting the points exactly
        float v = val * .99f * ((float)numPoints - 1);

        float up    = Mathf.Ceil(v);
        float down  = Mathf.Floor(v);
        float inVal = v - down;

        Vector3 fPos;


        if (inVal == 0 || up == down)
        {
            fPos = points[(int)down].position;
            w    = points[(int)down].width;
        }
        else
        {
            BranchPoint p1 = points[(int)down];
            BranchPoint p2 = points[(int)up];
            fPos = cubicPoint(inVal, p1.position, p1.position + p1.normal / 3, p2.position - p2.normal / 3, p2.position);
            w    = Mathf.Lerp(p1.width, p2.width, inVal);
        }

        return(fPos);
    }
        public void BuildModuleModel_Gets_NoBranchPoints_WhenNoSequencePoints()
        {
            // arrange
            var @class  = new Class();
            var @method = new Method {
                MetadataToken = 101
            };
            var brPoint = new BranchPoint();

            Container.GetMock <ISymbolManager>()
            .Setup(x => x.GetInstrumentableTypes())
            .Returns(new[] { @class });

            Container.GetMock <ISymbolManager>()
            .Setup(x => x.GetMethodsForType(@class, It.IsAny <File[]>()))
            .Returns(new[] { @method });

            Container.GetMock <ISymbolManager>()
            .Setup(x => x.GetBranchPointsForToken(101))
            .Returns(new[] { brPoint });

            Container.GetMock <IFilter>()
            .Setup(x => x.UseAssembly(It.IsAny <string>()))
            .Returns(true);

            // act
            var module = Instance.BuildModuleModel(true);

            // assert
            Assert.IsFalse(module.Classes[0].Methods[0].SequencePoints.Any());
            Assert.IsFalse(module.Classes[0].Methods[0].BranchPoints.Any());
        }
Example #4
0
        public void Commit_With_WithBranchPointsOnly()
        {
            // arrange
            var point = new BranchPoint();

            Instance.CoverageSession.Modules = new[]
            { new Module {
                  Classes = new[] { new Class {
                                        Methods = new[] { new Method {
                                                              BranchPoints = new[] { point }
                                                          } }
                                    } }
              } };

            // act
            InstrumentationPoint.AddVisitCount(point.UniqueSequencePoint, 0, 42);
            Assert.DoesNotThrow(() => Instance.Commit());

            // assert
            Assert.AreEqual(42, point.VisitCount);

            Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumSequencePoints);
            Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.VisitedSequencePoints);
            Assert.AreEqual(1, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumBranchPoints);
            Assert.AreEqual(1, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.VisitedBranchPoints);
        }
Example #5
0
        private static BranchPoint[] GetBranchPoints(MethodDefinition method, FileReference fileReference)
        {
            uint ordinal = 0;

            return(method.DebugInformation.GetScopes()
                   .Select(x =>
            {
                var branchPoint = new BranchPoint
                {
                    Offset = x.Start.Offset,
                    EndOffset = x.End.Offset,
                    Ordinal = ordinal++,
                    FileReference = fileReference
                };

                if (x.HasScopes)
                {
                    using (var enumerator = x.Scopes.GetEnumerator())
                        while (enumerator.MoveNext())
                        {
                            branchPoint.OffsetPoints.Add(enumerator.Current.Start.Offset);
                        }
                }

                return branchPoint;
            }).ToArray());
        }
        private IEnumerable <Suffix> AllFromNode(Node node, int length)
        {
            DebugCode.AssertArgument(length >= 0, nameof(length), "The length should be non-negative");
            if (node.IsLeaf)             // Empty subtree
            {
                if (length != 0)
                {
                    yield return(CreateSuffix(node.End, length));
                }
                yield break;
            }

            var branchStack = new Stack <BranchPoint>();
            var branchPoint = new BranchPoint {
                Node = node, EdgeIndex = 0
            };

            for (;;)
            {
                DebugCode.BugIf(branchPoint.Node.Children == null, "branchPoint.Node.Children == null");
                var edge       = GetNode(branchPoint.Node.Children[branchPoint.EdgeIndex]);
                var edgeLength = edge.Length;
                length += edgeLength;
                if (!edge.IsTerminal)
                {
                    branchPoint.Length = edgeLength;
                    branchStack.Push(branchPoint);
                    branchPoint = new BranchPoint {
                        Node = edge, EdgeIndex = 0
                    };
                    continue;
                }

                // We have descended to a terminal edge. Let's produce a suffix
                yield return(CreateSuffix(edge.End, length));

                // Move to the next suffix branch
                for (;;)
                {
                    length -= edgeLength;
                    var nextEdgeIndex = branchPoint.EdgeIndex + 1;
                    DebugCode.BugIf(branchPoint.Node.Children == null, "branchPoint.Node.Children == null");
                    if (nextEdgeIndex < branchPoint.Node.Children.Count)
                    {
                        branchPoint.EdgeIndex = nextEdgeIndex;
                        break;
                    }
                    // There is no more branches on the current level
                    // Return to the previous level
                    if (branchStack.Count == 0)
                    {
                        // no more branches to visit
                        yield break;
                    }
                    branchPoint = branchStack.Pop();
                    edgeLength  = branchPoint.Length;
                }
            }
        }
        private uint BuildPointsForBranch(List <BranchPoint> list, Instruction then, int branchingInstructionLine, string document,
                                          int branchOffset, uint ordinal, int pathCounter, BranchPoint path0, Collection <Instruction> instructions, MethodDefinition methodDefinition)
        {
            var pathOffsetList1 = GetBranchPath(@then);

            // Add path 1
            var path1 = new BranchPoint
            {
                StartLine    = branchingInstructionLine,
                Document     = document,
                Offset       = branchOffset,
                Ordinal      = ordinal++,
                Path         = pathCounter,
                OffsetPoints =
                    pathOffsetList1.Count > 1
                        ? pathOffsetList1.GetRange(0, pathOffsetList1.Count - 1)
                        : new List <int>(),
                EndOffset = pathOffsetList1.Last()
            };

            // only add branch if branch does not match a known sequence
            // e.g. auto generated field assignment
            // or encapsulates at least one sequence point
            var offsets = new[]
            {
                path0.Offset,
                path0.EndOffset,
                path1.Offset,
                path1.EndOffset
            };

            var ignoreSequences = new[]
            {
                // we may need other samples
                new[] { Code.Brtrue_S, Code.Pop, Code.Ldsfld, Code.Ldftn, Code.Newobj, Code.Dup, Code.Stsfld, Code.Newobj }, // CachedAnonymousMethodDelegate field allocation
            };

            var bs = offsets.Min();
            var be = offsets.Max();

            var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList();

            var match = ignoreSequences
                        .Where(ignoreSequence => range.Count >= ignoreSequence.Length)
                        .Any(ignoreSequence => range.Zip(ignoreSequence, (instruction, code) => instruction.OpCode.Code == code).All(x => x));

            var count = range
                        .Count(i => methodDefinition.DebugInformation.GetSequencePoint(i) != null);

            if (!match || count > 0)
            {
                list.Add(path0);
                list.Add(path1);
            }
            return(ordinal);
        }
        private bool BuildPointsForConditionalBranch(List <BranchPoint> list, Instruction instruction,
                                                     int branchingInstructionLine, string document, int branchOffset, int pathCounter,
                                                     Collection <Instruction> instructions, ref uint ordinal, MethodDefinition methodDefinition)
        {
            // Add Default branch (Path=0)

            // Follow else/default instruction
            var @else = instruction.Next;

            var pathOffsetList = GetBranchPath(@else);

            // add Path 0
            var path0 = new BranchPoint
            {
                StartLine    = branchingInstructionLine,
                Document     = document,
                Offset       = branchOffset,
                Ordinal      = ordinal++,
                Path         = pathCounter++,
                OffsetPoints =
                    pathOffsetList.Count > 1
                        ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                        : new List <int>(),
                EndOffset = pathOffsetList.Last()
            };

            // Add Conditional Branch (Path=1)
            if (instruction.OpCode.Code != Code.Switch)
            {
                // Follow instruction at operand
                var @then = instruction.Operand as Instruction;
                if (@then == null)
                {
                    return(false);
                }

                ordinal = BuildPointsForBranch(list, then, branchingInstructionLine, document, branchOffset,
                                               ordinal, pathCounter, path0, instructions, methodDefinition);
            }
            else // instruction.OpCode.Code == Code.Switch
            {
                var branchInstructions = instruction.Operand as Instruction[];
                if (branchInstructions == null || branchInstructions.Length == 0)
                {
                    return(false);
                }

                ordinal = BuildPointsForSwitchCases(list, path0, branchInstructions, branchingInstructionLine,
                                                    document, branchOffset, ordinal, ref pathCounter);
            }
            return(true);
        }
Example #9
0
        /// <summary>
        /// Get the branch ponts for a function
        /// </summary>
        /// <param name="modulePath"></param>
        /// <param name="functionToken"></param>
        /// <param name="branchPoints"></param>
        /// <returns></returns>
        public bool GetBranchPointsForFunction(string modulePath, int functionToken, out BranchPoint[] branchPoints)
        {
            branchPoints = new BranchPoint[0];
            var method = GetMethod(modulePath, functionToken, out Class @class);

            if (method != null && method.BranchPoints.Any())
            {
                System.Diagnostics.Debug.WriteLine("Getting Branch points for {0}({1})", method.FullName, method.MetadataToken);
                branchPoints = method.BranchPoints.ToArray();
                return(true);
            }
            return(false);
        }
Example #10
0
    public void GetBarkData(float x, float y, out Vector3 pos, out Vector3 centerPos, out Vector3 dir, out Vector3 nor, out Vector3 tang, out float life, out float width)
    {
        float v     = x * .99f * ((float)numPoints - 1);
        float angle = y * 2 * Mathf.PI;


        float up    = Mathf.Ceil(v);
        float down  = Mathf.Floor(v);
        float inVal = v - down;

        Vector3 fPos;
        Vector3 fPos1;


        float fLife;
        float fWidth;

        if (inVal == 0 || up == down)
        {
            v    += .0001f;
            up    = Mathf.Ceil(v);
            down  = Mathf.Floor(v);
            inVal = v - down;
        }

        BranchPoint p1 = points[(int)down];
        BranchPoint p2 = points[(int)up];

        fPos  = cubicPoint(inVal, p1.position, p1.position + p1.normal / 3, p2.position - p2.normal / 3, p2.position);
        fPos1 = cubicPoint(inVal + .001f, p1.position, p1.position + p1.normal / 3, p2.position - p2.normal / 3, p2.position);

        fLife  = Mathf.Lerp(p1.timeCreated, p2.timeCreated, inVal);
        fWidth = Mathf.Lerp(p1.width, p2.width, inVal);


        Vector3 fNor = Vector3.Lerp(p1.normal, p2.normal, inVal);
        Vector3 fTan = Vector3.Lerp(p1.tangent, p2.tangent, inVal);
        Vector3 fBi  = Vector3.Lerp(p1.binormal, p2.binormal, inVal);

        Vector3 outVec = (fTan * Mathf.Sin(angle) - fBi * Mathf.Cos(angle)) * fWidth;

        centerPos = fPos;
        fPos     += outVec;        // radius;;

        pos   = fPos;
        dir   = (fPos1 - fPos).normalized;
        nor   = outVec.normalized;
        tang  = Vector3.Cross(nor, dir).normalized;
        life  = fLife;
        width = fWidth;
    }
Example #11
0
        public void CanReturnLineNumbers()
        {
            // arrange
            var sequencePoint = new BranchPoint {
                StartLine = 1
            };

            // act
            var lineNumbers = sequencePoint.GetSourceLocation();

            // assert
            Assert.AreEqual(1, lineNumbers.Item1);
            Assert.IsNull(lineNumbers.Item2);
        }
Example #12
0
        private uint BuildPointsForConditionalBranch(List <BranchPoint> list, Instruction current, Instruction[] branchInstructions,
                                                     int branchingInstructionLine, string document, int branchOffset, uint ordinal, ref int pathCounter)
        {
            // add Path 0
            var pathOffsetList = GetConditionalBranchPath(current.Next);
            var path0          = new BranchPoint
            {
                StartLine    = branchingInstructionLine,
                Document     = document,
                Offset       = branchOffset,
                Ordinal      = ordinal++,
                Path         = pathCounter++,
                OffsetPoints =
                    pathOffsetList.Count > 1
                        ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                        : new List <int>(),
                EndOffset = pathOffsetList.Last()
            };

            list.Add(path0);

            var counter = pathCounter;

            // Add Conditional Branches (Path>0)
            list.AddRange(branchInstructions.Select(GetConditionalBranchPath)
                          .Select(pathOffsetList1 => new BranchPoint
            {
                StartLine    = branchingInstructionLine,
                Document     = document,
                Offset       = branchOffset,
                Ordinal      = ordinal++,
                Path         = counter++,
                OffsetPoints =
                    pathOffsetList1.Count > 1
                            ? pathOffsetList1.GetRange(0, pathOffsetList1.Count - 1)
                            : new List <int>(),
                EndOffset = pathOffsetList1.Last()
            }));
            pathCounter = counter;
            return(ordinal);
        }
Example #13
0
        private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
        {
            if (!_result.Documents.TryGetValue(branchPoint.Document, out var document))
            {
                document = new Document {
                    Path = branchPoint.Document
                };
                document.Index = _result.Documents.Count;
                _result.Documents.Add(document.Path, document);
            }

            BranchKey key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal);

            if (!document.Branches.ContainsKey(key))
            {
                document.Branches.Add(
                    key,
                    new Branch
                {
                    Number    = branchPoint.StartLine,
                    Class     = method.DeclaringType.FullName,
                    Method    = method.FullName,
                    Offset    = branchPoint.Offset,
                    EndOffset = branchPoint.EndOffset,
                    Path      = branchPoint.Path,
                    Ordinal   = branchPoint.Ordinal
                }
                    );

                if (method.DeclaringType.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(CompilerGeneratedAttribute).FullName))
                {
                    if (_branchesInCompiledGeneratedClass == null)
                    {
                        _branchesInCompiledGeneratedClass = new List <string>();
                    }

                    if (!_branchesInCompiledGeneratedClass.Contains(method.FullName))
                    {
                        _branchesInCompiledGeneratedClass.Add(method.FullName);
                    }
                }
            }

            _result.HitCandidates.Add(new HitCandidate(true, document.Index, branchPoint.StartLine, (int)branchPoint.Ordinal));

            return(AddInstrumentationInstructions(method, processor, instruction, _result.HitCandidates.Count - 1));
        }
Example #14
0
        private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
        {
            if (!_result.Documents.TryGetValue(branchPoint.Document, out var document))
            {
                document = new Document {
                    Path = branchPoint.Document
                };
                _result.Documents.Add(document.Path, document);
            }

            var key = (branchPoint.StartLine, (int)branchPoint.Ordinal);

            if (!document.Branches.ContainsKey(key))
            {
                document.Branches.Add(key,
                                      new Branch
                {
                    Number    = branchPoint.StartLine,
                    Class     = method.DeclaringType.FullName,
                    Method    = method.FullName,
                    Offset    = branchPoint.Offset,
                    EndOffset = branchPoint.EndOffset,
                    Path      = branchPoint.Path,
                    Ordinal   = branchPoint.Ordinal
                }
                                      );
            }

            string marker = $"B,{document.Path},{branchPoint.StartLine},{branchPoint.Ordinal}";

            var pathInstr = Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath);
            var markInstr = Instruction.Create(OpCodes.Ldstr, marker);
            var callInstr = Instruction.Create(OpCodes.Call, processor.Body.Method.Module.ImportReference(_markExecutedMethodLoader.Value));

            processor.InsertBefore(instruction, callInstr);
            processor.InsertBefore(callInstr, markInstr);
            processor.InsertBefore(markInstr, pathInstr);

            return(pathInstr);
        }
Example #15
0
    // Making points along each branch
    public void MakePoints()
    {
        Vector3 currPos = startPosition;

        tree.currentTotalPoints += numPoints;

        // place the points along the branch
        for (int i = 0; i < numPoints; i++)
        {
            float valInBranch = ((float)i / ((float)numPoints - 1));

            float widthMultiplier = 1;
            if (iterationLevel == 0)
            {
                widthMultiplier = tree.trunkCurve.Evaluate(valInBranch);
            }
            else
            {
                widthMultiplier = tree.branchCurve.Evaluate(valInBranch);
            }


            if (i != 0)
            {
                float currNoiseSize  = currVal(tree.noiseSize, tree.noiseSizeReducer);
                float currNoisePower = currVal(tree.noisePower, tree.noisePowerReducer);


                float currUp = currVal(tree.upDesire, tree.upDesireReducer);

                if (i != 1)
                {
                    Vector3 dir = points[i - 1].position - points[i - 2].position;
                    currPos += dir.normalized * length * ((float)1 / ((float)numPoints - 1));
                }
                else
                {
                    currPos += length * direction * ((float)1 / ((float)numPoints - 1));
                }

                currPos += currUp * Vector3.up * .003f;

                Vector3 noiseDir = Perlin.CurlNoise(currPos * currNoiseSize + tree.noiseOffset);

                currPos += noiseDir * currNoisePower * .04f;
            }

            float fWidth = baseWidth * widthMultiplier;

            BranchPoint p = new BranchPoint(currPos, valInBranch, timeCreated + valInBranch, fWidth);
            points.Add(p);
            // TODO ADD NOISE
        }

        // Gets Tangents for each of the points for sake of
        // cubic beziers
        for (int i = 0; i < numPoints; i++)
        {
            BranchPoint p = points[i];

            if (i == 0)
            {
                p.normal = (points[1].position - p.position);
            }
            else if (i == points.Count - 1)
            {
                p.normal = (p.position - points[points.Count - 2].position);
            }
            else
            {
                p.normal = -(points[i - 1].position - points[i + 1].position);
            }


            if (i == 0)
            {
                p.tangent  = (Vector3.Cross(p.normal.normalized, Vector3.left)).normalized;
                p.binormal = (Vector3.Cross(p.normal, p.tangent)).normalized;
            }
            else
            {
                p.tangent  = -(Vector3.Cross(p.normal.normalized, points[i - 1].binormal)).normalized;
                p.binormal = (Vector3.Cross(p.normal, p.tangent)).normalized;
            }

            points[i] = p;
        }
    }
        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);
                    }
                }
            }
        }
Example #17
0
        private void GetBranchPointsForToken(int token, List <BranchPoint> list)
        {
            var methodDefinition = GetMethodDefinition(token);

            if (methodDefinition == null)
            {
                return;
            }
            try
            {
                UInt32 ordinal = 0;

                foreach (var instruction in methodDefinition.SafeGetMethodBody().Instructions)
                {
                    if (instruction.OpCode.FlowControl != FlowControl.Cond_Branch)
                    {
                        continue;
                    }

                    if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition))
                    {
                        continue;
                    }

                    var pathCounter = 0;

                    // store branch origin offset
                    var branchOffset             = instruction.Offset;
                    var closestSeqPt             = FindClosestSequencePoints(methodDefinition.Body, instruction);
                    var branchingInstructionLine = closestSeqPt.Maybe(sp => sp.SequencePoint.StartLine, -1);
                    var document = closestSeqPt.Maybe(sp => sp.SequencePoint.Document.Url);

                    if (null == instruction.Next)
                    {
                        return;
                    }

                    // Add Default branch (Path=0)

                    // Follow else/default instruction
                    var @else = instruction.Next;

                    var pathOffsetList = GetBranchPath(@else);

                    // add Path 0
                    var path0 = new BranchPoint
                    {
                        StartLine    = branchingInstructionLine,
                        Document     = document,
                        Offset       = branchOffset,
                        Ordinal      = ordinal++,
                        Path         = pathCounter++,
                        OffsetPoints =
                            pathOffsetList.Count > 1
                                ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                : new List <int>(),
                        EndOffset = pathOffsetList.Last()
                    };
                    list.Add(path0);

                    // Add Conditional Branch (Path=1)
                    if (instruction.OpCode.Code != Code.Switch)
                    {
                        // Follow instruction at operand
                        var @then = instruction.Operand as Instruction;
                        if (@then == null)
                        {
                            return;
                        }

                        pathOffsetList = GetBranchPath(@then);

                        // Add path 1
                        var path1 = new BranchPoint
                        {
                            StartLine    = branchingInstructionLine,
                            Document     = document,
                            Offset       = branchOffset,
                            Ordinal      = ordinal++,
                            Path         = pathCounter,
                            OffsetPoints =
                                pathOffsetList.Count > 1
                                    ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                    : new List <int>(),
                            EndOffset = pathOffsetList.Last()
                        };
                        list.Add(path1);
                    }
                    else // instruction.OpCode.Code == Code.Switch
                    {
                        var branchInstructions = instruction.Operand as Instruction[];
                        if (branchInstructions == null || branchInstructions.Length == 0)
                        {
                            return;
                        }

                        // Add Conditional Branches (Path>0)
                        foreach (var @case in branchInstructions)
                        {
                            // Follow operand istruction
                            pathOffsetList = GetBranchPath(@case);

                            // add paths 1..n
                            var path1ToN = new BranchPoint
                            {
                                StartLine    = branchingInstructionLine,
                                Document     = document,
                                Offset       = branchOffset,
                                Ordinal      = ordinal++,
                                Path         = pathCounter++,
                                OffsetPoints =
                                    pathOffsetList.Count > 1
                                        ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                        : new List <int>(),
                                EndOffset = pathOffsetList.Last()
                            };
                            list.Add(path1ToN);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                          string.Format("An error occurred with 'GetBranchPointsForToken' for method '{0}'",
                                        methodDefinition.FullName), ex);
            }
        }
Example #18
0
        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);
        }
Example #19
0
        private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
        {
            if (!_result.Documents.TryGetValue(branchPoint.Document, out var document))
            {
                document = new Document {
                    Path = branchPoint.Document
                };
                document.Index = _result.Documents.Count;
                _result.Documents.Add(document.Path, document);
            }

            BranchKey key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal);

            if (!document.Branches.ContainsKey(key))
            {
                document.Branches.Add(key,
                                      new Branch
                {
                    Number    = branchPoint.StartLine,
                    Class     = method.DeclaringType.FullName,
                    Method    = method.FullName,
                    Offset    = branchPoint.Offset,
                    EndOffset = branchPoint.EndOffset,
                    Path      = branchPoint.Path,
                    Ordinal   = branchPoint.Ordinal
                }
                                      );
            }

            _result.HitCandidates.Add(new HitCandidate(true, document.Index, branchPoint.StartLine, (int)branchPoint.Ordinal));

            return(AddInstrumentationInstructions(method, processor, instruction, _result.HitCandidates.Count - 1));
        }
Example #20
0
        private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
        {
            var document = _result.Documents.FirstOrDefault(d => d.Path == branchPoint.Document);

            if (document == null)
            {
                document = new Document {
                    Path = branchPoint.Document
                };
                _result.Documents.Add(document);
            }

            if (!document.Branches.Exists(l => l.Number == branchPoint.StartLine && l.Ordinal == branchPoint.Ordinal))
            {
                document.Branches.Add(
                    new Branch
                {
                    Number    = branchPoint.StartLine,
                    Class     = method.DeclaringType.FullName,
                    Method    = method.FullName,
                    Offset    = branchPoint.Offset,
                    EndOffset = branchPoint.EndOffset,
                    Path      = branchPoint.Path,
                    Ordinal   = branchPoint.Ordinal
                }
                    );
            }

            string marker = $"B,{document.Path},{branchPoint.StartLine},{branchPoint.Ordinal}";

            var pathInstr = Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath);
            var markInstr = Instruction.Create(OpCodes.Ldstr, marker);
            var callInstr = Instruction.Create(OpCodes.Call, processor.Body.Method.Module.ImportReference(_markExecutedMethodLoader.Value));

            processor.InsertBefore(instruction, callInstr);
            processor.InsertBefore(callInstr, markInstr);
            processor.InsertBefore(markInstr, pathInstr);

            return(pathInstr);
        }
        private void GetBranchPointsForToken(int token, List <BranchPoint> list)
        {
            var methodDefinition = GetMethodDefinition(token);

            if (methodDefinition == null)
            {
                return;
            }
            try
            {
                UInt32 ordinal      = 0;
                var    instructions = methodDefinition.SafeGetMethodBody().Instructions;

                // if method is a generated MoveNext skip first branch (could be a switch or a branch)
                var skipFirstBranch = Regex.IsMatch(methodDefinition.FullName, @"\<.+\>d__\d+::MoveNext\(\)$");

                foreach (var instruction in instructions.Where(instruction => instruction.OpCode.FlowControl == FlowControl.Cond_Branch))
                {
                    if (skipFirstBranch)
                    {
                        skipFirstBranch = false;
                        continue;
                    }

                    if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition))
                    {
                        continue;
                    }

                    var pathCounter = 0;

                    // store branch origin offset
                    var branchOffset             = instruction.Offset;
                    var closestSeqPt             = FindClosestSequencePoints(methodDefinition.Body, instruction);
                    var branchingInstructionLine = closestSeqPt.Maybe(sp => sp.SequencePoint.StartLine, -1);
                    var document = closestSeqPt.Maybe(sp => sp.SequencePoint.Document.Url);

                    if (null == instruction.Next)
                    {
                        return;
                    }

                    // Add Default branch (Path=0)

                    // Follow else/default instruction
                    var @else = instruction.Next;

                    var pathOffsetList = GetBranchPath(@else);

                    // add Path 0
                    var path0 = new BranchPoint
                    {
                        StartLine    = branchingInstructionLine,
                        Document     = document,
                        Offset       = branchOffset,
                        Ordinal      = ordinal++,
                        Path         = pathCounter++,
                        OffsetPoints =
                            pathOffsetList.Count > 1
                                ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                : new List <int>(),
                        EndOffset = pathOffsetList.Last()
                    };

                    // Add Conditional Branch (Path=1)
                    if (instruction.OpCode.Code != Code.Switch)
                    {
                        // Follow instruction at operand
                        var @then = instruction.Operand as Instruction;
                        if (@then == null)
                        {
                            return;
                        }

                        pathOffsetList = GetBranchPath(@then);

                        // Add path 1
                        var path1 = new BranchPoint
                        {
                            StartLine    = branchingInstructionLine,
                            Document     = document,
                            Offset       = branchOffset,
                            Ordinal      = ordinal++,
                            Path         = pathCounter,
                            OffsetPoints =
                                pathOffsetList.Count > 1
                                    ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                    : new List <int>(),
                            EndOffset = pathOffsetList.Last()
                        };

                        // only add branch if branch does not match a known sequence
                        // e.g. auto generated field assignment
                        // or encapsulates at least one sequence point
                        var offsets = new[]
                        {
                            path0.Offset,
                            path0.EndOffset,
                            path1.Offset,
                            path1.EndOffset
                        };

                        var ignoreSequences = new[]
                        {
                            new [] { Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Br_S, Code.Ldsfld }, // CachedAnonymousMethodDelegate field allocation - debug
                            new [] { Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Ldsfld } // CachedAnonymousMethodDelegate field allocation
                        };

                        var bs = offsets.Min();
                        var be = offsets.Max();

                        var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList();

                        var match = ignoreSequences
                                    .Where(ignoreSequence => range.Count() >= ignoreSequence.Count())
                                    .Select(x => x.Zip(range, (code, i1) => new { Code1 = code, Code2 = i1.OpCode.Code }).All(y => y.Code1 == y.Code2))
                                    .Any();

                        var count = range
                                    .Count(i => i.SequencePoint != null);

                        if (!match || count > 0)
                        {
                            list.Add(path0);
                            list.Add(path1);
                        }
                    }
                    else // instruction.OpCode.Code == Code.Switch
                    {
                        var branchInstructions = instruction.Operand as Instruction[];
                        if (branchInstructions == null || branchInstructions.Length == 0)
                        {
                            return;
                        }

                        list.Add(path0);
                        // Add Conditional Branches (Path>0)
                        foreach (var @case in branchInstructions)
                        {
                            // Follow operand istruction
                            pathOffsetList = GetBranchPath(@case);

                            // add paths 1..n
                            var path1ToN = new BranchPoint
                            {
                                StartLine    = branchingInstructionLine,
                                Document     = document,
                                Offset       = branchOffset,
                                Ordinal      = ordinal++,
                                Path         = pathCounter++,
                                OffsetPoints =
                                    pathOffsetList.Count > 1
                                        ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1)
                                        : new List <int>(),
                                EndOffset = pathOffsetList.Last()
                            };
                            list.Add(path1ToN);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                          string.Format("An error occurred with 'GetBranchPointsForToken' for method '{0}'",
                                        methodDefinition.FullName), ex);
            }
        }
Example #22
0
        private uint BuildPointsForBranch(List <BranchPoint> list, Instruction then, int branchingInstructionLine, string document,
                                          int branchOffset, uint ordinal, int pathCounter, BranchPoint path0, Collection <Instruction> instructions)
        {
            var pathOffsetList1 = GetBranchPath(@then);

            // Add path 1
            var path1 = new BranchPoint
            {
                StartLine    = branchingInstructionLine,
                Document     = document,
                Offset       = branchOffset,
                Ordinal      = ordinal++,
                Path         = pathCounter,
                OffsetPoints =
                    pathOffsetList1.Count > 1
                        ? pathOffsetList1.GetRange(0, pathOffsetList1.Count - 1)
                        : new List <int>(),
                EndOffset = pathOffsetList1.Last()
            };

            // only add branch if branch does not match a known sequence
            // e.g. auto generated field assignment
            // or encapsulates at least one sequence point
            var offsets = new[]
            {
                path0.Offset,
                path0.EndOffset,
                path1.Offset,
                path1.EndOffset
            };

            var ignoreSequences = new[]
            {
                new[]
                { Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Br_S, Code.Ldsfld },
                // CachedAnonymousMethodDelegate field allocation - debug
                new[] { Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Ldsfld }
                // CachedAnonymousMethodDelegate field allocation
            };

            var bs = offsets.Min();
            var be = offsets.Max();

            var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList();

            var match = ignoreSequences
                        .Where(ignoreSequence => range.Count() >= ignoreSequence.Count())
                        .Select(
                x =>
                x.Zip(range, (code, i1) => new { Code1 = code, Code2 = i1.OpCode.Code })
                .All(y => y.Code1 == y.Code2))
                        .Any();

            var count = range
                        .Count(i => i.SequencePoint != null);

            if (!match || count > 0)
            {
                list.Add(path0);
                list.Add(path1);
            }
            return(ordinal);
        }
Example #23
0
        private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
        {
            if (!_result.Documents.TryGetValue(branchPoint.Document, out var document))
            {
                document = new Document {
                    Path = branchPoint.Document
                };
                document.Index = _result.Documents.Count;
                _result.Documents.Add(document.Path, document);
            }

            var key = (branchPoint.StartLine, (int)branchPoint.Ordinal);

            if (!document.Branches.ContainsKey(key))
            {
                document.Branches.Add(key,
                                      new Branch
                {
                    Number    = branchPoint.StartLine,
                    Class     = method.DeclaringType.FullName,
                    Method    = method.FullName,
                    Offset    = branchPoint.Offset,
                    EndOffset = branchPoint.EndOffset,
                    Path      = branchPoint.Path,
                    Ordinal   = branchPoint.Ordinal
                }
                                      );

                if (IsAsyncStateMachineBranch(method.DeclaringType, method))
                {
                    if (_asyncMachineStateMethod == null)
                    {
                        _asyncMachineStateMethod = new List <string>();
                    }

                    if (!_asyncMachineStateMethod.Contains(method.FullName))
                    {
                        _asyncMachineStateMethod.Add(method.FullName);
                    }
                }
            }

            var entry = (true, document.Index, branchPoint.StartLine, (int)branchPoint.Ordinal);

            _result.HitCandidates.Add(entry);

            return(AddInstrumentationInstructions(method, processor, instruction, _result.HitCandidates.Count - 1));
        }
        private void CreateEntries(Conversation conversation)
        {
            visitedIDs.Clear();
            DialogueEntry currentEntry = conversation.dialogueEntries[0];

            while (currentEntry.outgoingLinks.Count > 0 || branchPoints.Count > 0)
            {
                currentEntry = GetNextEntry(currentEntry);

                if (branchPoints.Count > 0 && (IsDeadEnd(currentEntry) || IsPickUpPoint(currentEntry)))
                {
                    if (currentEntry != null && IsDeadEnd(currentEntry))
                    {
                        TokenizeEntry(currentEntry);
                    }

                    BranchPoint bp = branchPoints[branchPoints.Count - 1];

                    TokenizeBranchName(bp.branchNodes[0]);
                    bp.branchNodes.RemoveAt(0);
                    builder.AppendLine();

                    if (bp.branchNodes.Count > 0)
                    {
                        currentEntry = bp.branchNodes[0];
                        TokenizeBranchName(bp.branchNodes[0]);
                    }
                    else
                    {
                        branchPoints.Remove(bp);

                        while (branchPoints.Count > 0)
                        {
                            BranchPoint parentBranch = branchPoints[branchPoints.Count - 1];
                            TokenizeBranchName(parentBranch.branchNodes[0]);
                            parentBranch.branchNodes.RemoveAt(0);

                            if (parentBranch.branchNodes.Count > 0)
                            {
                                currentEntry = parentBranch.branchNodes[0];
                                builder.AppendLine();
                                TokenizeBranchName(parentBranch.branchNodes[0]);
                                break;
                            }
                            else
                            {
                                branchPoints.Remove(parentBranch);
                            }
                        }
                    }
                }

                if (currentEntry != null)
                {
                    if (!HasAlreadyBeenVisited(currentEntry))
                    {
                        TokenizeEntry(currentEntry);
                    }
                    else if (currentEntry.outgoingLinks.Count > 0)
                    {
                        AddRecursiveErrorWarning();
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
        }