예제 #1
0
        private void WriteClass(ClassCoverageItem item)
        {
            if (item.filtered)
            {
                return;
            }

            // start class
            writer.WriteStartElement("class");
            writer.WriteAttributeString("name", item.name);
            writer.WriteAttributeString("fullname", item.FullName.Replace('/', '.'));
            writer.WriteAttributeString("namespace", item.Namespace);
            WriteCoverage(item);

            //		start source
            writer.WriteStartElement("source");

            if (item.sourceFile != null)
            {
                writer.WriteAttributeString("sourceFile", item.sourceFile.sourceFile);

                int[] coverage = item.sourceFile.Coverage;

                foreach (MethodCoverageItem method in item.Methods)
                {
                    int sum    = 0;
                    int length = method.endLine - method.startLine;
                    for (int index = method.startLine; index < method.endLine; index++)
                    {
                        if (coverage[index] > 0)
                        {
                            sum++;
                        }
                    }
                    if (length == 0)
                    {
                        continue;
                    }

                    writer.WriteStartElement("Method");
                    writer.WriteAttributeString("type", item.FullName);
                    writer.WriteAttributeString("method", method.Name);
                    writer.WriteAttributeString("coverage", "" + ((float)sum) / length);
                    writer.WriteAttributeString("length", "" + length);
                    writer.WriteEndElement();
                }
            }
            else
            {
            }
            // end source
            writer.WriteEndElement();
            // end class
            writer.WriteEndElement();
        }
예제 #2
0
        private void ProcessMethod(MethodDefinition monoMethod, MethodEntry entry, ClassCoverageItem klass, string methodName, string cov_info)
#endif
        {
            if (entry == null)
            {
                // Compiler generated, abstract method etc.
                return;
            }

            LineNumberEntry[] lines = entry.LineNumbers;

            // DEBUG
            //if( cov_info == null )
            //	Console.WriteLine( lines.Length );
            // DEBUG

            if (lines.Length == 0)
            {
                return;
            }

            int start_line = lines [0].Row;
            int end_line   = lines [lines.Length - 1].Row;

            MethodCoverageItem method
                = new MethodCoverageItem(klass, methodName);

            method.startLine = start_line;
            method.endLine   = end_line;
#if USE_REFLECTION
            method.filtered = IsFiltered("[" + monoMethod.DeclaringType.Assembly + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name);
#else
            method.filtered = IsFiltered("[" + monoMethod.DeclaringType.Module.Name + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name);
#endif
            klass.methodsByMethod [monoMethod] = method;


            if (klass.sourceFile == null)
            {
                string sourceFile = entry.SourceFile.FileName;

                SourceFileCoverageData source = (SourceFileCoverageData)sources [sourceFile];
                //Console.WriteLine( source );
                if (source == null)
                {
                    source = new SourceFileCoverageData(sourceFile);
                    sources [sourceFile] = source;
                }
                klass.sourceFile = source;
            }

            computeMethodCoverage(method, lines, cov_info);
        }
예제 #3
0
        private void WriteClass(ClassCoverageItem item)
        {
            if (item.filtered)
            {
                return;
            }

            writer.WriteStartElement("class");
            writer.WriteAttributeString("name", item.name);
            writer.WriteAttributeString("fullname", item.FullName.Replace('/', '.'));
            writer.WriteAttributeString("namespace", item.Namespace);

            WriteCoverage(item);

            writer.WriteStartElement("source");

            if (item.sourceFile != null)
            {
                writer.WriteAttributeString("sourceFile", item.sourceFile.sourceFile);

                StreamReader infile   = new StreamReader(item.sourceFile.sourceFile, Encoding.ASCII);
                int[]        coverage = item.sourceFile.Coverage;
                int          pos      = 1;
                while (infile.Peek() > -1)
                {
                    int count;
                    if ((coverage != null) && (pos < coverage.Length))
                    {
                        count = coverage [pos];
                    }
                    else
                    {
                        count = -1;
                    }
                    writer.WriteStartElement("l");
                    writer.WriteAttributeString("line", "" + pos);
                    writer.WriteAttributeString("count", "" + count);
                    string line = infile.ReadLine();
                    writer.WriteString(line);
                    writer.WriteEndElement();

                    pos++;
                }
            }

            writer.WriteEndElement();
        }
