/// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="methods">The methods.</param>
        /// <param name="class">The class.</param>
        private static void SetMethodMetrics(IEnumerable<XElement> methods, Class @class)
        {
            foreach (var method in methods)
            {
                string methodName = method.Element("MethodName").Value;

                // Exclude properties and lambda expressions
                if (methodName.StartsWith("get_", StringComparison.Ordinal)
                    || methodName.StartsWith("set_", StringComparison.Ordinal)
                    || Regex.IsMatch(methodName, "<.+>.+__"))
                {
                    continue;
                }

                var metrics = new[]
                {
                    new Metric(
                        "Blocks covered",
                        int.Parse(method.Element("BlocksCovered").Value, CultureInfo.InvariantCulture)),
                    new Metric(
                        "Blocks not covered",
                        int.Parse(method.Element("BlocksNotCovered").Value, CultureInfo.InvariantCulture))
                };

                @class.AddMethodMetric(new MethodMetric(methodName, metrics));
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Creates a class report.
 /// </summary>
 /// <param name="class">The class.</param>
 /// <param name="fileAnalyses">The file analyses that correspond to the class.</param>
 public override void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalyses)
 {
     using (var renderer = new HtmlRenderer(false, this.javaScriptContent))
     {
         this.CreateClassReport(renderer, @class, fileAnalyses);
     }
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="methods">The methods.</param>
        /// <param name="class">The class.</param>
        private static void SetMethodMetrics(IEnumerable<XElement> methods, Class @class)
        {
            foreach (var methodGroup in methods.GroupBy(m => m.Element("Name").Value))
            {
                var method = methodGroup.First();

                // Exclude properties and lambda expressions
                if (method.Attribute("skippedDueTo") != null
                    || method.HasAttributeWithValue("isGetter", "true")
                    || method.HasAttributeWithValue("isSetter", "true")
                    || Regex.IsMatch(methodGroup.Key, "::<.+>.+__"))
                {
                    continue;
                }

                var metrics = new[]
                {
                    new Metric(
                        "Cyclomatic Complexity",
                        methodGroup.Max(m => int.Parse(m.Attribute("cyclomaticComplexity").Value, CultureInfo.InvariantCulture))),
                    new Metric(
                        "Sequence Coverage",
                        methodGroup.Max(m => decimal.Parse(m.Attribute("sequenceCoverage").Value, CultureInfo.InvariantCulture))),
                    new Metric(
                        "Branch Coverage",
                        methodGroup.Max(m => decimal.Parse(m.Attribute("branchCoverage").Value, CultureInfo.InvariantCulture)))
                };

                @class.AddMethodMetric(new MethodMetric(methodGroup.Key, metrics));
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HistoricCoverage" /> class.
 /// </summary>
 /// <param name="class">The class.</param>
 /// <param name="executionTime">The execution time.</param>
 public HistoricCoverage(Class @class, DateTime executionTime)
     : this(executionTime)
 {
     this.CoveredLines = @class.CoveredLines;
     this.CoverableLines = @class.CoverableLines;
     this.TotalLines = @class.TotalLines.GetValueOrDefault();
     this.CoveredBranches = @class.CoveredBranches.GetValueOrDefault();
     this.TotalBranches = @class.TotalBranches.GetValueOrDefault();
 }
Ejemplo n.º 5
0
        public void AddFile_AddSingleFile_FileIsStored()
        {
            var assembly = new Assembly("C:\\test\\TestAssembly.dll");
            var sut = new Class("Test", assembly);
            var file = new CodeFile("C:\\temp\\Program.cs", new int[0]);
            sut.AddFile(file);

            Assert.AreEqual(file, sut.Files.First(), "Not equal");
            Assert.AreEqual(1, sut.Files.Count(), "Wrong number of classes");
        }
Ejemplo n.º 6
0
        public void Constructor()
        {
            Assembly assembly = new Assembly("C:\\test\\TestAssembly.dll");
            string classname = "TestClass";

            var sut = new Class(classname, assembly);

            Assert.AreEqual(assembly, sut.Assembly, "Not equal");
            Assert.AreEqual(classname, sut.Name, "Not equal");
        }
Ejemplo n.º 7
0
        public void AddClass_AddSingleClass_ClassIsStored()
        {
            var sut = new Assembly("C:\\test\\TestAssembly.dll");
            var @class = new Class("Test", sut);

            sut.AddClass(@class);

            Assert.AreEqual(@class, sut.Classes.First(), "Not equal");
            Assert.AreEqual(1, sut.Classes.Count(), "Wrong number of classes");
        }
Ejemplo n.º 8
0
        public void Merge_MergeAssemblyWithOneClass_ClassIsStored()
        {
            var sut = new Assembly("C:\\test\\TestAssembly.dll");
            var assemblyToMerge = new Assembly("C:\\test\\TestAssembly.dll");
            var @class = new Class("Test", sut);
            assemblyToMerge.AddClass(@class);

            sut.Merge(assemblyToMerge);

            Assert.AreEqual(@class, sut.Classes.First(), "Not equal");
            Assert.AreEqual(1, sut.Classes.Count(), "Wrong number of classes");
        }
Ejemplo n.º 9
0
        public void Equals()
        {
            Assembly assembly = new Assembly("C:\\test\\TestAssembly.dll");
            string classname = "TestClass";

            var target1 = new Class(classname, assembly);
            var target2 = new Class(classname, assembly);
            var target3 = new Class(classname + "123", assembly);

            Assert.IsTrue(target1.Equals(target2), "Objects are not equal");
            Assert.IsFalse(target1.Equals(target3), "Objects are equal");
            Assert.IsFalse(target1.Equals(null), "Objects are equal");
            Assert.IsFalse(target1.Equals(new object()), "Objects are equal");
        }
Ejemplo n.º 10
0
        public void Merge_MergeClassWithOneFileAndOneMethodMetric_FileIsStored()
        {
            var assembly = new Assembly("C:\\test\\TestAssembly.dll");
            var sut = new Class("Test", assembly);
            var classToMerge = new Class("Test", assembly);
            var file = new CodeFile("C:\\temp\\Program.cs", new int[0]);
            var methodMetric = new MethodMetric("Test");
            classToMerge.AddFile(file);
            classToMerge.AddMethodMetric(methodMetric);
            sut.Merge(classToMerge);

            Assert.AreEqual(file, sut.Files.First(), "Not equal");
            Assert.AreEqual(1, sut.Files.Count(), "Wrong number of classes");
            Assert.AreEqual(methodMetric, sut.MethodMetrics.First(), "Not equal");
            Assert.AreEqual(1, sut.MethodMetrics.Count(), "Wrong number of method metrics");
        }
Ejemplo n.º 11
0
        public void Merge_MergeClassWithCoverageQuota_FileIsStored()
        {
            var assembly = new Assembly("C:\\test\\TestAssembly.dll");
            var sut = new Class("Test", assembly);
            var classToMerge = new Class("Test", assembly)
            {
                CoverageQuota = 15
            };

            sut.Merge(classToMerge);

            Assert.AreEqual(15, sut.CoverageQuota);

            classToMerge = new Class("Test", assembly)
            {
                CoverageQuota = 20
            };

            sut.Merge(classToMerge);

            Assert.AreEqual(20, sut.CoverageQuota);
        }
        /// <summary>
        /// Extracts the metrics from the given <see cref="XElement">XElements</see>.
        /// </summary>
        /// <param name="methods">The methods.</param>
        /// <param name="class">The class.</param>
        private static void SetMethodMetrics(IEnumerable<XElement> methods, Class @class)
        {
            foreach (var methodGroup in methods.GroupBy(m => m.Element("Name").Value))
            {
                var method = methodGroup.First();

                // Exclude properties and lambda expressions
                if (method.Attribute("skippedDueTo") != null
                    || method.HasAttributeWithValue("isGetter", "true")
                    || method.HasAttributeWithValue("isSetter", "true")
                    || Regex.IsMatch(methodGroup.Key, "::<.+>.+__"))
                {
                    continue;
                }

                string methodName = Regex.Replace(
                    methodGroup.Key,
                    MethodRegex,
                    m => string.Format(CultureInfo.InvariantCulture, "{0}({1})", m.Groups["MethodName"].Value, m.Groups["Arguments"].Value.Length > 0 ? "..." : string.Empty));

                var metrics = new[] 
                { 
                    new Metric(
                        "Cyclomatic Complexity", 
                        methodGroup.Max(m => int.Parse(m.Attribute("cyclomaticComplexity").Value, CultureInfo.InvariantCulture))),
                    new Metric(
                        "Sequence Coverage", 
                        methodGroup.Max(m => int.Parse(m.Attribute("sequenceCoverage").Value, CultureInfo.InvariantCulture))),
                    new Metric(
                        "Branch Coverage", 
                        methodGroup.Max(m => int.Parse(m.Attribute("branchCoverage").Value, CultureInfo.InvariantCulture)))
                };

                @class.AddMethodMetric(new MethodMetric(methodName, metrics));
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Creates a class report.
 /// </summary>
 /// <param name="class">The class.</param>
 /// <param name="fileAnalyses">The file analyses that correspond to the class.</param>
 public override void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalyses)
 {
     this.CreateClassReport(new XmlRenderer(), @class, fileAnalyses);
 }
        /// <summary>
        /// Processes the given class.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="className">Name of the class.</param>
        /// <returns>The <see cref="Class"/>.</returns>
        private Class ProcessClass(Assembly assembly, string className)
        {
            var fileIdsOfClass = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(assembly.Name))
                .Elements("NamespaceTable")
                .Elements("Class")
                .Where(c => (c.Parent.Element("NamespaceName").Value + "." + c.Element("ClassName").Value).Equals(className, StringComparison.Ordinal)
                            || (c.Parent.Element("NamespaceName").Value + "." + c.Element("ClassName").Value).StartsWith(className + ".", StringComparison.Ordinal))
                .Elements("Method")
                .Elements("Lines")
                .Elements("SourceFileID")
                .Select(m => m.Value)
                .Distinct();

            var @class = new Class(className, assembly);

            foreach (var fileId in fileIdsOfClass)
            {
                string file = this.files.First(f => f.Element("SourceFileID").Value == fileId).Element("SourceFileName").Value;
                @class.AddFile(this.ProcessFile(fileId, @class, file));
            }

            return @class;
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Processes the given class.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="className">Name of the class.</param>
        /// <returns>The <see cref="Class"/>.</returns>
        private Class ProcessClass(Assembly assembly, string className)
        {
            var filesOfClass = this.modules
                .Where(module => module.Attribute("assembly").Value.Equals(assembly.Name)).Elements("method")
                .Where(method => method.Attribute("class").Value.Equals(className))
                .Where(m => m.Attribute("excluded").Value == "false")
                .Elements("seqpnt").Select(seqpnt => seqpnt.Attribute("document").Value)
                .Distinct()
                .ToArray();

            var @class = new Class(className, assembly);

            foreach (var file in filesOfClass)
            {
                @class.AddFile(this.ProcessFile(@class, file));
            }

            return @class;
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private CodeFile ProcessFile(Class @class, string filePath)
        {
            var seqpntsOfFile = this.modules
                .Where(type => type.Attribute("assembly").Value.Equals(@class.Assembly.Name))
                .Elements("method")
                .Where(m => m.Attribute("excluded").Value == "false")
                .Where(method => method.Attribute("class").Value.StartsWith(@class.Name, StringComparison.Ordinal))
                .Elements("seqpnt")
                .Where(seqpnt => seqpnt.Attribute("document").Value.Equals(filePath) && seqpnt.Attribute("line").Value != "16707566")
                .Select(seqpnt => new
                {
                    LineNumber = int.Parse(seqpnt.Attribute("line").Value, CultureInfo.InvariantCulture),
                    Visits = int.Parse(seqpnt.Attribute("visitcount").Value, CultureInfo.InvariantCulture)
                })
                .OrderBy(seqpnt => seqpnt.LineNumber)
                .ToArray();

            int[] coverage = new int[] { };

            if (seqpntsOfFile.Length > 0)
            {
                coverage = new int[seqpntsOfFile[seqpntsOfFile.LongLength - 1].LineNumber + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var seqpnt in seqpntsOfFile)
                {
                    coverage[seqpnt.LineNumber] = coverage[seqpnt.LineNumber] == -1 ? seqpnt.Visits : coverage[seqpnt.LineNumber] + seqpnt.Visits;
                }
            }

            return new CodeFile(filePath, coverage);
        }
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="fileId">The file id.</param>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private CodeFile ProcessFile(string fileId, Class @class, string filePath)
        {
            var methods = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(@class.Assembly.Name))
                .Elements("NamespaceTable")
                .Elements("Class")
                .Where(c => (c.Parent.Element("NamespaceName").Value + "." + c.Element("ClassName").Value).Equals(@class.Name, StringComparison.Ordinal)
                            || (c.Parent.Element("NamespaceName").Value + "." + c.Element("ClassName").Value).StartsWith(@class.Name + ".", StringComparison.Ordinal))
                .Elements("Method")
                .Where(m => m.Elements("Lines").Elements("SourceFileID").Any(s => s.Value == fileId))
                .ToArray();

            SetMethodMetrics(methods, @class);

            var linesOfFile = methods
                .Elements("Lines")
                .Select(l => new
                {
                    LineNumberStart = int.Parse(l.Element("LnStart").Value, CultureInfo.InvariantCulture),
                    LineNumberEnd = int.Parse(l.Element("LnEnd").Value, CultureInfo.InvariantCulture),
                    Coverage = int.Parse(l.Element("Coverage").Value, CultureInfo.InvariantCulture)
                })
                .OrderBy(seqpnt => seqpnt.LineNumberEnd)
                .ToArray();

            int[] coverage = new int[] { };

            if (linesOfFile.Length > 0)
            {
                coverage = new int[linesOfFile[linesOfFile.LongLength - 1].LineNumberEnd + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var seqpnt in linesOfFile)
                {
                    for (int lineNumber = seqpnt.LineNumberStart; lineNumber <= seqpnt.LineNumberEnd; lineNumber++)
                    {
                        int visits = seqpnt.Coverage < 2 ? 1 : 0;
                        coverage[lineNumber] = coverage[lineNumber] == -1 ? visits : Math.Min(coverage[lineNumber] + visits, 1);
                    }
                }
            }

            return new CodeFile(filePath, coverage);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="class">The class.</param>
        public void SummaryClass(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException(nameof(@class));
            }

            string filenameColumn = @class.Name;

            if (!this.onlySummary)
            {
                filenameColumn = string.Format(
                    CultureInfo.InvariantCulture,
                    "<a href=\"{0}\">{1}</a>",
                    WebUtility.HtmlEncode(GetClassReportFilename(@class.Assembly.ShortName, @class.Name)),
                    WebUtility.HtmlEncode(@class.Name));
            }

            this.reportTextWriter.Write("<tr>");
            this.reportTextWriter.Write("<td>{0}</td>", filenameColumn);
            this.reportTextWriter.Write("<td class=\"right\">{0}</td>", @class.CoveredLines);
            this.reportTextWriter.Write("<td class=\"right\">{0}</td>", @class.CoverableLines - @class.CoveredLines);
            this.reportTextWriter.Write("<td class=\"right\">{0}</td>", @class.CoverableLines);
            this.reportTextWriter.Write("<td class=\"right\">{0}</td>", @class.TotalLines.GetValueOrDefault());
            this.reportTextWriter.Write(
                "<td title=\"{0}\" class=\"right\">{1}</td>",
                @class.CoverageType,
                @class.CoverageQuota.HasValue ? @class.CoverageQuota.Value.ToString(CultureInfo.InvariantCulture) + "%" : string.Empty);
            this.reportTextWriter.Write("<td>{0}</td>", CreateCoverageTable(@class.CoverageQuota));
            this.reportTextWriter.Write(
                "<td class=\"right\">{0}</td>",
                @class.BranchCoverageQuota.HasValue ? @class.BranchCoverageQuota.Value.ToString(CultureInfo.InvariantCulture) + "%" : string.Empty);
            this.reportTextWriter.Write("<td>{0}</td>", CreateCoverageTable(@class.BranchCoverageQuota));
            this.reportTextWriter.WriteLine("</tr>");
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="class">The class.</param>
        public void SummaryClass(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException("class");
            }

            string row = string.Format(
                CultureInfo.InvariantCulture,
                @"{0} & {1}\%\\",
                EscapeLatexChars(@class.Name),
                @class.CoverageQuota);

            this.reportBuilder.AppendLine(row);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="class">The class.</param>
        public void SummaryClass(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException("class");
            }

            var coverage = new XElement(
                "Class",
                new XAttribute("name", @class.Name),
                new XAttribute("coverage", @class.CoverageQuota),
                new XAttribute("coveredlines", @class.CoveredLines),
                new XAttribute("coverablelines", @class.CoverableLines),
                new XAttribute("totallines", @class.TotalLines));

            this.currentAssembly.Add(coverage);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="class">The class.</param>
        public void SummaryClass(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException("class");
            }

            this.reportTextWriter.WriteStartElement("Class");
            this.reportTextWriter.WriteAttributeString("name", @class.Name);
            this.reportTextWriter.WriteAttributeString("coverage", @class.CoverageQuota.HasValue ? @class.CoverageQuota.Value.ToString(CultureInfo.InvariantCulture) : string.Empty);
            this.reportTextWriter.WriteAttributeString("coveredlines", @class.CoveredLines.ToString(CultureInfo.InvariantCulture));
            this.reportTextWriter.WriteAttributeString("coverablelines", @class.CoverableLines.ToString(CultureInfo.InvariantCulture));
            this.reportTextWriter.WriteAttributeString("totallines", @class.TotalLines.HasValue ? @class.TotalLines.Value.ToString(CultureInfo.InvariantCulture) : string.Empty);
            this.reportTextWriter.WriteEndElement();
        }
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="fileId">The file id.</param>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private static CodeFile ProcessFile(XElement module, string fileId, Class @class, string filePath)
        {
            var methods = module
                .Elements("functions")
                .Elements("function")
                .Where(c => c.Attribute("type_name").Value.Equals(@class.Name, StringComparison.Ordinal)
                            || c.Attribute("type_name").Value.StartsWith(@class.Name + ".", StringComparison.Ordinal))
                .Where(m => m.Elements("ranges").Elements("range").Any(r => r.Attribute("source_id").Value == fileId))
                .ToArray();

            SetMethodMetrics(methods, @class);

            var linesOfFile = methods
                .Elements("ranges")
                .Elements("range")
                .Select(l => new
                {
                    LineNumberStart = int.Parse(l.Attribute("start_line").Value, CultureInfo.InvariantCulture),
                    LineNumberEnd = int.Parse(l.Attribute("end_line").Value, CultureInfo.InvariantCulture),
                    Coverage = l.Attribute("covered").Value.Equals("no") ? 0 : 1
                })
                .OrderBy(seqpnt => seqpnt.LineNumberEnd)
                .ToArray();

            int[] coverage = new int[] { };

            if (linesOfFile.Length > 0)
            {
                coverage = new int[linesOfFile[linesOfFile.LongLength - 1].LineNumberEnd + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var seqpnt in linesOfFile)
                {
                    for (int lineNumber = seqpnt.LineNumberStart; lineNumber <= seqpnt.LineNumberEnd; lineNumber++)
                    {
                        coverage[lineNumber] = coverage[lineNumber] == -1 ? seqpnt.Coverage : Math.Min(coverage[lineNumber] + seqpnt.Coverage, 1);
                    }
                }
            }

            return new CodeFile(filePath, coverage);
        }
        /// <summary>
        /// Processes the given class.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="assembly">The assembly.</param>
        /// <param name="className">Name of the class.</param>
        /// <returns>The <see cref="Class"/>.</returns>
        private static Class ProcessClass(XElement module, Assembly assembly, string className)
        {
            var fileIdsOfClass = module
                .Elements("functions")
                .Elements("function")
                .Where(c => c.Attribute("type_name").Value.Equals(className, StringComparison.Ordinal)
                            || c.Attribute("type_name").Value.StartsWith(className + ".", StringComparison.Ordinal))
                .Elements("ranges")
                .Elements("range")
                .Select(r => r.Attribute("source_id").Value)
                .Distinct();

            var @class = new Class(className, assembly);

            var files = module.Elements("source_files").Elements("source_file");

            foreach (var fileId in fileIdsOfClass)
            {
                string file = files.First(f => f.Attribute("id").Value == fileId).Attribute("path").Value;
                @class.AddFile(ProcessFile(module, fileId, @class, file));
            }

            return @class;
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="class">The class.</param>
        public void SummaryClass(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException("class");
            }

            string row = string.Format(
                CultureInfo.InvariantCulture,
                @"{0} & {1}\\",
                EscapeLatexChars(@class.Name),
                @class.CoverageQuota.HasValue ? @class.CoverageQuota.Value.ToString(CultureInfo.InvariantCulture) + @"\%" : string.Empty);

            this.reportTextWriter.WriteLine(row);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Processes the given class.
        /// </summary>
        /// <param name="fileIdsByFilename">Dictionary containing the file ids by filename.</param>
        /// <param name="assembly">The assembly.</param>
        /// <param name="className">Name of the class.</param>
        /// <returns>The <see cref="Class"/>.</returns>
        private Class ProcessClass(Dictionary<string, HashSet<string>> fileIdsByFilename, Assembly assembly, string className)
        {
            var methods = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(assembly.Name))
                .Elements("Classes")
                .Elements("Class")
                .Where(c => c.Element("FullName").Value.Equals(className)
                            || c.Element("FullName").Value.StartsWith(className + "/", StringComparison.Ordinal))
                .Elements("Methods")
                .Elements("Method");

            var fileIdsOfClassInSequencePoints = methods
                .Elements("SequencePoints")
                .Elements("SequencePoint")
                .Where(seqpnt => seqpnt.Attribute("fileid") != null
                                 && seqpnt.Attribute("fileid").Value != "0")
                .Select(seqpnt => seqpnt.Attribute("fileid").Value)
                .ToArray();

            // Only required for backwards compatibility, older versions of OpenCover did not apply fileid for partial classes
            var fileIdsOfClassInFileRef = methods
                .Where(m => m.Element("FileRef") != null)
                .Select(m => m.Element("FileRef").Attribute("uid").Value)
                .ToArray();

            var fileIdsOfClass = fileIdsOfClassInSequencePoints
                .Concat(fileIdsOfClassInFileRef)
                .Distinct()
                .ToHashSet();

            var filesOfClass = this.files
                .Where(file => fileIdsOfClass.Contains(file.Attribute("uid").Value))
                .Select(file => file.Attribute("fullPath").Value)
                .Distinct()
                .ToArray();

            var @class = new Class(className, assembly);

            foreach (var file in filesOfClass)
            {
                @class.AddFile(this.ProcessFile(fileIdsByFilename[file], @class, file));
            }

            @class.CoverageQuota = this.GetCoverageQuotaOfClass(assembly, className);

            return @class;
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Merges the given class with the current instance.
        /// </summary>
        /// <param name="class">The class to merge.</param>
        internal void Merge(Class @class)
        {
            if (@class == null)
            {
                throw new ArgumentNullException(nameof(@class));
            }

            if (this.coverageQuota.HasValue && @class.coverageQuota.HasValue)
            {
                this.CoverageQuota = Math.Max(this.coverageQuota.Value, @class.coverageQuota.Value);
            }
            else if (@class.coverageQuota.HasValue)
            {
                this.CoverageQuota = @class.coverageQuota.Value;
            }

            foreach (var methodMetric in @class.methodMetrics)
            {
                var existingMethodMetric = this.methodMetrics.FirstOrDefault(m => m.Name == methodMetric.Name);
                if (existingMethodMetric != null)
                {
                    existingMethodMetric.Merge(methodMetric);
                }
                else
                {
                    this.AddMethodMetric(methodMetric);
                }
            }

            foreach (var file in @class.files)
            {
                var existingFile = this.files.FirstOrDefault(f => f.Path == file.Path);
                if (existingFile != null)
                {
                    existingFile.Merge(file);
                }
                else
                {
                    this.AddFile(file);
                }
            }
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="fileIds">The file ids of the class.</param>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private CodeFile ProcessFile(HashSet<string> fileIds, Class @class, string filePath)
        {
            var methods = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(@class.Assembly.Name))
                .Elements("Classes")
                .Elements("Class")
                .Where(c => c.Element("FullName").Value.Equals(@class.Name)
                            || c.Element("FullName").Value.StartsWith(@class.Name + "/", StringComparison.Ordinal))
                .Elements("Methods")
                .Elements("Method")
                .ToArray();

            var methodsOfFile = methods
                .Where(m => m.Element("FileRef") != null && fileIds.Contains(m.Element("FileRef").Attribute("uid").Value))
                .ToArray();

            SetMethodMetrics(methodsOfFile, @class);

            var seqpntsOfFile = methods
                .Elements("SequencePoints")
                .Elements("SequencePoint")
                .Where(seqpnt => (seqpnt.Attribute("fileid") != null
                                    && fileIds.Contains(seqpnt.Attribute("fileid").Value))
                    || (seqpnt.Attribute("fileid") == null && seqpnt.Parent.Parent.Element("FileRef") != null
                        && fileIds.Contains(seqpnt.Parent.Parent.Element("FileRef").Attribute("uid").Value)))
                .Select(seqpnt => new
                {
                    LineNumberStart = int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    LineNumberEnd = seqpnt.Attribute("el") != null ? int.Parse(seqpnt.Attribute("el").Value, CultureInfo.InvariantCulture) : int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    Visits = int.Parse(seqpnt.Attribute("vc").Value, CultureInfo.InvariantCulture),
                    TrackedMethodRefs = seqpnt.Elements("TrackedMethodRefs")
                        .Elements("TrackedMethodRef")
                        .Select(t => new
                        {
                            Visits = int.Parse(t.Attribute("vc").Value, CultureInfo.InvariantCulture),
                            TrackedMethodId = t.Attribute("uid").Value
                        })
                })
                .OrderBy(seqpnt => seqpnt.LineNumberEnd)
                .ToArray();

            int[] coverage = new int[] { };
            var branches = GetBranches(methods, fileIds);

            var trackedMethodsCoverage = seqpntsOfFile
                .SelectMany(s => s.TrackedMethodRefs)
                .Select(t => t.TrackedMethodId)
                .Distinct()
                .ToDictionary(id => id, id => new int[] { });

            if (seqpntsOfFile.Length > 0)
            {
                coverage = new int[seqpntsOfFile[seqpntsOfFile.LongLength - 1].LineNumberEnd + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var name in trackedMethodsCoverage.Keys.ToArray())
                {
                    trackedMethodsCoverage[name] = (int[])coverage.Clone();
                }

                foreach (var seqpnt in seqpntsOfFile)
                {
                    for (int lineNumber = seqpnt.LineNumberStart; lineNumber <= seqpnt.LineNumberEnd; lineNumber++)
                    {
                        int visits = coverage[lineNumber] == -1 ? seqpnt.Visits : coverage[lineNumber] + seqpnt.Visits;
                        coverage[lineNumber] = visits;

                        if (visits > -1)
                        {
                            foreach (var trackedMethodCoverage in trackedMethodsCoverage)
                            {
                                if (trackedMethodCoverage.Value[lineNumber] == -1)
                                {
                                    trackedMethodCoverage.Value[lineNumber] = 0;
                                }
                            }
                        }

                        foreach (var trackedMethod in seqpnt.TrackedMethodRefs)
                        {
                            var trackedMethodCoverage = trackedMethodsCoverage[trackedMethod.TrackedMethodId];
                            trackedMethodCoverage[lineNumber] = trackedMethodCoverage[lineNumber] == -1 ? trackedMethod.Visits : trackedMethodCoverage[lineNumber] + trackedMethod.Visits;
                        }
                    }
                }
            }

            var codeFile = new CodeFile(filePath, coverage, branches);

            foreach (var trackedMethodCoverage in trackedMethodsCoverage)
            {
                string name = null;

                // Sometimes no corresponding MethodRef element exists
                if (this.trackedMethods.TryGetValue(trackedMethodCoverage.Key, out name))
                {
                    string shortName = name.Substring(name.Substring(0, name.IndexOf(':') + 1).LastIndexOf('.') + 1);
                    TestMethod testMethod = new TestMethod(name, shortName);
                    codeFile.AddCoverageByTestMethod(testMethod, trackedMethodCoverage.Value);
                }
            }

            return codeFile;
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private CodeFile ProcessFile(Class @class, string filePath)
        {
            string fileId = this.fileIdByFilenameDictionary[filePath];

            var seqpntsOfFile = this.types
                .Where(type => type.Attribute("asm").Value.Equals(@class.Assembly.Name)
                    && (type.Attribute("name").Value.Equals(@class.Name, StringComparison.Ordinal)
                        || type.Attribute("name").Value.StartsWith(@class.Name + "<", StringComparison.Ordinal)))
                .Elements("method")
                .Elements("code")
                .Elements("pt")
                .Where(seqpnt => seqpnt.HasAttributeWithValue("fid", fileId))
                .Select(seqpnt => new
                {
                    LineNumberStart = int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    LineNumberEnd = seqpnt.Attribute("el") != null ? int.Parse(seqpnt.Attribute("el").Value, CultureInfo.InvariantCulture) : int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    Visits = int.Parse(seqpnt.Attribute("visit").Value, CultureInfo.InvariantCulture)
                })
                .OrderBy(seqpnt => seqpnt.LineNumberEnd)
                .ToArray();

            int[] coverage = new int[] { };

            if (seqpntsOfFile.Length > 0)
            {
                coverage = new int[seqpntsOfFile[seqpntsOfFile.LongLength - 1].LineNumberEnd + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var seqpnt in seqpntsOfFile)
                {
                    for (int lineNumber = seqpnt.LineNumberStart; lineNumber <= seqpnt.LineNumberEnd; lineNumber++)
                    {
                        coverage[lineNumber] = coverage[lineNumber] == -1 ? seqpnt.Visits : coverage[lineNumber] + seqpnt.Visits;
                    }
                }
            }

            return new CodeFile(filePath, coverage);
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Creates a class report.
 /// </summary>
 /// <param name="class">The class.</param>
 /// <param name="fileAnalyses">The file analyses that correspond to the class.</param>
 public void CreateClassReport(Palmmedia.ReportGenerator.Parser.Analysis.Class @class, IEnumerable <Palmmedia.ReportGenerator.Parser.Analysis.FileAnalysis> fileAnalyses)
 {
 }
 /// <summary>
 /// Creates a class report.
 /// </summary>
 /// <param name="class">The class.</param>
 /// <param name="fileAnalyses">The file analyses that correspond to the class.</param>
 public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalyses)
 {
 }
Ejemplo n.º 31
0
        /// <summary>
        /// Processes the given class.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="className">Name of the class.</param>
        /// <returns>The <see cref="Class"/>.</returns>
        private Class ProcessClass(Assembly assembly, string className)
        {
            var fileIdsOfClass = this.types
                .Where(type => type.Attribute("asm").Value.Equals(assembly.Name)
                    && (type.Attribute("name").Value.Equals(className, StringComparison.Ordinal)
                        || type.Attribute("name").Value.StartsWith(className + "<", StringComparison.Ordinal)))
                .Elements("method")
                .Elements("code")
                .Elements("pt")
                .Where(pt => pt.Attribute("fid") != null)
                .Select(pt => pt.Attribute("fid").Value)
                .Distinct()
                .ToHashSet();

            var filesOfClass = this.files
                .Where(file => fileIdsOfClass.Contains(file.Attribute("id").Value))
                .Select(file => file.Attribute("url").Value)
                .ToArray();

            var @class = new Class(className, assembly);

            foreach (var file in filesOfClass)
            {
                @class.AddFile(this.ProcessFile(@class, file));
            }

            return @class;
        }