Example #1
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");
        }
        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");
        }
        /// <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;
        }
        /// <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;
        }
        /// <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;
        }
        /// <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;
        }
        /// <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;
        }
        /// <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 => this.assembliesByIdDictionary[type.Attribute(this.assemblyAttribute).Value].Equals(assembly.Name) && type.Attribute("name").Value.Equals(className))
                .Elements("Method")
                .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;
        }
        /// <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 assemblyElement = this.modules
                .Where(m => m.Attribute("Name").Value.Equals(assembly.Name));

            var filesIdsOfClass = assemblyElement
                .Elements("Namespace")
                .Elements("Type")
                .Concat(assemblyElement.Elements("Type"))
                .Where(c => (c.Parent.Attribute("Name").Value + "." + c.Attribute("Name").Value).Equals(className))
                .Descendants("Statement")
                .Select(c => c.Attribute("FileIndex").Value)
                .Distinct()
                .ToArray();

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

            foreach (var fileId in filesIdsOfClass)
            {
                @class.AddFile(this.ProcessFile(fileId, @class));
            }

            return @class;
        }
        /// <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 fileIdsOfClass = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(assembly.Name))
                .Elements("Classes")
                .Elements("Class")
                .Where(c => c.Element("FullName").Value.Equals(className))
                .Elements("Methods")
                .Elements("Method")
                .Where(m => m.Element("FileRef") != null)
                .Select(m => m.Element("FileRef").Attribute("uid").Value)
                .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;
        }
        private IEnumerable<Class> ProcessClasses(Assembly rootAssembly, IEnumerable<CoverageLine> lines)
        {
            var classes = lines.GroupBy (x => x.TypeName);
            foreach (var classData in classes)
            {
                if (classData.Key.StartsWith ("<>__AnonType"))
                    continue;
                
                Class classEntry = new Class (classData.Key, rootAssembly);
                var totalNum = classData.Count ();
                var hit = classData.Count (x => !x.Missed);

                classEntry.CoverageQuota = hit / totalNum;
                foreach (var codeFile in ProcessFiles (classEntry, classData.ToList()))
                    classEntry.AddFile (codeFile);

                yield return classEntry;
            }
        }