예제 #4
0
 private void ProcessMethod(MethodBase monoMethod, MethodEntry entry, ClassCoverageItem klass, string methodName, string cov_info)
예제 #5
0
        private ClassCoverageItem ProcessClass(TypeDefinition t)
#endif
        {
            string className = t.FullName;
            int    nsindex   = className.LastIndexOf(".");
            string namespace2;
            string scopedName;

            if (nsindex == -1)
            {
                namespace2 = "<GLOBAL>";
                scopedName = className;
            }
            else if (nsindex == 0)
            {
                namespace2 = "<GLOBAL>";
                scopedName = className.Substring(1);
            }
            else
            {
                namespace2 = className.Substring(0, nsindex);
                scopedName = className.Substring(nsindex + 1);
            }

            // Create namespaces
            NamespaceCoverageItem ns = (NamespaceCoverageItem)namespaces [namespace2];

            if (ns == null)
            {
                string nsPrefix = "";
                foreach (String nsPart in namespace2.Split('.'))
                {
                    if (nsPrefix == "")
                    {
                        nsPrefix = nsPart;
                    }
                    else
                    {
                        nsPrefix = nsPrefix + "." + nsPart;
                    }
                    NamespaceCoverageItem ns2 = (NamespaceCoverageItem)namespaces [nsPrefix];
                    if (ns2 == null)
                    {
                        if (ns == null)
                        {
                            ns2 = new NamespaceCoverageItem(this, nsPrefix);
                        }
                        else
                        {
                            ns2 = new NamespaceCoverageItem(ns, nsPrefix);
                        }
                        namespaces [nsPrefix] = ns2;
                    }
                    ns = ns2;
                }
            }

            ClassCoverageItem klass = (ClassCoverageItem)classes [className];

            if (klass == null)
            {
                klass            = new ClassCoverageItem(ns);
                klass.name_space = namespace2;
                klass.name       = scopedName;
                klass.type       = t;
                klass.parent     = ns;

#if USE_REFLECTION
                klass.filtered = IsFiltered("[" + t.Assembly + "]" + className);
#else
                klass.filtered = IsFiltered("[" + t.Module.Name + "]" + className);
#endif
                classes [className] = klass;
            }

            return(klass);
        }
예제 #6
0
        private void computeMethodCoverage(MethodCoverageItem method, LineNumberEntry[] lines, string cov_info)
        {
            ClassCoverageItem      klass  = method.Class;
            SourceFileCoverageData source = klass.sourceFile;

            source.AddMethod(method);

            int nlines = method.endLine - method.startLine + 1;

            int[] coverage = new int [nlines];

            if (cov_info == null)
            {
                for (int i = 0; i < nlines; ++i)
                {
                    coverage [i] = 0;
                }
            }
            else
            {
                for (int i = 0; i < nlines; ++i)
                {
                    coverage [i] = -1;
                }

                // Hand crafted parsing code since this is performance critical
                int pos         = 0;
                int prev_offset = 0;
                while (pos < cov_info.Length)
                {
                    int pos2 = cov_info.IndexOfAny(digits, pos);
                    if (pos2 == -1)
                    {
                        break;
                    }
                    pos = cov_info.IndexOfAny(ws, pos2);
                    if (pos == -1)
                    {
                        break;
                    }

                    int offset = parsePositiveInteger(cov_info, pos2);

                    pos2 = cov_info.IndexOfAny(digits, pos);
                    if (pos2 == -1)
                    {
                        break;
                    }
                    pos = cov_info.IndexOfAny(ws, pos2);

                    int count = parsePositiveInteger(cov_info, pos2);

                    offset     += prev_offset;
                    prev_offset = offset;

                    int line1 = 0;
                    int line2 = 0;

                    bool found = GetSourceRangeFor(offset, method, lines, ref line1, ref line2);

                    /*
                     * if (found && (entry.Name.IndexOf ("Find") != -1)) {
                     * Console.WriteLine ("OFFSET: " + offset + " " + line1 + ":" + line2);
                     * }
                     */

                    if (found)
                    {
                        for (int i = line1; i < line2 + 1; ++i)
                        {
                            if ((i >= method.startLine) && (i <= method.endLine))
                            {
                                if (coverage [i - method.startLine] < count)
                                {
                                    coverage [i - method.startLine] = count;
                                }
                            }
                        }
                    }
                }
            }

            int hit    = 0;
            int missed = 0;

            for (int i = 0; i < nlines; ++i)
            {
                int count = coverage [i];
                if (count > 0)
                {
                    hit++;
                }
                else if (count == 0)
                {
                    missed++;
                }
            }

            method.setCoverage(hit, missed);

            method.lineCoverage = coverage;
        }
예제 #7
0
        public void ReadFromFile(string fileName)
        {
            namespaces = new Hashtable();
            classes    = new Hashtable();

            long begin = DateTime.Now.Ticks / 10000;
            long msec  = DateTime.Now.Ticks / 10000;
            long msec2;

            loadedAssemblies = new Hashtable();
            symbolFiles      = new Hashtable();

            XmlDocument dom = new XmlDocument();

            Progress("XML reading", 0);
            Console.Write("Loading " + fileName + "...");
            dom.Load(new XmlTextReader(new FileStream(fileName, FileMode.Open)));
            Console.WriteLine(" Done.");

            msec2 = DateTime.Now.Ticks / 10000;
            Console.WriteLine("XML Reading: " + (msec2 - msec) + " msec");
            msec = msec2;

            Progress("Load assemblies", 0.2);
            LoadAssemblies(dom);

            LoadFilters(dom);

            msec2 = DateTime.Now.Ticks / 10000;
            Console.WriteLine("Load assemblies: " + (msec2 - msec) + " msec");
            msec = msec2;

            Progress("Load methods", 0.4);
            foreach (XmlNode n in dom.GetElementsByTagName("method"))
            {
                string assemblyName = n.Attributes ["assembly"].Value;
                string className    = n.Attributes ["class"].Value;
                string methodName   = n.Attributes ["name"].Value;
                string token        = n.Attributes ["token"].Value;
                string cov_info     = n.FirstChild.Value;
                int    itok         = int.Parse(token);

#if USE_REFLECTION
                Assembly       assembly   = (Assembly)loadedAssemblies [assemblyName];
                MonoSymbolFile symbolFile = (MonoSymbolFile)symbolFiles [assembly];

                if (symbolFile == null)
                {
                    continue;
                }

                Type t = LoadType(assembly, className);
                if (t == null)
                {
                    Console.WriteLine("ERROR: Unable to resolve type " + className + " in " + assembly);
                    continue;
                }

                ClassCoverageItem klass = ProcessClass(t);

                MethodEntry entry = symbolFile.GetMethodByToken(Int32.Parse(token));

                Module[] modules = assembly.GetModules();

                if (modules.Length > 1)
                {
                    Console.WriteLine("WARNING: Assembly had more than one module. Using the first.");
                }

                Module module = modules[0];

                MethodBase monoMethod = module.ResolveMethod(Int32.Parse(token));

                ProcessMethod(monoMethod, entry, klass, methodName, cov_info);
#else
                if ((TokenType)(itok & 0xff000000) != TokenType.Method)
                {
                    continue;
                }
                AssemblyDefinition assembly   = (AssemblyDefinition)loadedAssemblies [assemblyName];
                MonoSymbolFile     symbolFile = (MonoSymbolFile)symbolFiles [assembly];

                if (symbolFile == null)
                {
                    continue;
                }

                TypeDefinition t = LoadType(assembly, className);
                if (t == null)
                {
                    Console.WriteLine("ERROR: Unable to resolve type " + className + " in " + assembly);
                    continue;
                }

                ClassCoverageItem klass = ProcessClass(t);

                MethodEntry entry = symbolFile.GetMethodByToken(itok);

                MethodDefinition monoMethod = assembly.MainModule.LookupByToken(
                    new MetadataToken((TokenType)(itok & 0xff000000), (uint)(itok & 0xffffff)))
                                              as MethodDefinition;
                //Console.WriteLine (monoMethod);
                ProcessMethod(monoMethod, entry, klass, methodName, cov_info);
#endif
            }

            msec2 = DateTime.Now.Ticks / 10000;
            Console.WriteLine("Process methods: " + (msec2 - msec) + " msec");
            msec = msec2;

            // Add info for klasses for which we have no coverage

#if USE_REFLECTION
            foreach (Assembly assembly in loadedAssemblies.Values)
            {
                foreach (Type t in assembly.GetTypes())
                {
                    ProcessClass(t);
                }
            }

            // Add info for methods for which we have no coverage

            foreach (ClassCoverageItem klass in classes.Values)
            {
                foreach (MethodInfo mb in klass.type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                {
                    MonoSymbolFile symbolFile = (MonoSymbolFile)symbolFiles [klass.type.Assembly];
                    if (symbolFile == null)
                    {
                        continue;
                    }

                    if (!klass.methodsByMethod.ContainsKey(mb))
                    {
                        MethodEntry entry = symbolFile.GetMethod(mb);
                        ProcessMethod(mb, entry, klass, mb.Name, null);
                    }
                }
            }
#else
            Progress("Not covered classes", 0.6);
            foreach (AssemblyDefinition assembly in loadedAssemblies.Values)
            {
                foreach (TypeDefinition t in assembly.MainModule.Types)
                {
                    ProcessClass(t);
                }
            }

            Progress("Not covered methods", 0.7);
            // Add info for methods for which we have no coverage
            foreach (ClassCoverageItem klass in classes.Values)
            {
                foreach (MethodDefinition mb in klass.type.Methods)
                {
                    MonoSymbolFile symbolFile = (MonoSymbolFile)symbolFiles [klass.type.Module.Assembly];
                    if (symbolFile == null)
                    {
                        continue;
                    }

                    if (!klass.methodsByMethod.ContainsKey(mb))
                    {
                        MethodEntry entry = symbolFile.GetMethodByToken((int)mb.MetadataToken.ToUInt());
                        string      name  = GetMethodNameWithParameters(mb);
                        ProcessMethod(mb, entry, klass, name, null);
                    }
                }
            }
#endif

            msec2 = DateTime.Now.Ticks / 10000;
            Console.WriteLine("Additional classes: " + (msec2 - msec) + " msec");
            msec = msec2;

            Progress("Compute coverage", 0.9);
            // Compute coverage for all items

            computeCoverage(true);

            msec2 = DateTime.Now.Ticks / 10000;
            Console.WriteLine("Compute coverage: " + (msec2 - msec) + " msec");
            msec = msec2;

            Console.WriteLine("All: " + (msec2 - begin) + " msec");
            Progress("Done loading", 0.9);

            // Free memory
            symbolFiles = null;
        }
예제 #8
0
 public MethodCoverageItem(ClassCoverageItem parent, String name) : base(parent)
 {
     this.name = name;
 }
예제 #9
0
        private void WriteItem(CoverageItem item, Type stopLevel, int level)
        {
            if (item.filtered)
            {
                return;
            }

            if (item.hit + item.missed == 0)
            {
                // Filtered
                return;
            }

            if (level == 0)
            {
                return;
            }

            if (item.GetType() == stopLevel)
            {
                return;
            }

            if (item is CoverageModel)
            {
                writer.WriteStartElement("project");
                writer.WriteAttributeString("name", "Project");
            }
            else
            if (item is NamespaceCoverageItem)
            {
                NamespaceCoverageItem ns = (NamespaceCoverageItem)item;
                writer.WriteStartElement("namespace");

                if (ns.ns == "<GLOBAL>")
                {
                    writer.WriteAttributeString("name", "GLOBAL");
                }
                else
                {
                    writer.WriteAttributeString("name", ns.ns);
                }
            }
            else
            if (item is ClassCoverageItem)
            {
                ClassCoverageItem klass = (ClassCoverageItem)item;
                writer.WriteStartElement("class");
                writer.WriteAttributeString("name", klass.name);
                writer.WriteAttributeString("fullname", klass.FullName.Replace('/', '.'));
            }

            WriteCoverage(item);

            if (item.ChildCount > 0)
            {
                foreach (CoverageItem child in item.children)
                {
                    WriteItem(child, stopLevel, level - 1);
                }
            }
            writer.WriteEndElement();
        }