From 91c3c2f2c5f14f3f10ee0b8bc67c8bd33976db36 Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Tue, 19 Jan 2016 22:34:09 +1100 Subject: [PATCH 01/30] organize badges [skip-ci] --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 64fbe27a7..06002e2c4 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,11 @@ OpenCover is a code coverage tool for .NET 2 and above (Windows OSs only - no MO The latest releases can be downloaded from [releases](https://github.com/opencover/opencover/releases) or from the OpenCover mirror site on [bitbucket](https://bitbucket.org/shaunwilde/opencover/downloads). **Alternatively** why not try the [nuget](http://nuget.org/packages/opencover) package (this is the most popular). -[![Build status](https://img.shields.io/appveyor/ci/sawilde/opencover.svg)](https://ci.appveyor.com/project/sawilde/opencover) -[![Coverage](https://img.shields.io/coveralls/OpenCover/opencover/master.svg)](https://coveralls.io/r/OpenCover/opencover) -[![Coverity](https://scan.coverity.com/projects/3921/badge.svg)](https://scan.coverity.com/projects/opencover-opencover) -[![Nuget](https://img.shields.io/nuget/dt/opencover.svg)](http://nuget.org/packages/opencover) -[![Nuget](https://img.shields.io/nuget/v/opencover.svg)](http://nuget.org/packages/opencover) -[![Nuget](https://img.shields.io/nuget/vpre/opencover.svg)](http://nuget.org/packages/opencover) +| Build | [![Build status](https://img.shields.io/appveyor/ci/sawilde/opencover.svg)](https://ci.appveyor.com/project/sawilde/opencover) | +| --- | --- | +| **Coverage** | [![Coverage](https://img.shields.io/coveralls/OpenCover/opencover/master.svg)](https://coveralls.io/r/OpenCover/opencover) [![Coverity](https://scan.coverity.com/projects/3921/badge.svg)](https://scan.coverity.com/projects/opencover-opencover) | +| **Nuget** | [![Nuget](https://img.shields.io/nuget/dt/opencover.svg)](http://nuget.org/packages/opencover) [![Nuget](https://img.shields.io/nuget/v/opencover.svg)](http://nuget.org/packages/opencover) [![Nuget](https://img.shields.io/nuget/vpre/opencover.svg)](http://nuget.org/packages/opencover) | +| **Lead Times** | [![Issue Stats](http://issuestats.com/github/opencover/opencover/badge/pr)](http://issuestats.com/github/opencover/opencover) [![Issue Stats](http://issuestats.com/github/opencover/opencover/badge/issue)](http://issuestats.com/github/opencover/opencover) | ### Master The primary repo for the project is [on GitHub](https://github.com/opencover/opencover/) and is also where the [wiki](https://github.com/OpenCover/opencover/wiki) and [issues](https://github.com/OpenCover/opencover/wiki) are managed from. From 952781c83e129cd8871fcb219f968b6983e581fe Mon Sep 17 00:00:00 2001 From: ddur Date: Thu, 21 Jan 2016 13:11:28 +0100 Subject: [PATCH 02/30] Problem 184061 --- main/OpenCover.Framework/Persistance/BasePersistance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 8bcf0630b..f78fc0ee2 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -703,7 +703,7 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera var text = sourceRepository.GetSequencePointText(sp); // Contract.Requires/Ensures is occasionally left inside method offset // Quick check for "C" and minimum length before using Regex - if (text[0] == 'C' && text.Length > 18) { + if (text.Length > 18 && text[0] == 'C') { // Use Regex here! "Contract" and "." and "Requires/Ensures" // can be separated by spaces and newlines if (contractRegex.IsMatch(text)) { From a192f72fab21865340bbb74bf4003fe3fc5c9925 Mon Sep 17 00:00:00 2001 From: ddur Date: Thu, 21 Jan 2016 14:59:50 +0100 Subject: [PATCH 03/30] Handle majority of generated branches without code --- .../Persistance/BasePersistance.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index f78fc0ee2..bc28364e0 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -700,9 +700,9 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera sp.BranchPoints = new List(); } else { // branches not removed // check for other options by reading SequencePoint source - var text = sourceRepository.GetSequencePointText(sp); + var text = sourceRepository.GetSequencePointText(sp); // text is not null // Contract.Requires/Ensures is occasionally left inside method offset - // Quick check for "C" and minimum length before using Regex + // Quick check for minimum length and "C" before using Regex if (text.Length > 18 && text[0] == 'C') { // Use Regex here! "Contract" and "." and "Requires/Ensures" // can be separated by spaces and newlines @@ -721,6 +721,28 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera #endregion } + else { + // Do as much possible without source + // This will remove generated branches within "{" "}" "in" SequencePoints + // but cannot remove Code Contracts ccrewite generated branches + foreach (var sp in method.SequencePoints) { + if (sp != null + && sp.BranchPoints != null + && sp.BranchPoints.Count != 0 + && sp.StartLine == sp.EndLine + && sp.EndColumn > sp.StartColumn + && sp.EndColumn - sp.StartColumn <= 2 + ) { + // Single and two character sequence point should not contain branches + // Never found 1 character sequencePoint except "{" and "}" + // Never found 2 character sequencePoint except "in" keyword + // Afaik, cannot express branch condition in one or two characters of source code + // x|y if(x) while(x) switch(x){...} case: x?. x?? x==y x?y:z; + // do{...}while(x) for(...) foreach(...) x is y + sp.BranchPoints = new List(); + } + } + } } } From 0e0c58b614dc8341717106467b8ae30235b3a498 Mon Sep 17 00:00:00 2001 From: ddur Date: Fri, 22 Jan 2016 17:57:00 +0100 Subject: [PATCH 04/30] Comments&changes when source code absent --- .../Persistance/BasePersistance.cs | 15 ++++++++------- .../Framework/Persistance/FilePersistenceTests.cs | 4 +++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index bc28364e0..33f93a465 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -723,22 +723,23 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera } else { // Do as much possible without source - // This will remove generated branches within "{" "}" "in" SequencePoints - // but cannot remove Code Contracts ccrewite generated branches + // This will remove generated branches within "{", "}" and "in" (single-line SequencePoints) + // but cannot remove Code Contract ccrewite generated branches foreach (var sp in method.SequencePoints) { if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.StartLine == sp.EndLine - && sp.EndColumn > sp.StartColumn + && sp.EndColumn >= sp.StartColumn && sp.EndColumn - sp.StartColumn <= 2 ) { - // Single and two character sequence point should not contain branches + // Zero, one or two character sequence point should not contain branches + // Never found 0 character sequencePoint // Never found 1 character sequencePoint except "{" and "}" // Never found 2 character sequencePoint except "in" keyword - // Afaik, cannot express branch condition in one or two characters of source code - // x|y if(x) while(x) switch(x){...} case: x?. x?? x==y x?y:z; - // do{...}while(x) for(...) foreach(...) x is y + // Afaik, c# cannot express branch condition in one or two characters of source code + // x|y if(x) while(x) switch(x){...} case: x?. x?? x==y x?y:z; for(...) foreach(...) x is y + // "do" keyword does not generate SequencePoint sp.BranchPoints = new List(); } } diff --git a/main/OpenCover.Test/Framework/Persistance/FilePersistenceTests.cs b/main/OpenCover.Test/Framework/Persistance/FilePersistenceTests.cs index 9bec80951..e3bcabfbf 100644 --- a/main/OpenCover.Test/Framework/Persistance/FilePersistenceTests.cs +++ b/main/OpenCover.Test/Framework/Persistance/FilePersistenceTests.cs @@ -61,7 +61,9 @@ public void CanLoadExistingFileWhenInitialising() var moduleHash = Guid.NewGuid().ToString(); var persistence = new FilePersistance(_mockCommandLine.Object, _mockLogger.Object); persistence.Initialise(_filePath, false); - var point = new SequencePoint(); + 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()}; var branchPoint2 = new BranchPoint { Path = 1, OffsetPoints = new List{1,2}}; var file = new OpenCover.Framework.Model.File(); From f7ba475c3967ae25cf0cc9495d0ea745d0d8b6d4 Mon Sep 17 00:00:00 2001 From: ddur Date: Fri, 22 Jan 2016 18:03:51 +0100 Subject: [PATCH 05/30] Include invalid size one-line SequencePoints --- main/OpenCover.Framework/Persistance/BasePersistance.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 33f93a465..401db7132 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -730,7 +730,6 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.StartLine == sp.EndLine - && sp.EndColumn >= sp.StartColumn && sp.EndColumn - sp.StartColumn <= 2 ) { // Zero, one or two character sequence point should not contain branches From f3dab2cd7b8bdcccfcd76380d7827ac3fe11a990 Mon Sep 17 00:00:00 2001 From: ddur Date: Sat, 23 Jan 2016 21:09:42 +0100 Subject: [PATCH 06/30] #498 #498 --- .../Persistance/BasePersistance.cs | 10 +++- .../Utility/CodeCoverageStringTextSource.cs | 52 +++++++++++++------ .../CodeCoverageStringTextSourceTest.cs | 10 +++- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 401db7132..4607cdc89 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -649,7 +649,7 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera CodeCoverageStringTextSource source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); // Do we have C# source? - if (source != null && source.FileType == FileType.CSharp ) { + if (source != null && source.FileFound && source.FileType == FileType.CSharp ) { #region Use sorted SequencePoint's offset and content to Remove Compiler Generated Branches @@ -701,6 +701,14 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera } else { // branches not removed // check for other options by reading SequencePoint source var text = sourceRepository.GetSequencePointText(sp); // text is not null + if (text == string.Empty) { + if (sourceRepository.ContainsKey (sp.FileId)) { + ("File changed?: " + sourceRepository[sp.FileId].FilePath).InformUser(); + } else { + ("File Id " + sp.FileId + " is not available").InformUser(); + } + return; + } // Contract.Requires/Ensures is occasionally left inside method offset // Quick check for minimum length and "C" before using Regex if (text.Length > 18 && text[0] == 'C') { diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index 182395305..ff2613cb8 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -31,10 +31,25 @@ public enum FileType : byte { public class CodeCoverageStringTextSource { /// - /// File Type by file name extension + /// File Type guessed by file-name extension /// - public FileType FileType = FileType.Unsupported; + public FileType FileType { get { return fileType; } } + private readonly FileType fileType = FileType.Unsupported; + + /// + /// Path to source file + /// + public string FilePath { get { return filePath; } } + private readonly string filePath = string.Empty; + + /// + /// Source file found or not + /// + public bool FileFound { get { return fileFound; } } + private readonly bool fileFound = false; + private readonly string textSource; + private struct lineInfo { public int Offset; public int Length; @@ -45,8 +60,19 @@ private struct lineInfo { /// Constructor /// /// - public CodeCoverageStringTextSource(string source) + /// + public CodeCoverageStringTextSource(string source, string filePath = "") { + this.fileFound = source != null; + + if (!string.IsNullOrWhiteSpace (filePath)) { + this.filePath = filePath; + if (this.filePath.IndexOfAny(Path.GetInvalidPathChars()) < 0 + && Path.GetExtension(this.filePath).ToLowerInvariant() == ".cs" ) { + this.fileType = FileType.CSharp; + } + } + if (string.IsNullOrEmpty(source)) { this.textSource = string.Empty; } else { @@ -212,27 +238,19 @@ public string GetLine ( int LineNo ) { /// /// Get line-parsed source from file name /// - /// + /// /// - public static CodeCoverageStringTextSource GetSource(string filename) { + public static CodeCoverageStringTextSource GetSource(string filePath) { - var retSource = new CodeCoverageStringTextSource (string.Empty); + var retSource = new CodeCoverageStringTextSource (null, filePath); // null indicates source-file not found try { - using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) + using (Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader (stream, Encoding.Default, true)) { stream.Position = 0; - retSource = new CodeCoverageStringTextSource(reader.ReadToEnd()); - switch (Path.GetExtension(filename).ToLowerInvariant()) { - case ".cs": - retSource.FileType = FileType.CSharp; - break; - default: - retSource.FileType = FileType.Unsupported; - break; - } + retSource = new CodeCoverageStringTextSource(reader.ReadToEnd(), filePath); } } catch (Exception e) { - // Source is optional (excess-branch removal), application can continue without it + // Source is optional (for excess-branch removal), application can continue without it LogHelper.InformUser(e); // Do not throw ExitApplicationWithoutReportingException } return retSource; diff --git a/main/OpenCover.Test/Framework/Utility/CodeCoverageStringTextSourceTest.cs b/main/OpenCover.Test/Framework/Utility/CodeCoverageStringTextSourceTest.cs index 7d56732a9..674582471 100644 --- a/main/OpenCover.Test/Framework/Utility/CodeCoverageStringTextSourceTest.cs +++ b/main/OpenCover.Test/Framework/Utility/CodeCoverageStringTextSourceTest.cs @@ -333,7 +333,7 @@ public void CountLinesLineFeed() } [Test] - public void CountLinesCarriageReturn() + public void CountLinesCrLf() { // arrange @@ -384,7 +384,9 @@ public void GetSource() // assert Assert.True (!ReferenceEquals(source, null)); - Assert.True (source.FileType == FileType.Unsupported); + Assert.True (source.FileType == FileType.CSharp); + Assert.True (source.FilePath == cSharpFileName); + Assert.False (source.FileFound); // arrange System.IO.File.WriteAllLines(cSharpFileName, lines); @@ -396,6 +398,8 @@ public void GetSource() // assert Assert.True (!ReferenceEquals(source, null)); Assert.True (source.FileType == FileType.CSharp); + Assert.True (source.FilePath == cSharpFileName); + Assert.True (source.FileFound); // arrange System.IO.File.WriteAllLines(vBasicFileName, lines); @@ -407,6 +411,8 @@ public void GetSource() // assert Assert.True (!ReferenceEquals(source, null)); Assert.True (source.FileType == FileType.Unsupported); + Assert.True (source.FilePath == vBasicFileName); + Assert.True (source.FileFound); } } From 58211541a5556d08bc6cccd1d29e9b5527027dc8 Mon Sep 17 00:00:00 2001 From: sawilde Date: Sun, 24 Jan 2016 11:25:07 +1100 Subject: [PATCH 07/30] ignore .sonarqube folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a9a94d914..bc8b1998b 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ coverity.zip #SharpDevelop /**/OpenCover/coverage.xml +/.sonarqube From 17f6b41b7adcc4ba54476afd1e31c94efd5127f8 Mon Sep 17 00:00:00 2001 From: sawilde Date: Sun, 24 Jan 2016 11:25:57 +1100 Subject: [PATCH 08/30] ensure 32 bit preferred flag is false #500 --- .../OpenCover.Console.csproj | 2 ++ main/OpenCover.Test/Console/OutputTests.cs | 33 +++++++++++++++++++ main/OpenCover.Test/OpenCover.Test.csproj | 5 ++- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 main/OpenCover.Test/Console/OutputTests.cs diff --git a/main/OpenCover.Console/OpenCover.Console.csproj b/main/OpenCover.Console/OpenCover.Console.csproj index 8b9b5581b..68291f2b5 100644 --- a/main/OpenCover.Console/OpenCover.Console.csproj +++ b/main/OpenCover.Console/OpenCover.Console.csproj @@ -54,6 +54,7 @@ false ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules true + false ..\bin\Release\ @@ -73,6 +74,7 @@ false false true + false ..\Icons\Icon.ico diff --git a/main/OpenCover.Test/Console/OutputTests.cs b/main/OpenCover.Test/Console/OutputTests.cs new file mode 100644 index 000000000..889709cd9 --- /dev/null +++ b/main/OpenCover.Test/Console/OutputTests.cs @@ -0,0 +1,33 @@ +using System; +using System.Diagnostics; +using System.IO; +using NUnit.Framework; + +// ReSharper disable once CheckNamespace +namespace OpenCover.Test.ConsoleEx +{ + [TestFixture] + public class OutputTests + { + [Test] + public void OutputHasPreferred32BitDisabled() + { + var pi = new ProcessStartInfo() + { + FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\corflags.exe"), + Arguments = "OpenCover.Console.exe", + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true + }; + + var process = Process.Start(pi); + Assert.IsNotNull(process); + var output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Console.WriteLine(output); + + Assert.IsTrue(output.Contains("32BITPREF : 0")); + } + } +} diff --git a/main/OpenCover.Test/OpenCover.Test.csproj b/main/OpenCover.Test/OpenCover.Test.csproj index eb9d68d34..fc1ac316c 100644 --- a/main/OpenCover.Test/OpenCover.Test.csproj +++ b/main/OpenCover.Test/OpenCover.Test.csproj @@ -139,6 +139,7 @@ MoqFramework\UnityAutoMockContainer.cs + @@ -197,9 +198,7 @@ OpenCover.Support - - - + From b7884651d1fd4aa27d0073b4fad40b6370373d5b Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 24 Jan 2016 14:39:18 +0100 Subject: [PATCH 09/30] Source/Module file time compare #498 Source/Module file time compare #498 --- .../Model/InstrumentationModelBuilder.cs | 7 +- main/OpenCover.Framework/Model/Module.cs | 8 +- .../Persistance/BasePersistance.cs | 106 +++++++++--------- .../Utility/CodeCoverageStringTextSource.cs | 10 ++ main/OpenCover.Framework/Utility/LogHelper.cs | 6 +- .../Model/InstrumentationModelBuilderTests.cs | 2 +- .../Persistance/BasePersistenceTests.cs | 44 ++++---- 7 files changed, 104 insertions(+), 79 deletions(-) diff --git a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs index 8c50055de..e2791f800 100644 --- a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs +++ b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs @@ -34,15 +34,18 @@ public Module BuildModuleModel(bool full) private Module CreateModule(bool full) { var hash = string.Empty; + var timeStamp = new DateTime(); if (System.IO.File.Exists(_symbolManager.ModulePath)) { + try { timeStamp = System.IO.File.GetLastWriteTime(_symbolManager.ModulePath); } catch {} hash = HashFile(_symbolManager.ModulePath); } var module = new Module { ModuleName = _symbolManager.ModuleName, - FullName = _symbolManager.ModulePath, - ModuleHash = hash + ModulePath = _symbolManager.ModulePath, + ModuleHash = hash, + ModuleTime = timeStamp }; module.Aliases.Add(_symbolManager.ModulePath); diff --git a/main/OpenCover.Framework/Model/Module.cs b/main/OpenCover.Framework/Model/Module.cs index 0a3b2bd6e..759704f56 100644 --- a/main/OpenCover.Framework/Model/Module.cs +++ b/main/OpenCover.Framework/Model/Module.cs @@ -4,6 +4,7 @@ // This source code is released under the MIT License; see the accompanying license file. // +using System; using System.Collections.Generic; using System.Xml.Serialization; @@ -25,7 +26,12 @@ public Module() /// /// The full path name to the module /// - public string FullName { get; set; } + public string ModulePath { get; set; } + + /// + /// GetlastWriteTime + /// + public DateTime ModuleTime { get; set; } /// /// A list of aliases diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 4607cdc89..9bf7ccc5d 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -65,9 +65,9 @@ public void PersistModule(Module module) { if ( !existingModule.Aliases.Any( - x => x.Equals(module.FullName, StringComparison.InvariantCultureIgnoreCase))) + x => x.Equals(module.ModulePath, StringComparison.InvariantCultureIgnoreCase))) { - existingModule.Aliases.Add(module.FullName); + existingModule.Aliases.Add(module.ModulePath); } return; } @@ -548,8 +548,8 @@ private void TransformSequences() { TransformSequences_Initialize (methods); TransformSequences_JoinWithBranches (methods); TransformSequences_AddSources (module.Files, methods, sourceRepository); - TransformSequences_RemoveCompilerGeneratedBranches (methods, sourceRepository); - TransformSequences_RemoveFalsePositiveUnvisited (methods, sourceRepository); + TransformSequences_RemoveCompilerGeneratedBranches (methods, sourceRepository, module.ModuleTime); + TransformSequences_RemoveFalsePositiveUnvisited (methods, sourceRepository, module.ModuleTime); TransformSequences_ReduceBranches (methods); // last } } @@ -583,8 +583,8 @@ private static void TransformSequences_AddSources (IEnumerable files, IEnu Where (file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) { - var source = CodeCoverageStringTextSource.GetSource(file.FullPath); - if (source != null && source.FileType == FileType.CSharp) sourceRepository.Add (file.UniqueId, source); + var source = CodeCoverageStringTextSource.GetSource(file.FullPath); // never reurns null + if (source.FileType == FileType.CSharp) sourceRepository.Add (file.UniqueId, source); filesDictionary.Add(file.FullPath, file.UniqueId); } @@ -632,7 +632,7 @@ private static void TransformSequences_JoinWithBranches (IEnumerable met // "Contract" and "." and "Requires/Ensures" can be separated by spaces and newlines (valid c# syntax)! private static readonly Regex contractRegex = new Regex(@"^Contract\s*\.\s*(Requi|Ensu)res", regexOptions); - private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumerable methods, SourceRepository sourceRepository) + private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) { foreach (var method in methods) { @@ -646,12 +646,19 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera } // Get method source if availabile - CodeCoverageStringTextSource source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); + var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); // Do we have C# source? - if (source != null && source.FileFound && source.FileType == FileType.CSharp ) { + if (source != null + && source.FileFound + && source.FileType == FileType.CSharp ) { - #region Use sorted SequencePoint's offset and content to Remove Compiler Generated Branches + if (source.FileTime > moduleTime) { + ("Source file is modified: " + source.FilePath).InformUser(); + return; + } + + #region Use line/col-sorted SequencePoint's offset and content to Remove Compiler Generated Branches // initialize offset with unreachable values long startOffset = long.MinValue; @@ -700,13 +707,10 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera sp.BranchPoints = new List(); } else { // branches not removed // check for other options by reading SequencePoint source - var text = sourceRepository.GetSequencePointText(sp); // text is not null + var text = sourceRepository.GetSequencePointText(sp); // text is never null if (text == string.Empty) { - if (sourceRepository.ContainsKey (sp.FileId)) { - ("File changed?: " + sourceRepository[sp.FileId].FilePath).InformUser(); - } else { - ("File Id " + sp.FileId + " is not available").InformUser(); - } + ("Empty sequence-point at line: " + sp.StartLine + " column: " + sp.StartColumn).InformUser(); + ("Source file: " + source.FilePath).InformUser(); return; } // Contract.Requires/Ensures is occasionally left inside method offset @@ -804,7 +808,7 @@ private static void TransformSequences_ReduceBranches (IEnumerable metho } - private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable methods, SourceRepository sourceRepository) + private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) { // From Methods with Source and visited SequencePoints var sequencePointsQuery = methods @@ -850,32 +854,45 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable } if (sequencePointsSet.Contains(sp)) { // Unvisited duplicate found, add to remove list - toRemoveMethodSequencePoint.Add(new Tuple(method,sp)); + toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); } } // Select false unvisited right-curly-braces at generated "MoveNext" method // (Curly braces moved to generated "MoveNext" method and left unvisited) + // Source is required here to identify curly braces if (method.CallName == "MoveNext") { - int countDown = 2; // remove up to two last right-curly-braces - foreach (var sp in method.SequencePoints.Reverse()) { - if (sp != null - && sp.FileId != 0 - && sp.StartLine == sp.EndLine - && sp.StartColumn + 1 == sp.EndColumn - && sp.VisitCount == 0 // unvisited only - ) { - } else { - continue; - } - if (countDown > 0) { - if (sourceRepository.IsRightCurlyBraceSequencePoint(sp)) { - toRemoveMethodSequencePoint.Add(new Tuple(method, sp)); - countDown -= 1; + + // Get method source if availabile + var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); + + // Do we have C# source? + if (source != null + && source.FileFound + && source.FileType == FileType.CSharp + && source.FileTime <= moduleTime + ) { + + int countDown = 2; // remove up to two last right-curly-braces + foreach (var sp in method.SequencePoints.Reverse()) { + if (sp != null + && sp.FileId != 0 + && sp.StartLine == sp.EndLine + && sp.StartColumn + 1 == sp.EndColumn + && sp.VisitCount == 0 // unvisited only + ) { + } else { + continue; + } + if (countDown > 0) { + if (sourceRepository.IsRightCurlyBraceSequencePoint(sp)) { + toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); + countDown -= 1; + } + } + else { + break; } - } - else { - break; } } } @@ -890,26 +907,13 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable tuple.Item1.SequencePoints = cleanSequencePoints.ToArray(); } - #region ToDo + #region ToDo? /* Problems: - * - * - * 1) Compiler can duplicate sequence point (found in DBCL project) - * Solution: DONE - * Remove unvisited duplicate? - * - * 2) Compiler can move SequencePoint into compiler generated method + * Compiler can move SequencePoint into compiler generated method * Solution? * Identify compiler generated methods * Match each with user method * Move SequencePoints & branches into user method - * - * 3) Right braces at IEnumerator + /// Last write DateTime + /// + public DateTime FileTime { get { return timeStamp; } } + private readonly DateTime timeStamp = new DateTime(); + private readonly string textSource; private struct lineInfo { @@ -71,6 +77,10 @@ public CodeCoverageStringTextSource(string source, string filePath = "") && Path.GetExtension(this.filePath).ToLowerInvariant() == ".cs" ) { this.fileType = FileType.CSharp; } + if (this.fileFound) { + try { timeStamp = System.IO.File.GetLastWriteTime (this.filePath); } catch {} + } + } if (string.IsNullOrEmpty(source)) { diff --git a/main/OpenCover.Framework/Utility/LogHelper.cs b/main/OpenCover.Framework/Utility/LogHelper.cs index 0b7c43333..c3d7e1f56 100644 --- a/main/OpenCover.Framework/Utility/LogHelper.cs +++ b/main/OpenCover.Framework/Utility/LogHelper.cs @@ -15,13 +15,15 @@ namespace OpenCover.Framework.Utility /// public static class LogHelper { + const string loggerName = "OpenCover"; + /// /// Use to inform user about handled exception where appropriate (failed IO, Access Rights etc..) /// /// public static void InformUser(this Exception e) { - LogManager.GetLogger("OpenCover").InfoFormat ("An {0} occured: {1} ", e.GetType(), e.Message); + LogManager.GetLogger(loggerName).InfoFormat ("An {0} occured: {1} ", e.GetType(), e.Message); } /// @@ -30,7 +32,7 @@ public static void InformUser(this Exception e) /// public static void InformUser(this string message) { - LogManager.GetLogger("OpenCover").InfoFormat (message); + LogManager.GetLogger(loggerName).InfoFormat (message); } } } diff --git a/main/OpenCover.Test/Framework/Model/InstrumentationModelBuilderTests.cs b/main/OpenCover.Test/Framework/Model/InstrumentationModelBuilderTests.cs index fee20efd6..92f7b3758 100644 --- a/main/OpenCover.Test/Framework/Model/InstrumentationModelBuilderTests.cs +++ b/main/OpenCover.Test/Framework/Model/InstrumentationModelBuilderTests.cs @@ -31,7 +31,7 @@ public void BuildModuleModel_Gets_ModulePath_From_SymbolReader() // assert Assert.IsNotNull(module); - Assert.AreEqual("ModulePath", module.FullName); + Assert.AreEqual("ModulePath", module.ModulePath); Assert.AreEqual("ModulePath", module.Aliases[0]); } diff --git a/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs b/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs index 7f5edcd22..e77eb052e 100644 --- a/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs +++ b/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs @@ -52,9 +52,9 @@ public void Can_Add_SeveralModules_To_Session() //arrange // act - var module1 = new Module {ModuleHash = "123", FullName = "Path1", Classes = new Class[0]}; + var module1 = new Module {ModuleHash = "123", ModulePath = "Path1", Classes = new Class[0]}; module1.Aliases.Add("Path1"); - var module2 = new Module {ModuleHash = "123", FullName = "Path2", Classes = new Class[0]}; + var module2 = new Module {ModuleHash = "123", ModulePath = "Path2", Classes = new Class[0]}; module2.Aliases.Add("Path2"); Instance.PersistModule(module1); Instance.PersistModule(module2); @@ -84,7 +84,7 @@ public void Can_GetBranchPoints_Of_MethodByToken() BranchPoint[] pts; var module = new Module { - FullName = "ModulePath", + ModulePath = "ModulePath", Classes = new[] { new Class @@ -118,7 +118,7 @@ public void Can_GetFullClassName_Of_MethodByToken() // arrange var module = new Module { - FullName = "ModulePath", + ModulePath = "ModulePath", Classes = new[] { new Class {FullName = "namespace.class", Methods = new[] {new Method {MetadataToken = 1001}}} @@ -143,7 +143,7 @@ public void Can_GetSequencePoints_Of_MethodByToken() InstrumentationPoint[] pts; var module = new Module { - FullName = "ModulePath", + ModulePath = "ModulePath", Classes = new[] { new Class @@ -181,9 +181,9 @@ public void Can_Merge_Modules_In_Session_When_HashMatched() .Returns(true); // act - var module1 = new Module {ModuleHash = "123", FullName = "Path1", Classes = new Class[0]}; + var module1 = new Module {ModuleHash = "123", ModulePath = "Path1", Classes = new Class[0]}; module1.Aliases.Add("Path1"); - var module2 = new Module {ModuleHash = "123", FullName = "Path2", Classes = new Class[0]}; + var module2 = new Module {ModuleHash = "123", ModulePath = "Path2", Classes = new Class[0]}; module2.Aliases.Add("Path2"); Instance.PersistModule(module1); Instance.PersistModule(module2); @@ -416,7 +416,7 @@ public void GeBranchPoints_GetsZeroPoints_When_FunctionNotKnown() // arrange var module = new Module { - FullName = "ModuleName", + ModulePath = "ModuleName", Classes = new[] { new Class @@ -445,7 +445,7 @@ public void GetSequencePoints_GetsPoints_When_ModuleAndFunctionKnown_FirstPointI var methodPoint = new InstrumentationPoint {VisitCount = 2000}; var module = new Module { - FullName = "ModulePath", + ModulePath = "ModulePath", Classes = new[] { @@ -486,7 +486,7 @@ public void GetSequencePoints_GetsPoints_When_ModuleAndFunctionKnown_FirstPointI var seqPoint = new SequencePoint {VisitCount = 1000}; var module = new Module { - FullName = "ModulePath", + ModulePath = "ModulePath", Classes = new[] { @@ -525,7 +525,7 @@ public void GetSequencePoints_GetsZeroPoints_When_FunctionNotKnown() // arrange var module = new Module { - FullName = "ModuleName", + ModulePath = "ModuleName", Classes = new[] { new Class @@ -553,7 +553,7 @@ public void GetSequencePoints_GetsZeroPoints_When_ModuleNotKnown() // arrange Instance.PersistModule(new Module { - FullName = "ModuleName", + ModulePath = "ModuleName", Classes = new[] { @@ -639,7 +639,7 @@ public void HideSkipped_With_File_Removes_EmptyClasses() var module = new Module { - FullName = "Keep", + ModulePath = "Keep", Classes = new[] { new Class @@ -694,7 +694,7 @@ public void HideSkipped_With_File_Removes_UnreferencedFiles() Instance.PersistModule(new Module { - FullName = "Keep", + ModulePath = "Keep", Files = new[] {new File {UniqueId = 1, FullPath = "KeepFile"}, new File {UniqueId = 2}}, Classes = new[] { @@ -734,7 +734,7 @@ public void HideSkipped_With_X_Removes_SkippedClasses( @class.MarkAsSkipped(reason); Instance.PersistModule(new Module { - FullName = "Keep", + ModulePath = "Keep", Classes = new[] { @class, @@ -764,7 +764,7 @@ public void HideSkipped_With_X_Removes_SkippedMethods( var module = new Module { - FullName = "Keep", + ModulePath = "Keep", Classes = new[] { new Class @@ -802,17 +802,17 @@ public void HideSkipped_With_X_Removes_SkippedModules( .SetupGet(x => x.HideSkipped) .Returns(new List {reason}); - var module = new Module {FullName = "Skipped"}; + var module = new Module {ModulePath = "Skipped"}; module.MarkAsSkipped(reason); Instance.PersistModule(module); - Instance.PersistModule(new Module {FullName = "Keep"}); + Instance.PersistModule(new Module {ModulePath = "Keep"}); // act Instance.Commit(); // assert Assert.AreEqual(1, Instance.CoverageSession.Modules.Count()); - Assert.AreEqual("Keep", Instance.CoverageSession.Modules[0].FullName); + Assert.AreEqual("Keep", Instance.CoverageSession.Modules[0].ModulePath); } /// @@ -827,7 +827,7 @@ public void var point = new InstrumentationPoint {IsSkipped = false}; var module = new Module { - FullName = "Keep", + ModulePath = "Keep", Classes = new[] { new Class {Methods = new[] {new Method {MethodPoint = point}, new Method()}}, @@ -864,7 +864,7 @@ public void public void IsTracking_Fase_IfModuleSkipped() { // arrange - var module = new Module {FullName = "ModulePath"}; + var module = new Module {ModulePath = "ModulePath"}; module.MarkAsSkipped(SkippedMethod.Filter); module.Aliases.Add("ModulePath"); @@ -881,7 +881,7 @@ public void IsTracking_Fase_IfModuleSkipped() public void IsTracking_True_IfModuleKnown() { // arrange - var module = new Module {FullName = "ModulePath", Classes = new Class[0]}; + var module = new Module {ModulePath = "ModulePath", Classes = new Class[0]}; module.Aliases.Add("ModulePath"); Instance.PersistModule(module); From 6c9a8a91b5c8bcee7c1103b025c94ca6b609b423 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 24 Jan 2016 14:52:21 +0100 Subject: [PATCH 10/30] Check if file time is valid time #498 Check if file time is valid time #498 File.GetLastWriteTime can fail with exception --- main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs | 2 +- main/OpenCover.Framework/Persistance/BasePersistance.cs | 4 +++- .../Utility/CodeCoverageStringTextSource.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs index e2791f800..fa2290b6c 100644 --- a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs +++ b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs @@ -34,7 +34,7 @@ public Module BuildModuleModel(bool full) private Module CreateModule(bool full) { var hash = string.Empty; - var timeStamp = new DateTime(); + var timeStamp = DateTime.MinValue; if (System.IO.File.Exists(_symbolManager.ModulePath)) { try { timeStamp = System.IO.File.GetLastWriteTime(_symbolManager.ModulePath); } catch {} diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 9bf7ccc5d..808fbb098 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -653,7 +653,9 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera && source.FileFound && source.FileType == FileType.CSharp ) { - if (source.FileTime > moduleTime) { + if (source.FileTime != DateTime.MinValue + && moduleTime != DateTime.MinValue + && source.FileTime > moduleTime) { ("Source file is modified: " + source.FilePath).InformUser(); return; } diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index f679d1168..b63857180 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -52,7 +52,7 @@ public class CodeCoverageStringTextSource /// Last write DateTime /// public DateTime FileTime { get { return timeStamp; } } - private readonly DateTime timeStamp = new DateTime(); + private readonly DateTime timeStamp = DateTime.MinValue; private readonly string textSource; From 51cd275e969580caa882c2b572562998275f9214 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 01:55:13 +1100 Subject: [PATCH 11/30] integrate sonarqube #481 --- .gitignore | 3 ++ appveyor.yml | 9 ++++- default.build | 36 +++++++++++++++++-- tools/sonarqube/MSBuild.SonarQube.Runner.exe | Bin 0 -> 23040 bytes tools/sonarqube/SonarQube.Analysis.xml | 33 +++++++++++++++++ tools/sonarqube/SonarQube.Common.dll | Bin 0 -> 50176 bytes 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tools/sonarqube/MSBuild.SonarQube.Runner.exe create mode 100644 tools/sonarqube/SonarQube.Analysis.xml create mode 100644 tools/sonarqube/SonarQube.Common.dll diff --git a/.gitignore b/.gitignore index bc8b1998b..1ed8f602a 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ coverity.zip #SharpDevelop /**/OpenCover/coverage.xml + +#sonarqube /.sonarqube +!tools/sonarqube/**/* diff --git a/appveyor.yml b/appveyor.yml index de3d5422b..17d92e296 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,10 @@ environment: secure: rw3Pk+YPWTG7xG7AaJx8wpxnYAOXM1/7HTRahQGuCHc= COVERITY_EMAIL: secure: lgy4M/uQ9jMlxmPzTIYWVE2GggvPntq6kfpO6Z0pjAs= + SONARQUBE_USER: + secure: +9YfPnwJzGsvdyto85pHwg== + SONARQUBE_PASSWORD: + secure: bGKR0fiOKZo/cNuigVxuUw== cache: - build/Version/opencover.snk - build/Version/opencover.public.snk @@ -18,9 +22,12 @@ build_script: - ps: >- if ($env:APPVEYOR_SCHEDULED_BUILD -eq "True" -or $env:APPVEYOR_REPO_BRANCH -eq "coverity") { & .\build.bat create-coverity-release + } else if ($env:APPVEYOR_REPO_BRANCH -eq "sonar") { + & .\build.bat sonarqube-build } else { & .\build.bat create-release } + test: off artifacts: - path: main/bin/installer/*.msi @@ -71,6 +78,6 @@ notifications: on_build_status_changed: true on_success: - ps: >- - if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity") { + if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity" -and $env:APPVEYOR_REPO_BRANCH -ne "sonar") { & .\build.bat dogfood-release } \ No newline at end of file diff --git a/default.build b/default.build index 5edc0bbb1..51bb2b00a 100644 --- a/default.build +++ b/default.build @@ -25,6 +25,11 @@ + + + + + @@ -82,9 +87,36 @@ - + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + diff --git a/tools/sonarqube/MSBuild.SonarQube.Runner.exe b/tools/sonarqube/MSBuild.SonarQube.Runner.exe new file mode 100644 index 0000000000000000000000000000000000000000..8823dac26b262b057548ada32b3783d3358f97e7 GIT binary patch literal 23040 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 + + + http://sonar.many-monkeys.com:9000 + + + + + + \ No newline at end of file diff --git a/tools/sonarqube/SonarQube.Common.dll b/tools/sonarqube/SonarQube.Common.dll new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b1f8f8b1849d44750343401dc42d21cfa474 GIT binary patch literal 50176 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 literal 0 HcmV?d00001 From 60127ceea8ef1037e227fef0922dff9d064ffdd5 Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Mon, 25 Jan 2016 02:00:34 +1100 Subject: [PATCH 12/30] update ps command --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 17d92e296..d30e24295 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ build_script: - ps: >- if ($env:APPVEYOR_SCHEDULED_BUILD -eq "True" -or $env:APPVEYOR_REPO_BRANCH -eq "coverity") { & .\build.bat create-coverity-release - } else if ($env:APPVEYOR_REPO_BRANCH -eq "sonar") { + } elseif ($env:APPVEYOR_REPO_BRANCH -eq "sonar") { & .\build.bat sonarqube-build } else { & .\build.bat create-release @@ -80,4 +80,4 @@ on_success: - ps: >- if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity" -and $env:APPVEYOR_REPO_BRANCH -ne "sonar") { & .\build.bat dogfood-release - } \ No newline at end of file + } From f3d72a7a7d9f9d112965134cc773b6ea6226b3bf Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 24 Jan 2016 17:20:15 +0100 Subject: [PATCH 13/30] SonarQube: Repeated code #481 SonarQube: Repeated code #481 --- main/OpenCover.Framework/Filter.cs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index 129c5eb80..b068bf3da 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -59,16 +59,20 @@ public Filter(bool useRegexFilters = false) public bool UseAssembly(string processPath, string assemblyPath) { var processName = string.Empty; + var processNameAdd = false; if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException processName = Path.GetFileNameWithoutExtension(processPath); + processNameAdd = !string.IsNullOrEmpty(processName) && processName != processPath; } var assemblyName = string.Empty; + var assemblyNameAdd = false; if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); + assemblyNameAdd = !string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath; } var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((!string.IsNullOrEmpty(processName) && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) + if (assemblyNameAdd) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((processNameAdd && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) { return false; } @@ -79,7 +83,7 @@ public bool UseAssembly(string processPath, string assemblyPath) } var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } if (matchingInclusionFilters.Any()) { return true; @@ -103,16 +107,20 @@ public bool InstrumentClass(string processPath, string assemblyPath, string clas } var processName = string.Empty; + var processNameAdd = false; if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException processName = Path.GetFileNameWithoutExtension(processPath); // can return null + processNameAdd = !string.IsNullOrEmpty(processName) && processName != processPath; } var assemblyName = string.Empty; + var assemblyNameAdd = false; if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); // can return null + assemblyNameAdd = !string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath; } var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((!string.IsNullOrEmpty(processName) && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) + if (assemblyNameAdd) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((processNameAdd && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) { return false; } @@ -125,7 +133,7 @@ public bool InstrumentClass(string processPath, string assemblyPath, string clas } var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } if (matchingInclusionFilters.Any(inclusionFilter => inclusionFilter.IsMatchingClassName(className))) { return true; @@ -363,12 +371,14 @@ public bool InstrumentProcess(string processPath) if (!ExclusionFilters.Any() && !InclusionFilters.Any()) return true; var processName = string.Empty; + var processNameAdd = false; if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException processName = Path.GetFileNameWithoutExtension(processPath); + processNameAdd = !string.IsNullOrWhiteSpace(processName) && processName != processPath; } if (ExclusionFilters.Any()) { var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForProcessName(processPath); - if (!string.IsNullOrWhiteSpace (processName) && processName != processPath) { + if (processNameAdd) { matchingExclusionFilters.AddRange(ExclusionFilters.GetMatchingFiltersForProcessName(processName)); } if (matchingExclusionFilters.Any @@ -384,7 +394,7 @@ public bool InstrumentProcess(string processPath) if (InclusionFilters.Any()) { var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForProcessName(processPath); - if (!string.IsNullOrWhiteSpace (processName) && processName != processPath) { + if (processNameAdd) { matchingInclusionFilters.AddRange(InclusionFilters.GetMatchingFiltersForProcessName(processName)); } return matchingInclusionFilters.Any(); From e2e6700f1b09e697418a4fd667fce7fe72bf4af3 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 24 Jan 2016 18:04:42 +0100 Subject: [PATCH 14/30] SonarCube: Fix 6 new issues #481 SonarCube: Fix 6 new issues #481 --- .../Model/InstrumentationModelBuilder.cs | 7 +++++- .../Utility/CodeCoverageStringTextSource.cs | 24 ++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs index fa2290b6c..ec307989a 100644 --- a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs +++ b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs @@ -9,6 +9,7 @@ using System.Security.Cryptography; using Mono.Cecil; using OpenCover.Framework.Symbols; +using OpenCover.Framework.Utility; namespace OpenCover.Framework.Model { @@ -37,7 +38,11 @@ private Module CreateModule(bool full) var timeStamp = DateTime.MinValue; if (System.IO.File.Exists(_symbolManager.ModulePath)) { - try { timeStamp = System.IO.File.GetLastWriteTime(_symbolManager.ModulePath); } catch {} + try { + timeStamp = System.IO.File.GetLastWriteTime(_symbolManager.ModulePath); + } catch (Exception e) { + e.InformUser(); + } hash = HashFile(_symbolManager.ModulePath); } var module = new Module diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index b63857180..c77749630 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -78,7 +78,11 @@ public CodeCoverageStringTextSource(string source, string filePath = "") this.fileType = FileType.CSharp; } if (this.fileFound) { - try { timeStamp = System.IO.File.GetLastWriteTime (this.filePath); } catch {} + try { + timeStamp = System.IO.File.GetLastWriteTime (this.filePath); + } catch (Exception e) { + e.InformUser(); + } } } @@ -89,6 +93,12 @@ public CodeCoverageStringTextSource(string source, string filePath = "") this.textSource = source; } + lines = initLines (); + + } + + private lineInfo[] initLines () + { lineInfo line; var lineInfoList = new List(); int offset = 0; @@ -98,12 +108,11 @@ public CodeCoverageStringTextSource(string source, string filePath = "") bool lf = false; const ushort carriageReturn = 0xD; const ushort lineFeed = 0xA; - if (textSource != string.Empty) { - foreach ( ushort ch in textSource ) { + foreach (ushort ch in textSource) { switch (ch) { case carriageReturn: - if (lf||cr) { + if (lf || cr) { lf = false; newLine = true; // cr after cr|lf } else { @@ -118,7 +127,7 @@ public CodeCoverageStringTextSource(string source, string filePath = "") } break; default: - if (cr||lf) { + if (cr || lf) { cr = false; lf = false; newLine = true; // any non-line-end char after any line-end @@ -135,16 +144,13 @@ public CodeCoverageStringTextSource(string source, string filePath = "") } ++counter; } - // Add last line line = new lineInfo(); line.Offset = offset; line.Length = counter - offset; lineInfoList.Add(line); - - // Store to readonly field - lines = lineInfoList.ToArray(); } + return lineInfoList.ToArray(); } /// Return text/source using SequencePoint line/col info From 7dce426dbaa12885d2ad03503e12f70f5a4003cb Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 11:32:40 +1100 Subject: [PATCH 15/30] always run coveralls and sonar at end of the build --- appveyor.yml | 6 ++---- default.build | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d30e24295..e6d5ea904 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,8 +22,6 @@ build_script: - ps: >- if ($env:APPVEYOR_SCHEDULED_BUILD -eq "True" -or $env:APPVEYOR_REPO_BRANCH -eq "coverity") { & .\build.bat create-coverity-release - } elseif ($env:APPVEYOR_REPO_BRANCH -eq "sonar") { - & .\build.bat sonarqube-build } else { & .\build.bat create-release } @@ -78,6 +76,6 @@ notifications: on_build_status_changed: true on_success: - ps: >- - if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity" -and $env:APPVEYOR_REPO_BRANCH -ne "sonar") { - & .\build.bat dogfood-release + if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity") { + & .\build.bat sonarqube-build } diff --git a/default.build b/default.build index 51bb2b00a..19f222d5c 100644 --- a/default.build +++ b/default.build @@ -16,6 +16,8 @@ + + @@ -83,7 +85,7 @@ + commandline='--form token=${coverity.token} --insecure --form email=${coverity.email} --form file=@coverity.zip --form version="${ci.fullBuildNumber}" --form description="${ci.fullBuildNumber}" https://scan.coverity.com/builds?project=OpenCover%2Fopencover' /> @@ -106,7 +108,7 @@ - + From ac388cd70a72d5c6f2063490d7d2f5dbf565ccbf Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 12:15:12 +1100 Subject: [PATCH 16/30] address a number of sonar and resharper warnings #481 --- .../SigningExtensions.cs | 5 +- main/OpenCover.Console/Program.cs | 12 ++-- .../ServiceEnvironmentManagement.cs | 3 +- main/OpenCover.Framework/Bootstrapper.cs | 3 +- main/OpenCover.Framework/CommandLineParser.cs | 10 +-- .../CommandLineParserBase.cs | 65 ++++++++++++------- .../Communication/Messages.cs | 3 +- .../Filtering/FilterHelper.cs | 3 +- .../Manager/MemoryManager.cs | 20 ++++-- .../Model/InstrumentationPoint.cs | 7 +- main/OpenCover.Framework/Model/Method.cs | 30 +++++---- .../Persistance/BasePersistance.cs | 51 ++++++++------- .../ProfilerRegistration.cs | 5 +- .../Service/ProfilerCommunication.cs | 8 ++- .../Strategy/TrackedMethodStrategyManager.cs | 6 +- .../Symbols/CecilSymbolManager.cs | 38 ++++++----- main/OpenCover.Specs/Steps/PackagingSteps.cs | 41 ++++++++---- .../UITesting/UITestingHelper.cs | 3 +- 18 files changed, 193 insertions(+), 120 deletions(-) diff --git a/main/OpenCover.3rdParty.Signer/SigningExtensions.cs b/main/OpenCover.3rdParty.Signer/SigningExtensions.cs index 51d56d84e..122f1aca2 100644 --- a/main/OpenCover.3rdParty.Signer/SigningExtensions.cs +++ b/main/OpenCover.3rdParty.Signer/SigningExtensions.cs @@ -11,7 +11,10 @@ public static void SignFile(this AssemblyDefinition definition, string outputPat using (var stream = new FileStream(key, FileMode.Open, FileAccess.Read)) { var keyPair = new StrongNameKeyPair(stream); - definition.Write(outputPath, new WriterParameters() { StrongNameKeyPair = keyPair }); + definition.Write(outputPath, new WriterParameters() + { + StrongNameKeyPair = keyPair + }); } } } diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs index 5e8076555..6d4644af9 100644 --- a/main/OpenCover.Console/Program.cs +++ b/main/OpenCover.Console/Program.cs @@ -48,7 +48,8 @@ static int Main(string[] args) //throw new NullReferenceException(); CommandLineParser parser; - if (!ParseCommandLine(args, out parser)) return parser.ReturnCodeOffset + 1; + if (!ParseCommandLine(args, out parser)) + return parser.ReturnCodeOffset + 1; LogManager.GetRepository().Threshold = parser.LogLevel; @@ -58,7 +59,8 @@ static int Main(string[] args) var perfCounter = CreatePerformanceCounter(parser); string outputFile; - if (!GetFullOutputFile(parser, out outputFile)) return returnCodeOffset + 1; + if (!GetFullOutputFile(parser, out outputFile)) + return returnCodeOffset + 1; using (var container = new Bootstrapper(Logger)) { @@ -385,7 +387,8 @@ private static int RunProcess(CommandLineParser parser, Action private static void DisplayResults(CoverageSession coverageSession, ICommandLine parser, ILog logger) { - if (!logger.IsInfoEnabled) return; + if (!logger.IsInfoEnabled) + return; var altTotalClasses = 0; var altVisitedClasses = 0; @@ -403,7 +406,8 @@ from module in coverageSession.Modules.Where(x=>x.Classes != null) from @class in module.Classes.Where(c => !c.ShouldSerializeSkippedDueTo()) select @class) { - if (@class.Methods == null) continue; + if (@class.Methods == null) + continue; if ((@class.Methods.Any(x => !x.ShouldSerializeSkippedDueTo() && x.SequencePoints.Any(y => y.VisitCount > 0)))) { diff --git a/main/OpenCover.Console/ServiceEnvironmentManagement.cs b/main/OpenCover.Console/ServiceEnvironmentManagement.cs index c9284b714..2f593cdad 100644 --- a/main/OpenCover.Console/ServiceEnvironmentManagement.cs +++ b/main/OpenCover.Console/ServiceEnvironmentManagement.cs @@ -202,8 +202,7 @@ private string[] GetServicesEnvironment() private static unsafe int wcslen(char* s) { char* e; - for (e = s; *e != '\0'; e++) - ; + for (e = s; *e != '\0'; e++){/* intentionally do nothing */} return (int)(e - s); } diff --git a/main/OpenCover.Framework/Bootstrapper.cs b/main/OpenCover.Framework/Bootstrapper.cs index fa66ba6c5..d40e8472b 100644 --- a/main/OpenCover.Framework/Bootstrapper.cs +++ b/main/OpenCover.Framework/Bootstrapper.cs @@ -81,7 +81,8 @@ public void Initialise(IFilter filter, /// 2 public void Dispose() { - if (_container == null) return; + if (_container == null) + return; _container.Dispose(); _container = null; } diff --git a/main/OpenCover.Framework/CommandLineParser.cs b/main/OpenCover.Framework/CommandLineParser.cs index b080b1ef9..b1a41e9f9 100644 --- a/main/OpenCover.Framework/CommandLineParser.cs +++ b/main/OpenCover.Framework/CommandLineParser.cs @@ -300,9 +300,9 @@ private static List ExtractFilters(string rawFilters) return (from Match myMatch in myRegex.Matches(rawFilters) where myMatch.Success select myMatch.Value.Trim()).ToList(); } - private static List ExtractSkipped(string skipped) + private static List ExtractSkipped(string skippedArg) { - if (string.IsNullOrWhiteSpace(skipped)) skipped = "All"; + var skipped = string.IsNullOrWhiteSpace(skippedArg) ? "All" : skippedArg; var options = skipped.Split(';'); var list = new List(); foreach (var option in options) @@ -334,7 +334,8 @@ private TimeSpan ParseTimeoutValue(string timeoutValue) var match = Regex.Match(timeoutValue, @"((?\d+)m)?((?\d+)s)?"); if (match.Success) { - int minutes = 0, seconds = 0; + int minutes = 0; + int seconds = 0; var minutesMatch = match.Groups["minutes"]; if (minutesMatch.Success) @@ -368,7 +369,8 @@ private static Exception ExceptionForInvalidArgumentValue(string argumentName, s private void ValidateArguments() { - if (PrintUsage || PrintVersion) return; + if (PrintUsage || PrintVersion) + return; if (string.IsNullOrWhiteSpace(Target)) { diff --git a/main/OpenCover.Framework/CommandLineParserBase.cs b/main/OpenCover.Framework/CommandLineParserBase.cs index dc03f7b86..345eb01d5 100644 --- a/main/OpenCover.Framework/CommandLineParserBase.cs +++ b/main/OpenCover.Framework/CommandLineParserBase.cs @@ -36,36 +36,51 @@ protected CommandLineParserBase(string[] arguments) /// protected void ParseArguments() { - if (_arguments == null) return; - if (ParsedArguments.Count > 0) return; + if (_arguments == null) + return; + if (ParsedArguments.Count > 0) + return; foreach (var argument in _arguments) { - var trimmed = argument.Trim(); - if (string.IsNullOrEmpty(trimmed)) continue; - - if (!trimmed.StartsWith("-")) - throw new InvalidOperationException(string.Format("The argument '{0}' is not recognised", argument)); - - trimmed = trimmed.Substring(1); - if (string.IsNullOrEmpty(trimmed)) continue; - - var colonidx = trimmed.IndexOf(':'); - if (colonidx>0) - { - var arg = trimmed.Substring(0, colonidx); - var val = trimmed.Substring(colonidx + 1); - if (!ParsedArguments.ContainsKey(arg)) - ParsedArguments.Add(arg, val); - else - ParsedArguments[arg] = (ParsedArguments[arg] + " " + val).Trim(); - } + string trimmed; + if (ExtractTrimmedArgument(argument, out trimmed)) + continue; + + ExtractArgumentValue(trimmed); + } + } + + private void ExtractArgumentValue(string trimmed) + { + var colonidx = trimmed.IndexOf(':'); + if (colonidx > 0) + { + var arg = trimmed.Substring(0, colonidx); + var val = trimmed.Substring(colonidx + 1); + if (!ParsedArguments.ContainsKey(arg)) + ParsedArguments.Add(arg, val); else - { - if (!ParsedArguments.ContainsKey(trimmed)) - ParsedArguments.Add(trimmed, String.Empty); - } + ParsedArguments[arg] = (ParsedArguments[arg] + " " + val).Trim(); } + else + { + if (!ParsedArguments.ContainsKey(trimmed)) + ParsedArguments.Add(trimmed, String.Empty); + } + } + + private static bool ExtractTrimmedArgument(string argument, out string trimmed) + { + trimmed = argument.Trim(); + if (string.IsNullOrEmpty(trimmed)) + return true; + + if (!trimmed.StartsWith("-")) + throw new InvalidOperationException(string.Format("The argument '{0}' is not recognised", argument)); + + trimmed = trimmed.Substring(1); + return string.IsNullOrEmpty(trimmed); } /// diff --git a/main/OpenCover.Framework/Communication/Messages.cs b/main/OpenCover.Framework/Communication/Messages.cs index 34e618dd1..a2d7d079f 100644 --- a/main/OpenCover.Framework/Communication/Messages.cs +++ b/main/OpenCover.Framework/Communication/Messages.cs @@ -11,8 +11,7 @@ namespace OpenCover.Framework.Communication /// The command supportd by the host /// // ReSharper disable InconsistentNaming - // ReSharper disable once EnumUnderlyingTypeIsInt - public enum MSG_Type : int + public enum MSG_Type { /// /// Does this assembly have any code that can be covered diff --git a/main/OpenCover.Framework/Filtering/FilterHelper.cs b/main/OpenCover.Framework/Filtering/FilterHelper.cs index c0c80d49b..929b88dd5 100644 --- a/main/OpenCover.Framework/Filtering/FilterHelper.cs +++ b/main/OpenCover.Framework/Filtering/FilterHelper.cs @@ -13,7 +13,8 @@ internal static string WrapWithAnchors(this string data) internal static string ValidateAndEscape(this string match, string notAllowed = @"\[]") { - if (match.IndexOfAny(notAllowed.ToCharArray()) >= 0) throw new InvalidOperationException(String.Format("The string is invalid for an filter name {0}", match)); + if (match.IndexOfAny(notAllowed.ToCharArray()) >= 0) + throw new InvalidOperationException(String.Format("The string is invalid for an filter name {0}", match)); match = match.Replace(@"\", @"\\"); match = match.Replace(@".", @"\."); match = match.Replace(@"*", @".*"); diff --git a/main/OpenCover.Framework/Manager/MemoryManager.cs b/main/OpenCover.Framework/Manager/MemoryManager.cs index aab48c4c8..b781ec58a 100644 --- a/main/OpenCover.Framework/Manager/MemoryManager.cs +++ b/main/OpenCover.Framework/Manager/MemoryManager.cs @@ -275,7 +275,8 @@ public void Initialise(string @namespace, string key, IEnumerable servic { lock (_lockObject) { - if (_isIntialised) return; + if (_isIntialised) + return; _namespace = @namespace; _key = key; _servicePrincipal = servicePrincipal.ToArray(); @@ -295,7 +296,8 @@ public ManagedBufferBlock AllocateMemoryBuffer(int bufferSize, out uint bufferId lock (_lockObject) { - if (!_isIntialised) return null; + if (!_isIntialised) + return null; bufferId = _bufferId++; var tuple = new ManagedBufferBlock { @@ -316,8 +318,12 @@ public ManagedBufferBlock AllocateMemoryBuffer(int bufferSize, out uint bufferId /// public IList GetBlocks { - get { - lock (_lockObject) { return _blocks; } + get + { + lock (_lockObject) + { + return _blocks; + } } } @@ -330,7 +336,8 @@ public void DeactivateMemoryBuffer(uint bufferId) lock (_lockObject) { var block = _blocks.FirstOrDefault(b => b.BufferId == bufferId); - if (block == null) return; + if (block == null) + return; block.Active = false; } } @@ -342,7 +349,8 @@ public void RemoveDeactivatedBlock(ManagedBufferBlock block) { lock (_lockObject) { - if (block.Active) return; + if (block.Active) + return; block.CommunicationBlock.Do(x => x.Dispose()); block.MemoryBlock.Do(x => x.Dispose()); _blocks.RemoveAt(_blocks.IndexOf(block)); diff --git a/main/OpenCover.Framework/Model/InstrumentationPoint.cs b/main/OpenCover.Framework/Model/InstrumentationPoint.cs index 68266f38f..78117483a 100644 --- a/main/OpenCover.Framework/Model/InstrumentationPoint.cs +++ b/main/OpenCover.Framework/Model/InstrumentationPoint.cs @@ -13,7 +13,7 @@ namespace OpenCover.Framework.Model public class InstrumentationPoint { private static int _instrumentPoint; - private static object _addInstrumentPointSync = new object(); + private static readonly object LockObject = new object(); private static readonly List InstrumentPoints; static InstrumentationPoint() @@ -115,7 +115,7 @@ public static bool AddVisitCount(uint spid, uint trackedMethodId, int sum = 1) /// public InstrumentationPoint() { - lock (_addInstrumentPointSync) + lock (LockObject) { UniqueSequencePoint = (uint)++_instrumentPoint; InstrumentPoints.Add(this); @@ -165,7 +165,8 @@ public TrackedMethodRef[] TrackedMethodRefs set { _tracked = null; - if (value == null) return; + if (value == null) + return; _tracked = new List(value); } } diff --git a/main/OpenCover.Framework/Model/Method.cs b/main/OpenCover.Framework/Model/Method.cs index 9dc76a762..c5693d168 100644 --- a/main/OpenCover.Framework/Model/Method.cs +++ b/main/OpenCover.Framework/Model/Method.cs @@ -111,7 +111,8 @@ public class Method : SummarySkippedEntity public override void MarkAsSkipped(SkippedMethod reason) { SkippedDueTo = reason; - if (MethodPoint != null) MethodPoint.IsSkipped = true; + if (MethodPoint != null) + MethodPoint.IsSkipped = true; MethodPoint = null; SequencePoints = null; BranchPoints = null; @@ -125,9 +126,9 @@ public override void MarkAsSkipped(SkippedMethod reason) internal bool IsGenerated { get { if (_resolvedIsGenerated == null) { - _resolvedIsGenerated = !String.IsNullOrWhiteSpace(this.FullName) - && this.FullName.Contains("__") // quick test before using regex heavy weapon - && isGeneratedMethodRegex.IsMatch(this.FullName); + _resolvedIsGenerated = !string.IsNullOrWhiteSpace(FullName) + && FullName.Contains("__") // quick test before using regex heavy weapon + && IsGeneratedMethodRegex.IsMatch(FullName); } return _resolvedIsGenerated == true; } @@ -138,14 +139,15 @@ internal bool IsGenerated { /// internal string CallName { get { - if (_resolvedCallName != null) { return _resolvedCallName; } // cached - _resolvedCallName = String.Empty; // init resolve value - if (!String.IsNullOrWhiteSpace(this.FullName)) { - int startIndex = this.FullName.IndexOf("::", StringComparison.Ordinal); + if (_resolvedCallName != null) + return _resolvedCallName; + _resolvedCallName = string.Empty; // init resolve value + if (!string.IsNullOrWhiteSpace(FullName)) { + var startIndex = FullName.IndexOf("::", StringComparison.Ordinal); startIndex += 2; - int finalIndex = this.FullName.IndexOf('(', startIndex); + var finalIndex = FullName.IndexOf('(', startIndex); if (startIndex > 1 && finalIndex > startIndex) { - _resolvedCallName = this.FullName // resolve cache + _resolvedCallName = FullName // resolve cache .Substring(startIndex, finalIndex - startIndex); } } @@ -153,10 +155,10 @@ internal string CallName { } } - private bool? _resolvedIsGenerated = null; - private string _resolvedCallName = null; - private static readonly RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; - private static readonly Regex isGeneratedMethodRegex = new Regex(@"(<[^\s:>]+>\w__\w)", regexOptions); + private bool? _resolvedIsGenerated; + private string _resolvedCallName; + private const RegexOptions RegexOptions = System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Singleline | System.Text.RegularExpressions.RegexOptions.ExplicitCapture; + private static readonly Regex IsGeneratedMethodRegex = new Regex(@"(<[^\s:>]+>\w__\w)", RegexOptions); #endregion diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 808fbb098..1c338150c 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -196,7 +196,8 @@ public virtual void Commit() private void RemoveSkippedModules(SkippedMethod skipped) { - if (CoverageSession.Modules == null) return; + if (CoverageSession.Modules == null) + return; var modules = CoverageSession.Modules; modules = modules.Where(x => x.SkippedDueTo != skipped).ToArray(); CoverageSession.Modules = modules; @@ -204,10 +205,12 @@ private void RemoveSkippedModules(SkippedMethod skipped) private void RemoveSkippedClasses(SkippedMethod skipped) { - if (CoverageSession.Modules == null) return; + if (CoverageSession.Modules == null) + return; foreach (var module in CoverageSession.Modules) { - if (module.Classes == null) continue; + if (module.Classes == null) + continue; var classes = module.Classes.Where(x => x.SkippedDueTo != skipped).ToArray(); module.Classes = classes; } @@ -215,13 +218,16 @@ private void RemoveSkippedClasses(SkippedMethod skipped) private void RemoveSkippedMethods(SkippedMethod skipped) { - if (CoverageSession.Modules == null) return; + if (CoverageSession.Modules == null) + return; foreach (var module in CoverageSession.Modules) { - if (module.Classes == null) continue; + if (module.Classes == null) + continue; foreach (var @class in module.Classes) { - if (@class.Methods == null) continue; + if (@class.Methods == null) + continue; var methods = @class.Methods.Where(x => x.SkippedDueTo != skipped).ToArray(); @class.Methods = methods; } @@ -230,17 +236,20 @@ private void RemoveSkippedMethods(SkippedMethod skipped) private void RemoveEmptyClasses() { - if (CoverageSession.Modules == null) return; + if (CoverageSession.Modules == null) + return; foreach (var module in CoverageSession.Modules) { - if (module.Classes == null) continue; + if (module.Classes == null) + continue; module.Classes = module.Classes.Where(@class => @class.Methods != null && @class.Methods.Any()).ToArray(); } } private void RemoveUnreferencedFiles() { - if (CoverageSession.Modules == null) return; + if (CoverageSession.Modules == null) + return; foreach (var module in CoverageSession.Modules) { module.Files = (from file in module.Files ?? new File[0] @@ -306,8 +315,8 @@ private void CalculateCoverage() method.NPathComplexity = 0; var nPaths = new Dictionary(); if (method.BranchPoints != null && method.BranchPoints.Length != 0) { - foreach (var bp in method.BranchPoints) { - if (!Object.ReferenceEquals(bp, null) && nPaths.ContainsKey(bp.Offset)) { + foreach (var bp in method.BranchPoints.Where(b => b != null)) { + if (nPaths.ContainsKey(bp.Offset)) { nPaths[bp.Offset] += 1; } else { nPaths.Add(bp.Offset, 1); @@ -451,7 +460,8 @@ private Method GetMethod(string modulePath, int functionToken, out Class @class) .FirstOrDefault(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase))); if (module == null) return null; - if (!_moduleMethodMap[module].ContainsKey(functionToken)) return null; + if (!_moduleMethodMap[module].ContainsKey(functionToken)) + return null; var pair = _moduleMethodMap[module][functionToken]; @class = pair.Key; return pair.Value; @@ -572,9 +582,10 @@ static void TransformSequences_Initialize (IEnumerable methods) } } - private static void TransformSequences_AddSources (IEnumerable files, IEnumerable methods, IDictionary sourceRepository) + private static void TransformSequences_AddSources (IList files, IEnumerable methods, IDictionary sourceRepository) { - if (files == null || !files.Any()) return; + if (files == null || !files.Any()) + return; // Dictionary with stored source file names per module var filesDictionary = new Dictionary(); @@ -630,7 +641,7 @@ private static void TransformSequences_JoinWithBranches (IEnumerable met // Compiled for speed, treat as .Singleline for multiline SequencePoint, do not waste time to capture Groups (speed) private static readonly RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; // "Contract" and "." and "Requires/Ensures" can be separated by spaces and newlines (valid c# syntax)! - private static readonly Regex contractRegex = new Regex(@"^Contract\s*\.\s*(Requi|Ensu)res", regexOptions); + private static readonly Regex ContractRegex = new Regex(@"^Contract\s*\.\s*(Requi|Ensu)res", regexOptions); private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) { @@ -720,7 +731,7 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera if (text.Length > 18 && text[0] == 'C') { // Use Regex here! "Contract" and "." and "Requires/Ensures" // can be separated by spaces and newlines - if (contractRegex.IsMatch(text)) { + if (ContractRegex.IsMatch(text)) { sp.BranchPoints = new List(); } // "in" keyword? @@ -810,7 +821,7 @@ private static void TransformSequences_ReduceBranches (IEnumerable metho } - private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) + private static void TransformSequences_RemoveFalsePositiveUnvisited (IList methods, SourceRepository sourceRepository, DateTime moduleTime) { // From Methods with Source and visited SequencePoints var sequencePointsQuery = methods @@ -902,11 +913,7 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable // Remove selected SequencePoints foreach (var tuple in toRemoveMethodSequencePoint) { - var cleanSequencePoints = new List(); - foreach (var sp in tuple.Item1.SequencePoints.Where(sp => sp != tuple.Item2)) { - cleanSequencePoints.Add(sp); - } - tuple.Item1.SequencePoints = cleanSequencePoints.ToArray(); + tuple.Item1.SequencePoints = tuple.Item1.SequencePoints.Where(sp => sp != tuple.Item2).ToArray(); } #region ToDo? diff --git a/main/OpenCover.Framework/ProfilerRegistration.cs b/main/OpenCover.Framework/ProfilerRegistration.cs index 21c1a7833..8c91ff07e 100644 --- a/main/OpenCover.Framework/ProfilerRegistration.cs +++ b/main/OpenCover.Framework/ProfilerRegistration.cs @@ -62,7 +62,10 @@ public static void Unregister(Registration registration) private static void ExecuteRegsvr32(bool userRegistration, bool register) { ExecuteRegsvr32(userRegistration, register, false); - if (Environment.Is64BitOperatingSystem) { ExecuteRegsvr32(userRegistration, register, true); } + if (Environment.Is64BitOperatingSystem) + { + ExecuteRegsvr32(userRegistration, register, true); + } } private static int ExecuteProcess(ProcessStartInfo psi) diff --git a/main/OpenCover.Framework/Service/ProfilerCommunication.cs b/main/OpenCover.Framework/Service/ProfilerCommunication.cs index 21a367242..2b6771d19 100644 --- a/main/OpenCover.Framework/Service/ProfilerCommunication.cs +++ b/main/OpenCover.Framework/Service/ProfilerCommunication.cs @@ -27,11 +27,15 @@ public ProfilerCommunication(IFilter filter, public bool TrackAssembly(string processPath, string modulePath, string assemblyName) { - if (_persistance.IsTracking(modulePath)) return true; + if (_persistance.IsTracking(modulePath)) + return true; Module module = null; var builder = _instrumentationModelBuilderFactory.CreateModelBuilder(modulePath, assemblyName); var assemblyPath = assemblyName; - if (modulePath.Contains (assemblyName)) { assemblyPath = modulePath; } + if (modulePath.Contains(assemblyName)) + { + assemblyPath = modulePath; + } if (!_filter.UseAssembly(processPath, assemblyPath)) { module = builder.BuildModuleModel(false); diff --git a/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs b/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs index 664b1abb0..af3fc0209 100644 --- a/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs +++ b/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs @@ -31,7 +31,8 @@ public TrackedMethodStrategyProxy() public TrackedMethod[] GetTrackedMethods(string assembly) { var definition = AssemblyDefinition.ReadAssembly(assembly); - if (definition == null) return new TrackedMethod[0]; + if (definition == null) + return new TrackedMethod[0]; var trackedmethods = new List(); foreach (var trackedMethodStrategy in _strategies) @@ -89,7 +90,8 @@ public TrackedMethod[] GetTrackedMethods(string assembly) public void Dispose() { _proxy = null; - if (_domain == null) return; + if (_domain == null) + return; try { AppDomain.Unload(_domain); diff --git a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs index b9b61d16e..0c76f6bea 100644 --- a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs +++ b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs @@ -15,7 +15,6 @@ using OpenCover.Framework.Model; using OpenCover.Framework.Strategy; using log4net; -using OpenCover.Framework.Utility; using File = OpenCover.Framework.Model.File; using SequencePoint = OpenCover.Framework.Model.SequencePoint; @@ -73,7 +72,7 @@ private SymbolFolder FindSymbolFolder() { var origFolder = Path.GetDirectoryName(ModulePath); - var searchFolders = new List() { origFolder, _commandLine.TargetDir }; + var searchFolders = new List { origFolder, _commandLine.TargetDir }; if (_commandLine.SearchDirs != null) searchFolders.AddRange(_commandLine.SearchDirs); searchFolders.Add(Environment.CurrentDirectory); @@ -118,7 +117,8 @@ private void LoadSourceAssembly() try { var symbolFolder = FindSymbolFolder(); - if (symbolFolder == null) return; + if (symbolFolder == null) + return; var folder = symbolFolder.TargetFolder ?? Environment.CurrentDirectory; var parameters = new ReaderParameters @@ -179,7 +179,8 @@ public File[] GetFiles() public Class[] GetInstrumentableTypes() { - if (SourceAssembly == null) return new Class[0]; + if (SourceAssembly == null) + return new Class[0]; var classes = new List(); IEnumerable typeDefinitions = SourceAssembly.MainModule.Types; @@ -193,8 +194,10 @@ private static void GetInstrumentableTypes(IEnumerable typeDefin { foreach (var typeDefinition in typeDefinitions) { - if (typeDefinition.IsEnum) continue; - if (typeDefinition.IsInterface && typeDefinition.IsAbstract) continue; + if (typeDefinition.IsEnum) + continue; + if (typeDefinition.IsInterface && typeDefinition.IsAbstract) + continue; var @class = new Class { FullName = typeDefinition.FullName }; if (!filter.InstrumentClass(assemblyPath, @class.FullName)) { @@ -266,9 +269,8 @@ private static void BuildMethods(ICollection methods, File[] files, IFil { foreach (var methodDefinition in typeDefinition.Methods) { - if (methodDefinition.IsAbstract) continue; - if (methodDefinition.IsGetter) continue; - if (methodDefinition.IsSetter) continue; + if (methodDefinition.IsAbstract || methodDefinition.IsGetter || methodDefinition.IsSetter) + continue; var method = BuildMethod(files, filter, methodDefinition, false, commandLine); methods.Add(method); @@ -355,7 +357,8 @@ public int GetCyclomaticComplexityForToken(int token) private void BuildMethodMap() { - if (_methodMap.Count > 0) return; + if (_methodMap.Count > 0) + return; IEnumerable typeDefinitions = SourceAssembly.MainModule.Types; BuildMethodMap(typeDefinitions); } @@ -379,7 +382,8 @@ private void BuildMethodMap(IEnumerable typeDefinitions) private void GetSequencePointsForToken(int token, List list) { var methodDefinition = GetMethodDefinition(token); - if (methodDefinition == null) return; + if (methodDefinition == null) + return; try { UInt32 ordinal = 0; @@ -409,7 +413,8 @@ private void GetSequencePointsForToken(int token, List list) private void GetBranchPointsForToken(int token, List list) { var methodDefinition = GetMethodDefinition(token); - if (methodDefinition == null) return; + if (methodDefinition == null) + return; try { UInt32 ordinal = 0; @@ -618,7 +623,8 @@ private List GetBranchPath(Instruction instruction) private Instruction FindClosestSequencePoints(MethodBody methodBody, Instruction instruction) { var sequencePointsInMethod = methodBody.Instructions.Where(HasValidSequencePoint).ToList(); - if (!sequencePointsInMethod.Any()) return null; + if (!sequencePointsInMethod.Any()) + return null; var idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer()); Instruction prev; if (idx < 0) @@ -657,13 +663,15 @@ private MethodDefinition GetMethodDefinition(int token) private void GetCyclomaticComplexityForToken(int token, ref int complexity) { var methodDefinition = GetMethodDefinition(token); - if (methodDefinition == null) return; + if (methodDefinition == null) + return; complexity = Gendarme.Rules.Maintainability.AvoidComplexMethodsRule.GetCyclomaticComplexity(methodDefinition); } public TrackedMethod[] GetTrackedMethods() { - if (SourceAssembly==null) return null; + if (SourceAssembly==null) + return null; var modulePath = ModulePath; if (!System.IO.File.Exists(modulePath)) diff --git a/main/OpenCover.Specs/Steps/PackagingSteps.cs b/main/OpenCover.Specs/Steps/PackagingSteps.cs index ee738ac2c..ec3e143bd 100644 --- a/main/OpenCover.Specs/Steps/PackagingSteps.cs +++ b/main/OpenCover.Specs/Steps/PackagingSteps.cs @@ -24,7 +24,8 @@ public void DeleteZipFolder() public void DeleteMsiFolder() { var folder = Path.GetFullPath(Path.Combine((string)ScenarioContext.Current["targetFolder"], "..")); - if (Directory.Exists(folder)) Directory.Delete(folder, true); + if (Directory.Exists(folder)) + Directory.Delete(folder, true); } private static dynamic GetTargetPackage(string folder, string ext) @@ -51,7 +52,8 @@ public void GivenIHaveAValidZipPackageInTheOutputFolder() var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "zipFolder")); var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "zipoutput.xml")); - if (File.Exists(targetOutput)) File.Delete(targetOutput); + if (File.Exists(targetOutput)) + File.Delete(targetOutput); ScenarioContext.Current["targetZip"] = targetFile; ScenarioContext.Current["targetFolder"] = targetFolder; @@ -62,7 +64,8 @@ public void GivenIHaveAValidZipPackageInTheOutputFolder() public void GivenIUnzipThatPackageIntoADeploymentFolder() { var folder = (string)ScenarioContext.Current["targetFolder"]; - if (Directory.Exists(folder)) Directory.Delete(folder, true); + if (Directory.Exists(folder)) + Directory.Delete(folder, true); var zip = new ZipFile((string)ScenarioContext.Current["targetZip"]); zip.ExtractAll(folder); zip.Dispose(); @@ -79,7 +82,8 @@ public void GivenIHaveAValidNugetpackageInTheOutputFolder() var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "nuFolder")); var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "nuoutput.xml")); - if (File.Exists(targetOutput)) File.Delete(targetOutput); + if (File.Exists(targetOutput)) + File.Delete(targetOutput); ScenarioContext.Current["targetZip"] = targetFile; ScenarioContext.Current["targetFolder"] = targetFolder; @@ -97,7 +101,8 @@ public void GivenIHaveAValidInstallerInTheOutputFolder() var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "msiFolder")); var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "msioutput.xml")); - if (File.Exists(targetOutput)) File.Delete(targetOutput); + if (File.Exists(targetOutput)) + File.Delete(targetOutput); ScenarioContext.Current["targetMsi"] = targetFile; ScenarioContext.Current["targetFolder"] = targetFolder; @@ -108,14 +113,18 @@ public void GivenIHaveAValidInstallerInTheOutputFolder() public void GivenIInstallThatPackageIntoADeploymentFolder() { var folder = (string)ScenarioContext.Current["targetFolder"]; - if (Directory.Exists(folder)) Directory.Delete(folder, true); + if (Directory.Exists(folder)) + Directory.Delete(folder, true); var installer = (string)ScenarioContext.Current["targetMsi"]; var msiExec = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "msiexec.exe"); - var startInfo = new ProcessStartInfo(msiExec); - startInfo.Arguments = string.Format("/qn /a {0} TARGETDIR={1}", installer, folder); - startInfo.UseShellExecute = false; + var startInfo = new ProcessStartInfo(msiExec) + { + Arguments = string.Format("/qn /a {0} TARGETDIR={1}", installer, folder), + UseShellExecute = false + }; var process = Process.Start(startInfo); + Assert.NotNull(process); process.WaitForExit(); ScenarioContext.Current["targetFolder"] = Path.Combine(folder, "[ApplicationFolderName]"); @@ -124,7 +133,7 @@ public void GivenIInstallThatPackageIntoADeploymentFolder() [When(@"I execute the deployed OpenCover against the (x\d\d) target application")] public void WhenIExecuteTheDeployedOpenCoverAgainstTheXTargetApplication(string binFolder) { - this.WhenIExecuteTheDeployedOpenCoverAgainstTheXTargetApplicationInSubfolder(binFolder, string.Empty); + WhenIExecuteTheDeployedOpenCoverAgainstTheXTargetApplicationInSubfolder(binFolder, string.Empty); } [When(@"I execute the deployed OpenCover against the (x\d\d) target application in subfolder (.*)")] @@ -136,14 +145,18 @@ public void WhenIExecuteTheDeployedOpenCoverAgainstTheXTargetApplicationInSubfol var outputXml = string.Format(@"{0}\{1}_{2}{3}", Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), binFolder, Path.GetExtension(output)); - if (File.Exists(outputXml)) File.Delete(outputXml); + if (File.Exists(outputXml)) + File.Delete(outputXml); var openCover = Path.Combine(folder, subfolder, "OpenCover.Console.exe"); var target = Path.Combine(folder, string.Format(@"Samples\{0}\OpenCover.Simple.Target.exe", binFolder)); - var startInfo = new ProcessStartInfo(openCover); - startInfo.Arguments = string.Format(@"-register:user ""-target:{0}"" ""-output:{1}""", target, outputXml); - startInfo.UseShellExecute = false; + var startInfo = new ProcessStartInfo(openCover) + { + Arguments = string.Format(@"-register:user ""-target:{0}"" ""-output:{1}""", target, outputXml), + UseShellExecute = false + }; var process = Process.Start(startInfo); + Assert.NotNull(process); process.WaitForExit(); } diff --git a/main/OpenCover.Support/UITesting/UITestingHelper.cs b/main/OpenCover.Support/UITesting/UITestingHelper.cs index 19fe3f99d..ef94fbb9c 100644 --- a/main/OpenCover.Support/UITesting/UITestingHelper.cs +++ b/main/OpenCover.Support/UITesting/UITestingHelper.cs @@ -13,7 +13,8 @@ public class UITestingHelper public static void PropagateRequiredEnvironmentVariables(object data) { var pi = data as ProcessStartInfo; - if (pi == null) return; + if (pi == null) + return; foreach (var ev in from DictionaryEntry ev in Environment.GetEnvironmentVariables() where (ev.Key.ToString().StartsWith("COR", StringComparison.InvariantCultureIgnoreCase) || ev.Key.ToString().StartsWith("OPEN", StringComparison.InvariantCultureIgnoreCase) || From 8300e188ea13e1c55914c3b28f982c95d63e27d9 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 12:28:13 +1100 Subject: [PATCH 17/30] address duplicate blocks in Filter.cs --- main/OpenCover.Framework/Filter.cs | 105 +++++++++++++---------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index b068bf3da..1e7c90454 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -10,7 +10,6 @@ using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using log4net; -using log4net.Repository.Hierarchy; using Mono.Cecil; using OpenCover.Framework.Filtering; @@ -58,24 +57,11 @@ public Filter(bool useRegexFilters = false) /// as it is the class that is being filtered within these unless the class filter is * public bool UseAssembly(string processPath, string assemblyPath) { - var processName = string.Empty; - var processNameAdd = false; - if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException - processName = Path.GetFileNameWithoutExtension(processPath); - processNameAdd = !string.IsNullOrEmpty(processName) && processName != processPath; - } - var assemblyName = string.Empty; - var assemblyNameAdd = false; - if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException - assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); - assemblyNameAdd = !string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath; - } - var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (assemblyNameAdd) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((processNameAdd && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) - { + string assemblyName; + bool assemblyNameAdd; + IList matchingExclusionFilters; + if (!ExtractExclusionFilters(processPath, assemblyPath, out assemblyName, out assemblyNameAdd, out matchingExclusionFilters)) return false; - } if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName != ".*")) { @@ -84,12 +70,38 @@ public bool UseAssembly(string processPath, string assemblyPath) var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingInclusionFilters.Any()) + return matchingInclusionFilters.Any(); + } + + private bool ExtractExclusionFilters(string processPath, string assemblyPath, out string assemblyName, + out bool assemblyNameAdd, out IList matchingExclusionFilters) + { + var processName = string.Empty; + var processNameAdd = false; + if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { - return true; + // avoids ArgumentException + processName = Path.GetFileNameWithoutExtension(processPath); + processNameAdd = !string.IsNullOrEmpty(processName) && processName != processPath; } - - return false; + assemblyName = string.Empty; + assemblyNameAdd = false; + if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) + { + // avoids ArgumentException + assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); + assemblyNameAdd = !string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath; + } + matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); + if (assemblyNameAdd) + { + matchingExclusionFilters.AddRange(ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); + } + return !matchingExclusionFilters.Any( + exclusionFilter => + exclusionFilter.ClassName == ".*" && + ((processNameAdd && exclusionFilter.IsMatchingProcessName(processName)) || + exclusionFilter.IsMatchingProcessName(processPath))); } /// @@ -106,24 +118,11 @@ public bool InstrumentClass(string processPath, string assemblyPath, string clas return false; } - var processName = string.Empty; - var processNameAdd = false; - if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException - processName = Path.GetFileNameWithoutExtension(processPath); // can return null - processNameAdd = !string.IsNullOrEmpty(processName) && processName != processPath; - } - var assemblyName = string.Empty; - var assemblyNameAdd = false; - if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException - assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); // can return null - assemblyNameAdd = !string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath; - } - var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (assemblyNameAdd) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((processNameAdd && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath)))) - { + string assemblyName; + bool assemblyNameAdd; + IList matchingExclusionFilters; + if (!ExtractExclusionFilters(processPath, assemblyPath, out assemblyName, out assemblyNameAdd, out matchingExclusionFilters)) return false; - } if (matchingExclusionFilters .Where(exclusionFilter => exclusionFilter.ClassName != ".*") @@ -134,12 +133,7 @@ public bool InstrumentClass(string processPath, string assemblyPath, string clas var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } - if (matchingInclusionFilters.Any(inclusionFilter => inclusionFilter.IsMatchingClassName(className))) - { - return true; - } - - return false; + return matchingInclusionFilters.Any(inclusionFilter => inclusionFilter.IsMatchingClassName(className)); } @@ -162,22 +156,22 @@ public bool InstrumentClass(string assemblyPath, string className) /// public void AddFilter(string processAssemblyClassFilter) { - string _assemblyFilter; - string _classFilter; - string _processFilter; + string assemblyFilter; + string classFilter; + string processFilter; FilterType filterType; - GetAssemblyClassName(processAssemblyClassFilter, RegExFilters, out filterType, out _assemblyFilter, out _classFilter, out _processFilter); + GetAssemblyClassName(processAssemblyClassFilter, RegExFilters, out filterType, out assemblyFilter, out classFilter, out processFilter); try { if (!RegExFilters) { - _processFilter = (string.IsNullOrEmpty(_processFilter) ? "*" : _processFilter).ValidateAndEscape("<>|\""); // Path.GetInvalidPathChars except *? - _assemblyFilter = _assemblyFilter.ValidateAndEscape(); - _classFilter = _classFilter.ValidateAndEscape(); + processFilter = (string.IsNullOrEmpty(processFilter) ? "*" : processFilter).ValidateAndEscape("<>|\""); // Path.GetInvalidPathChars except *? + assemblyFilter = assemblyFilter.ValidateAndEscape(); + classFilter = classFilter.ValidateAndEscape(); } - var filter = new AssemblyAndClassFilter(_processFilter, _assemblyFilter, _classFilter); + var filter = new AssemblyAndClassFilter(processFilter, assemblyFilter, classFilter); if (filterType == FilterType.Inclusion) InclusionFilters.Add(filter); @@ -293,10 +287,7 @@ where excludeAttribute.IsMatchingExpression(customAttribute.AttributeType.FullNa /// public bool ExcludeByAttribute(AssemblyDefinition entity) { - if (ExcludedAttributes.Count == 0) - return false; - - return ExcludeByAttribute((ICustomAttributeProvider)entity); + return ExcludedAttributes.Count != 0 && ExcludeByAttribute((ICustomAttributeProvider)entity); } /// From 5b9ba3fee5c70114c835f6418e72c2fbe26fbd6c Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 12:41:22 +1100 Subject: [PATCH 18/30] don't run sonarqube on a pull request --- appveyor.yml | 4 +++- default.build | 13 +++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e6d5ea904..78cf48df7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -76,6 +76,8 @@ notifications: on_build_status_changed: true on_success: - ps: >- - if ($env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity") { + if (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_SCHEDULED_BUILD -ne "True" -and $env:APPVEYOR_REPO_BRANCH -ne "coverity") { & .\build.bat sonarqube-build + } else { + & .\build.bat dogfood-release } diff --git a/default.build b/default.build index 19f222d5c..8e8558f31 100644 --- a/default.build +++ b/default.build @@ -27,11 +27,6 @@ - - - - - @@ -89,8 +84,14 @@ - + + + + + + + From dcf76b0cd2e2f3f69ff9e5f3e7c1c3261a285104 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 16:27:15 +1100 Subject: [PATCH 19/30] improve build speed on appveyor --- .gitignore | 1 + default.build | 19 ++-- main/OpenCover.SonarQube.sln | 170 +++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 main/OpenCover.SonarQube.sln diff --git a/.gitignore b/.gitignore index 1ed8f602a..f3f186f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ coverity.zip #sonarqube /.sonarqube !tools/sonarqube/**/* +/main/OpenCover.SonarQube.sdf diff --git a/default.build b/default.build index 8e8558f31..0efc97524 100644 --- a/default.build +++ b/default.build @@ -86,15 +86,10 @@ - - + - - - - @@ -111,12 +106,12 @@ - - - - - - + + + + + + diff --git a/main/OpenCover.SonarQube.sln b/main/OpenCover.SonarQube.sln new file mode 100644 index 000000000..263a5cfb5 --- /dev/null +++ b/main/OpenCover.SonarQube.sln @@ -0,0 +1,170 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Console", "OpenCover.Console\OpenCover.Console.csproj", "{42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}" + ProjectSection(ProjectDependencies) = postProject + {EE9B358A-335C-43E9-BC35-853807C5E776} = {EE9B358A-335C-43E9-BC35-853807C5E776} + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E} = {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Test", "OpenCover.Test\OpenCover.Test.csproj", "{BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Simple.Target", "OpenCover.Simple.Target\OpenCover.Simple.Target.csproj", "{27AD5F08-0625-4093-8782-F7936737FAB7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Framework", "OpenCover.Framework\OpenCover.Framework.csproj", "{C6F40A34-101B-4BAF-A2F4-6EA28A264F57}" + ProjectSection(ProjectDependencies) = postProject + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E} = {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Root", "Root", "{1E02E180-E417-4810-B8AF-939CB3DB4939}" + ProjectSection(SolutionItems) = preProject + ..\appveyor.yml = ..\appveyor.yml + ..\default.build = ..\default.build + ..\ReleaseNotes.tmp = ..\ReleaseNotes.tmp + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{4337F24C-830C-4A9A-987B-2348F9222C39}" + ProjectSection(SolutionItems) = preProject + ..\build\environment.build = ..\build\environment.build + ..\build\installer.build = ..\build\installer.build + ..\build\opencover.build = ..\build\opencover.build + ..\build\version.build = ..\build\version.build + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Integration.Test", "OpenCover.Integration.Test\OpenCover.Integration.Test.csproj", "{C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}" + ProjectSection(ProjectDependencies) = postProject + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2} = {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.MSBuild", "OpenCover.MSBuild\OpenCover.MSBuild.csproj", "{746A6B40-4570-40CB-BBE5-CEECEE9E220F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{C4B551F8-0420-40EE-B5F8-67487627BFDD}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Specs", "OpenCover.Specs\OpenCover.Specs.csproj", "{5A908D9D-617E-408F-ACED-9E505693DE96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Extensions", "OpenCover.Extensions\OpenCover.Extensions.csproj", "{EE9B358A-335C-43E9-BC35-853807C5E776}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Support", "OpenCover.Support\OpenCover.Support.csproj", "{31B0FAA6-A63F-46FC-96EE-697235DA2BB0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.UITest", "OpenCover.UITest\OpenCover.UITest.csproj", "{E8513153-6298-411D-9BD9-0DB0CC708D34}" + ProjectSection(ProjectDependencies) = postProject + {27AD5F08-0625-4093-8782-F7936737FAB7} = {27AD5F08-0625-4093-8782-F7936737FAB7} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.3rdParty.Signer", "OpenCover.3rdParty.Signer\OpenCover.3rdParty.Signer.csproj", "{0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Debug|x64.ActiveCfg = Debug|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Debug|x64.Build.0 = Debug|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Debug|x86.ActiveCfg = Debug|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Debug|x86.Build.0 = Debug|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Release|x64.ActiveCfg = Release|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Release|x64.Build.0 = Release|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Release|x86.ActiveCfg = Release|Any CPU + {42EA7A31-2D5C-4B50-ACEA-D56C3BAB0CC2}.Release|x86.Build.0 = Release|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Debug|x64.ActiveCfg = Debug|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Debug|x64.Build.0 = Debug|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Debug|x86.ActiveCfg = Debug|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Debug|x86.Build.0 = Debug|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Release|x64.ActiveCfg = Release|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Release|x64.Build.0 = Release|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Release|x86.ActiveCfg = Release|Any CPU + {BDFCE9C6-A116-45AF-94DC-F491D0CE8EB2}.Release|x86.Build.0 = Release|Any CPU + {27AD5F08-0625-4093-8782-F7936737FAB7}.Debug|x64.ActiveCfg = Debug|x64 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Debug|x64.Build.0 = Debug|x64 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Debug|x86.ActiveCfg = Debug|x86 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Debug|x86.Build.0 = Debug|x86 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Release|x64.ActiveCfg = Release|x64 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Release|x64.Build.0 = Release|x64 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Release|x86.ActiveCfg = Release|x86 + {27AD5F08-0625-4093-8782-F7936737FAB7}.Release|x86.Build.0 = Release|x86 + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Debug|x64.ActiveCfg = Debug|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Debug|x64.Build.0 = Debug|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Debug|x86.ActiveCfg = Debug|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Debug|x86.Build.0 = Debug|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Release|x64.ActiveCfg = Release|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Release|x64.Build.0 = Release|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Release|x86.ActiveCfg = Release|Any CPU + {C6F40A34-101B-4BAF-A2F4-6EA28A264F57}.Release|x86.Build.0 = Release|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Debug|x64.ActiveCfg = Debug|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Debug|x64.Build.0 = Debug|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Debug|x86.ActiveCfg = Debug|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Debug|x86.Build.0 = Debug|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Release|x64.ActiveCfg = Release|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Release|x64.Build.0 = Release|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Release|x86.ActiveCfg = Release|Any CPU + {C5533EEB-9AEF-4CC9-8E76-3FFE57D09C23}.Release|x86.Build.0 = Release|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Debug|x64.ActiveCfg = Debug|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Debug|x64.Build.0 = Debug|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Debug|x86.ActiveCfg = Debug|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Debug|x86.Build.0 = Debug|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Release|x64.ActiveCfg = Release|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Release|x64.Build.0 = Release|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Release|x86.ActiveCfg = Release|Any CPU + {746A6B40-4570-40CB-BBE5-CEECEE9E220F}.Release|x86.Build.0 = Release|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Debug|x64.ActiveCfg = Debug|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Debug|x64.Build.0 = Debug|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Debug|x86.ActiveCfg = Debug|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Debug|x86.Build.0 = Debug|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Release|x64.ActiveCfg = Release|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Release|x64.Build.0 = Release|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Release|x86.ActiveCfg = Release|Any CPU + {5A908D9D-617E-408F-ACED-9E505693DE96}.Release|x86.Build.0 = Release|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Debug|x64.ActiveCfg = Debug|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Debug|x64.Build.0 = Debug|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Debug|x86.ActiveCfg = Debug|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Debug|x86.Build.0 = Debug|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Release|x64.ActiveCfg = Release|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Release|x64.Build.0 = Release|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Release|x86.ActiveCfg = Release|Any CPU + {EE9B358A-335C-43E9-BC35-853807C5E776}.Release|x86.Build.0 = Release|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Debug|x64.ActiveCfg = Debug|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Debug|x64.Build.0 = Debug|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Debug|x86.ActiveCfg = Debug|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Debug|x86.Build.0 = Debug|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x64.ActiveCfg = Release|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x64.Build.0 = Release|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x86.ActiveCfg = Release|Any CPU + {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x86.Build.0 = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x64.ActiveCfg = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x64.Build.0 = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x86.ActiveCfg = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x86.Build.0 = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x64.ActiveCfg = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x64.Build.0 = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x86.ActiveCfg = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x86.Build.0 = Release|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Debug|x64.ActiveCfg = Debug|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Debug|x64.Build.0 = Debug|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Debug|x86.ActiveCfg = Debug|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Debug|x86.Build.0 = Debug|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Release|x64.ActiveCfg = Release|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Release|x64.Build.0 = Release|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Release|x86.ActiveCfg = Release|Any CPU + {0B94C4BF-762B-4722-BF5A-30E7F6D2CB7E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4337F24C-830C-4A9A-987B-2348F9222C39} = {1E02E180-E417-4810-B8AF-939CB3DB4939} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35 + EndGlobalSection +EndGlobal From ffbf2817e3db29115e67dd1211519783e3ccb57d Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 16:27:29 +1100 Subject: [PATCH 20/30] address more sonar issues --- .../CrashReporterSigner.cs | 1 + .../GendarmeSigner.cs | 1 + .../SigningExtensions.cs | 2 +- .../Communication/MessageHandler.cs | 2 + .../Communication/Messages.cs | 5 + main/OpenCover.Framework/Filter.cs | 2 - .../Filtering/FilterHelper.cs | 5 +- .../Filtering/RegexFilter.cs | 11 +- .../Manager/MemoryManager.cs | 1 - .../Manager/ProfilerManager.cs | 19 ++- .../Persistance/BasePersistance.cs | 3 +- .../Utility/CodeCoverageStringTextSource.cs | 137 +++++++++--------- main/OpenCover.Specs/Steps/PackagingSteps.cs | 55 ++++--- main/OpenCover.Support/Fakes/FakesHelper.cs | 21 ++- .../Communication/MessageHandlerTests.cs | 13 ++ 15 files changed, 149 insertions(+), 129 deletions(-) diff --git a/main/OpenCover.3rdParty.Signer/CrashReporterSigner.cs b/main/OpenCover.3rdParty.Signer/CrashReporterSigner.cs index f01331edf..b64bb6dd4 100644 --- a/main/OpenCover.3rdParty.Signer/CrashReporterSigner.cs +++ b/main/OpenCover.3rdParty.Signer/CrashReporterSigner.cs @@ -27,6 +27,7 @@ public static bool AlreadySigned(string baseFolder) } catch { + return false; } } return false; diff --git a/main/OpenCover.3rdParty.Signer/GendarmeSigner.cs b/main/OpenCover.3rdParty.Signer/GendarmeSigner.cs index 458f95d3e..cbfcaea7d 100644 --- a/main/OpenCover.3rdParty.Signer/GendarmeSigner.cs +++ b/main/OpenCover.3rdParty.Signer/GendarmeSigner.cs @@ -28,6 +28,7 @@ public static bool AlreadySigned(string baseFolder) } catch { + return false; } } return false; diff --git a/main/OpenCover.3rdParty.Signer/SigningExtensions.cs b/main/OpenCover.3rdParty.Signer/SigningExtensions.cs index 122f1aca2..f87ed2c29 100644 --- a/main/OpenCover.3rdParty.Signer/SigningExtensions.cs +++ b/main/OpenCover.3rdParty.Signer/SigningExtensions.cs @@ -11,7 +11,7 @@ public static void SignFile(this AssemblyDefinition definition, string outputPat using (var stream = new FileStream(key, FileMode.Open, FileAccess.Read)) { var keyPair = new StrongNameKeyPair(stream); - definition.Write(outputPath, new WriterParameters() + definition.Write(outputPath, new WriterParameters { StrongNameKeyPair = keyPair }); diff --git a/main/OpenCover.Framework/Communication/MessageHandler.cs b/main/OpenCover.Framework/Communication/MessageHandler.cs index 0ab052d15..b528444a9 100644 --- a/main/OpenCover.Framework/Communication/MessageHandler.cs +++ b/main/OpenCover.Framework/Communication/MessageHandler.cs @@ -108,6 +108,8 @@ public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Act case MSG_Type.MSG_TrackProcess: writeSize = HandleTrackProcessMessage(pinnedMemory); break; + default: + throw new InvalidOperationException(); } return writeSize; diff --git a/main/OpenCover.Framework/Communication/Messages.cs b/main/OpenCover.Framework/Communication/Messages.cs index a2d7d079f..e2d34bee7 100644 --- a/main/OpenCover.Framework/Communication/Messages.cs +++ b/main/OpenCover.Framework/Communication/Messages.cs @@ -13,6 +13,11 @@ namespace OpenCover.Framework.Communication // ReSharper disable InconsistentNaming public enum MSG_Type { + /// + /// This message is unknown of course + /// + MSG_Unknown = -1, + /// /// Does this assembly have any code that can be covered /// diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index 1e7c90454..b617e4a6b 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -64,9 +64,7 @@ public bool UseAssembly(string processPath, string assemblyPath) return false; if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName != ".*")) - { return true; - } var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } diff --git a/main/OpenCover.Framework/Filtering/FilterHelper.cs b/main/OpenCover.Framework/Filtering/FilterHelper.cs index 929b88dd5..a30dae4fa 100644 --- a/main/OpenCover.Framework/Filtering/FilterHelper.cs +++ b/main/OpenCover.Framework/Filtering/FilterHelper.cs @@ -15,10 +15,7 @@ internal static string ValidateAndEscape(this string match, string notAllowed = { if (match.IndexOfAny(notAllowed.ToCharArray()) >= 0) throw new InvalidOperationException(String.Format("The string is invalid for an filter name {0}", match)); - match = match.Replace(@"\", @"\\"); - match = match.Replace(@".", @"\."); - match = match.Replace(@"*", @".*"); - return match; + return match.Replace(@"\", @"\\").Replace(@".", @"\.").Replace(@"*", @".*"); } internal static IList GetMatchingFiltersForAssemblyName(this IEnumerable filters, string assemblyName) diff --git a/main/OpenCover.Framework/Filtering/RegexFilter.cs b/main/OpenCover.Framework/Filtering/RegexFilter.cs index ee1f01d91..5b432a243 100644 --- a/main/OpenCover.Framework/Filtering/RegexFilter.cs +++ b/main/OpenCover.Framework/Filtering/RegexFilter.cs @@ -5,24 +5,19 @@ namespace OpenCover.Framework.Filtering { internal class RegexFilter { - private readonly Lazy regex; + private readonly Lazy _regex; internal string FilterExpression { get; private set; } public RegexFilter(string filterExpression, bool shouldWrapExpression = true) { FilterExpression = filterExpression; - if (shouldWrapExpression) - { - filterExpression = filterExpression.WrapWithAnchors(); - } - - regex = new Lazy(() => new Regex(filterExpression)); + _regex = new Lazy(() => new Regex(shouldWrapExpression ? filterExpression.WrapWithAnchors() : filterExpression)); } public bool IsMatchingExpression(string input) { - return regex.Value.IsMatch(input); + return _regex.Value.IsMatch(input); } } } diff --git a/main/OpenCover.Framework/Manager/MemoryManager.cs b/main/OpenCover.Framework/Manager/MemoryManager.cs index b781ec58a..9c659b021 100644 --- a/main/OpenCover.Framework/Manager/MemoryManager.cs +++ b/main/OpenCover.Framework/Manager/MemoryManager.cs @@ -44,7 +44,6 @@ public class ManagedBlock protected string MakeName(string name, int id) { var newName = string.Format("{0}{1}{2}{3}", Namespace, name, Key, id); - //Console.WriteLine(newName); return newName; } } diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index d10db9a74..5db0d1ef6 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -39,17 +39,26 @@ public class ProfilerManager : IProfilerManager private ConcurrentQueue _messageQueue; - private readonly object syncRoot = new object (); + private readonly object _syncRoot = new object (); /// /// Syncronisation Root /// public object SyncRoot { get { - return syncRoot; + return _syncRoot; } } + /// + /// wait for how long + /// + internal static int BufferWaitCount + { + get { return _bufferWaitCount; } + set { _bufferWaitCount = value; } + } + private static readonly ILog DebugLogger = LogManager.GetLogger("DebugLogger"); private class ThreadTermination @@ -195,7 +204,7 @@ private WaitCallback SaveVisitData(EventWaitHandle queueMgmt) /// /// wait for how long /// - internal static int BufferWaitCount = 30; + private static int _bufferWaitCount = 30; private bool _continueWait = true; @@ -220,12 +229,14 @@ private void ProcessMessages(WaitHandle[] handles) } })); break; + default: + break; } } while (_continueWait); // we need to let the profilers dump the thread buffers over before they close - max 15s (ish) var i = 0; - while (i < BufferWaitCount && _memoryManager.GetBlocks.Any(b => b.Active)) + while (i < _bufferWaitCount && _memoryManager.GetBlocks.Any(b => b.Active)) { DebugLogger.InfoFormat("Waiting for {0} processes to close", _memoryManager.GetBlocks.Count(b => b.Active)); diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 1c338150c..002a936bc 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -595,7 +595,8 @@ private static void TransformSequences_AddSources (IList files, IEnumerabl && !filesDictionary.ContainsKey(file.FullPath))) { var source = CodeCoverageStringTextSource.GetSource(file.FullPath); // never reurns null - if (source.FileType == FileType.CSharp) sourceRepository.Add (file.UniqueId, source); + if (source.FileType == FileType.CSharp) + sourceRepository.Add (file.UniqueId, source); filesDictionary.Add(file.FullPath, file.UniqueId); } diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index c77749630..e4fd70c87 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Text; using OpenCover.Framework.Model; @@ -33,34 +32,34 @@ public class CodeCoverageStringTextSource /// /// File Type guessed by file-name extension /// - public FileType FileType { get { return fileType; } } - private readonly FileType fileType = FileType.Unsupported; + public FileType FileType { get { return _fileType; } } + private readonly FileType _fileType = FileType.Unsupported; /// /// Path to source file /// - public string FilePath { get { return filePath; } } - private readonly string filePath = string.Empty; + public string FilePath { get { return _filePath; } } + private readonly string _filePath = string.Empty; /// /// Source file found or not /// - public bool FileFound { get { return fileFound; } } - private readonly bool fileFound = false; + public bool FileFound { get { return _fileFound; } } + private readonly bool _fileFound; /// /// Last write DateTime /// - public DateTime FileTime { get { return timeStamp; } } - private readonly DateTime timeStamp = DateTime.MinValue; + public DateTime FileTime { get { return _timeStamp; } } + private readonly DateTime _timeStamp = DateTime.MinValue; - private readonly string textSource; + private readonly string _textSource; - private struct lineInfo { + private struct LineInfo { public int Offset; public int Length; } - private readonly lineInfo[] lines = new lineInfo[0]; + private readonly LineInfo[] _lines; /// /// Constructor @@ -69,17 +68,17 @@ private struct lineInfo { /// public CodeCoverageStringTextSource(string source, string filePath = "") { - this.fileFound = source != null; + _fileFound = source != null; if (!string.IsNullOrWhiteSpace (filePath)) { - this.filePath = filePath; - if (this.filePath.IndexOfAny(Path.GetInvalidPathChars()) < 0 - && Path.GetExtension(this.filePath).ToLowerInvariant() == ".cs" ) { - this.fileType = FileType.CSharp; + _filePath = filePath; + if (_filePath.IndexOfAny(Path.GetInvalidPathChars()) < 0 + && Path.GetExtension(_filePath).ToLowerInvariant() == ".cs" ) { + _fileType = FileType.CSharp; } - if (this.fileFound) { + if (_fileFound) { try { - timeStamp = System.IO.File.GetLastWriteTime (this.filePath); + _timeStamp = System.IO.File.GetLastWriteTime (_filePath); } catch (Exception e) { e.InformUser(); } @@ -87,20 +86,15 @@ public CodeCoverageStringTextSource(string source, string filePath = "") } - if (string.IsNullOrEmpty(source)) { - this.textSource = string.Empty; - } else { - this.textSource = source; - } + _textSource = string.IsNullOrEmpty(source) ? string.Empty : source; - lines = initLines (); + _lines = InitLines (); } - private lineInfo[] initLines () + private LineInfo[] InitLines () { - lineInfo line; - var lineInfoList = new List(); + var lineInfoList = new List(); int offset = 0; int counter = 0; bool newLine = false; @@ -108,9 +102,10 @@ private lineInfo[] initLines () bool lf = false; const ushort carriageReturn = 0xD; const ushort lineFeed = 0xA; - if (textSource != string.Empty) { - foreach (ushort ch in textSource) { - switch (ch) { + if (_textSource != string.Empty) { + LineInfo line; + foreach (var ch in _textSource) { + switch ((ushort)ch) { case carriageReturn: if (lf || cr) { lf = false; @@ -136,18 +131,22 @@ private lineInfo[] initLines () } if (newLine) { // newLine detected - add line newLine = false; - line = new lineInfo(); - line.Offset = offset; - line.Length = counter - offset; + line = new LineInfo + { + Offset = offset, + Length = counter - offset + }; lineInfoList.Add(line); offset = counter; } ++counter; } // Add last line - line = new lineInfo(); - line.Offset = offset; - line.Length = counter - offset; + line = new LineInfo + { + Offset = offset, + Length = counter - offset + }; lineInfoList.Add(line); } return lineInfoList.ToArray(); @@ -158,71 +157,69 @@ private lineInfo[] initLines () /// /// public string GetText(SequencePoint sp) { - return this.GetText(sp.StartLine, sp.StartColumn, sp.EndLine, sp.EndColumn ); + return GetText(sp.StartLine, sp.StartColumn, sp.EndLine, sp.EndColumn ); } /// Return text at Line/Column/EndLine/EndColumn position /// Line and Column counting starts at 1. /// - /// - /// - /// - /// + /// + /// + /// + /// /// - public string GetText(int Line, int Column, int EndLine, int EndColumn) { + public string GetText(int startLine, int startColumn, int endLine, int endColumn) { var text = new StringBuilder(); string line; bool argOutOfRange; - if (Line==EndLine) { + if (startLine==endLine) { #region One-Line request - line = GetLine(Line); + line = GetLine(startLine); - argOutOfRange = Column > EndColumn || Column > line.Length; + argOutOfRange = startColumn > endColumn || startColumn > line.Length; if (!argOutOfRange) { - if (Column < 1) { Column = 1; } - if (EndColumn > line.Length + 1) { EndColumn = line.Length + 1; } - text.Append(line.Substring (Column-1, EndColumn-Column)); + if (startColumn < 1) { startColumn = 1; } + if (endColumn > line.Length + 1) { endColumn = line.Length + 1; } + text.Append(line.Substring (startColumn-1, endColumn-startColumn)); } #endregion - } else if (Line line.Length; + argOutOfRange = startColumn > line.Length; if (!argOutOfRange) { - if (Column < 1) { Column = 1; } - text.Append (line.Substring (Column-1)); + if (startColumn < 1) { startColumn = 1; } + text.Append (line.Substring (startColumn-1)); } #endregion #region More than two lines - for ( int lineIndex = Line + 1; lineIndex < EndLine; lineIndex++ ) { + for ( int lineIndex = startLine + 1; lineIndex < endLine; lineIndex++ ) { text.Append ( GetLine ( lineIndex ) ); } #endregion #region Last line - line = GetLine(EndLine); + line = GetLine(endLine); - argOutOfRange = EndColumn < 1; + argOutOfRange = endColumn < 1; if (!argOutOfRange) { - if (EndColumn > line.Length + 1) { EndColumn = line.Length + 1; } - text.Append(line.Substring(0,EndColumn-1)); + if (endColumn > line.Length + 1) { endColumn = line.Length + 1; } + text.Append(line.Substring(0,endColumn-1)); } #endregion #endregion - } else { - ; - } + } return text.ToString(); } @@ -231,21 +228,21 @@ public string GetText(int Line, int Column, int EndLine, int EndColumn) { /// public int LinesCount { get { - return lines.Length; + return _lines.Length; } } /// Return SequencePoint enumerated line /// - /// + /// /// - public string GetLine ( int LineNo ) { + public string GetLine ( int lineNo ) { - string retString = String.Empty; + string retString = string.Empty; - if ( LineNo > 0 && LineNo <= lines.Length ) { - lineInfo lineInfo = lines[LineNo-1]; - retString = textSource.Substring(lineInfo.Offset, lineInfo.Length); + if ( lineNo > 0 && lineNo <= _lines.Length ) { + LineInfo lineInfo = _lines[lineNo-1]; + retString = _textSource.Substring(lineInfo.Offset, lineInfo.Length); } return retString; @@ -267,7 +264,7 @@ public static CodeCoverageStringTextSource GetSource(string filePath) { } } catch (Exception e) { // Source is optional (for excess-branch removal), application can continue without it - LogHelper.InformUser(e); // Do not throw ExitApplicationWithoutReportingException + e.InformUser(); // Do not throw ExitApplicationWithoutReportingException } return retSource; } diff --git a/main/OpenCover.Specs/Steps/PackagingSteps.cs b/main/OpenCover.Specs/Steps/PackagingSteps.cs index ec3e143bd..c28d65c4e 100644 --- a/main/OpenCover.Specs/Steps/PackagingSteps.cs +++ b/main/OpenCover.Specs/Steps/PackagingSteps.cs @@ -17,7 +17,8 @@ public class PackagingSteps public void DeleteZipFolder() { var folder = (string)ScenarioContext.Current["targetFolder"]; - if (Directory.Exists(folder)) Directory.Delete(folder, true); + if (Directory.Exists(folder)) + Directory.Delete(folder, true); } [AfterScenario("msitag")] @@ -44,20 +45,28 @@ private static dynamic GetTargetPackage(string folder, string ext) [Given(@"I have a valid zip package in the output folder")] public void GivenIHaveAValidZipPackageInTheOutputFolder() { - var target = GetTargetPackage("zip", "zip"); + string targetFolder; + string targetOutput; + var targetFile = BuildTargets("zip", "zip", "zipFolder", "zipoutput.xml", out targetFolder, out targetOutput); + + ScenarioContext.Current["targetZip"] = targetFile; + ScenarioContext.Current["targetFolder"] = targetFolder; + ScenarioContext.Current["targetOutput"] = targetOutput; + } + + private static dynamic BuildTargets(string folder, string ext, string dir, string xml, out string targetFolder, out string targetOutput) + { + var target = GetTargetPackage(folder, ext); - Assert.NotNull(target, "Could not find a valid ZIP file."); + Assert.NotNull(target, "Could not find a valid file."); var targetFile = Path.GetFullPath(target.File); - var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "zipFolder")); - var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "zipoutput.xml")); + targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, dir)); + targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, xml)); - if (File.Exists(targetOutput)) + if (File.Exists(targetOutput)) File.Delete(targetOutput); - - ScenarioContext.Current["targetZip"] = targetFile; - ScenarioContext.Current["targetFolder"] = targetFolder; - ScenarioContext.Current["targetOutput"] = targetOutput; + return targetFile; } [Given(@"I (?:unzip|unpack) that package into a deployment folder")] @@ -74,16 +83,9 @@ public void GivenIUnzipThatPackageIntoADeploymentFolder() [Given(@"I have a valid nugetpackage in the output folder")] public void GivenIHaveAValidNugetpackageInTheOutputFolder() { - var target = GetTargetPackage("nugetpackage", "nupkg"); - - Assert.NotNull(target, "Could not find a valid NUGET file."); - - var targetFile = Path.GetFullPath(target.File); - var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "nuFolder")); - var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "nuoutput.xml")); - - if (File.Exists(targetOutput)) - File.Delete(targetOutput); + string targetFolder; + string targetOutput; + var targetFile = BuildTargets("nugetpackage", "nupkg", "nuFolder", "nuoutput.xml", out targetFolder, out targetOutput); ScenarioContext.Current["targetZip"] = targetFile; ScenarioContext.Current["targetFolder"] = targetFolder; @@ -93,16 +95,9 @@ public void GivenIHaveAValidNugetpackageInTheOutputFolder() [Given(@"I have a valid installer in the output folder")] public void GivenIHaveAValidInstallerInTheOutputFolder() { - var target = GetTargetPackage("installer", "msi"); - - Assert.NotNull(target, "Could not find a valid MSI file."); - - var targetFile = Path.GetFullPath(target.File); - var targetFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "msiFolder")); - var targetOutput = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "msioutput.xml")); - - if (File.Exists(targetOutput)) - File.Delete(targetOutput); + string targetFolder; + string targetOutput; + var targetFile = BuildTargets("installer", "msi", "msiFolder", "msioutput.xml", out targetFolder, out targetOutput); ScenarioContext.Current["targetMsi"] = targetFile; ScenarioContext.Current["targetFolder"] = targetFolder; diff --git a/main/OpenCover.Support/Fakes/FakesHelper.cs b/main/OpenCover.Support/Fakes/FakesHelper.cs index bc8506f8b..bbe70067c 100644 --- a/main/OpenCover.Support/Fakes/FakesHelper.cs +++ b/main/OpenCover.Support/Fakes/FakesHelper.cs @@ -4,7 +4,7 @@ namespace OpenCover.Support.Fakes { - public class FakesHelper + public static class FakesHelper { private const string CorEnableProfiling = "COR_ENABLE_PROFILING"; private const string CorProfiler = "COR_PROFILER"; @@ -15,13 +15,7 @@ public class FakesHelper public static void LoadOpenCoverProfilerInstead(object data) { var dict = data as IDictionary; - if (dict == null) - return; - - if (!dict.ContainsKey(CorEnableProfiling) || dict[CorEnableProfiling] != "1") - return; - - if (!dict.ContainsKey(CorProfiler) || dict[CorProfiler] == OpenCoverProfilerGuid) + if (dict == null || IsAnotherProfilerAttached(dict)) return; var currentProfiler = dict[CorProfiler]; @@ -36,6 +30,17 @@ public static void LoadOpenCoverProfilerInstead(object data) dict[CorProfiler] = OpenCoverProfilerGuid; } + private static bool IsAnotherProfilerAttached(IDictionary dict) + { + if (!dict.ContainsKey(CorEnableProfiling) || dict[CorEnableProfiling] != "1") + return true; + + if (!dict.ContainsKey(CorProfiler) || dict[CorProfiler] == OpenCoverProfilerGuid) + return true; + + return false; + } + public static void PretendWeLoadedFakesProfiler(object data) { var enabled = Environment.GetEnvironmentVariable(CorEnableProfiling); diff --git a/main/OpenCover.Test/Framework/Communication/MessageHandlerTests.cs b/main/OpenCover.Test/Framework/Communication/MessageHandlerTests.cs index a47970ffb..d073d7d08 100644 --- a/main/OpenCover.Test/Framework/Communication/MessageHandlerTests.cs +++ b/main/OpenCover.Test/Framework/Communication/MessageHandlerTests.cs @@ -488,5 +488,18 @@ public void ExceptionDuring_MSG_TrackProcess_ReturnsTrackAsFalse() // assert Assert.AreEqual(false, response.track); } + + [Test] + public void Unsupported_MSG_Type_Throws_Exception() + { + // arrange + Container.GetMock() + .Setup(x => x.PtrToStructure(It.IsAny())) + .Returns(new MSG_TrackMethod_Request()); + + // act + Assert.Throws(() => Instance.StandardMessage(MSG_Type.MSG_Unknown, _mockCommunicationBlock.Object, (i, block) => { }, block => { })); + + } } } From bb27ea0861893c6eeb025e39fb9e0c8503c1ea1a Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 17:04:04 +1100 Subject: [PATCH 21/30] sonar issue --- .../Manager/ProfilerManager.cs | 18 +++++++----------- .../Utility/CodeCoverageStringTextSource.cs | 17 +++++++++-------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index 5db0d1ef6..652fb8790 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -53,11 +53,7 @@ public object SyncRoot { /// /// wait for how long /// - internal static int BufferWaitCount - { - get { return _bufferWaitCount; } - set { _bufferWaitCount = value; } - } + internal static int BufferWaitCount { get; set; } private static readonly ILog DebugLogger = LogManager.GetLogger("DebugLogger"); @@ -201,13 +197,13 @@ private WaitCallback SaveVisitData(EventWaitHandle queueMgmt) }; } - /// - /// wait for how long - /// - private static int _bufferWaitCount = 30; - private bool _continueWait = true; + static ProfilerManager() + { + BufferWaitCount = 30; + } + private void ProcessMessages(WaitHandle[] handles) { var threadHandles = new List(); @@ -236,7 +232,7 @@ private void ProcessMessages(WaitHandle[] handles) // we need to let the profilers dump the thread buffers over before they close - max 15s (ish) var i = 0; - while (i < _bufferWaitCount && _memoryManager.GetBlocks.Any(b => b.Active)) + while (i < BufferWaitCount && _memoryManager.GetBlocks.Any(b => b.Active)) { DebugLogger.InfoFormat("Waiting for {0} processes to close", _memoryManager.GetBlocks.Count(b => b.Active)); diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index e4fd70c87..a85749abc 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -180,10 +180,11 @@ public string GetText(int startLine, int startColumn, int endLine, int endColumn line = GetLine(startLine); argOutOfRange = startColumn > endColumn || startColumn > line.Length; - if (!argOutOfRange) { - if (startColumn < 1) { startColumn = 1; } - if (endColumn > line.Length + 1) { endColumn = line.Length + 1; } - text.Append(line.Substring (startColumn-1, endColumn-startColumn)); + if (!argOutOfRange) + { + var actualStartColumn = (startColumn < 1) ? 1 : startColumn; + var actualEndColumn = (endColumn > line.Length + 1) ? line.Length + 1 : endColumn; + text.Append(line.Substring(actualStartColumn - 1, actualEndColumn - actualStartColumn)); } #endregion @@ -196,8 +197,8 @@ public string GetText(int startLine, int startColumn, int endLine, int endColumn argOutOfRange = startColumn > line.Length; if (!argOutOfRange) { - if (startColumn < 1) { startColumn = 1; } - text.Append (line.Substring (startColumn-1)); + var actualStartColumn = (startColumn < 1) ? 1 : startColumn; + text.Append(line.Substring(actualStartColumn - 1)); } #endregion @@ -212,8 +213,8 @@ public string GetText(int startLine, int startColumn, int endLine, int endColumn argOutOfRange = endColumn < 1; if (!argOutOfRange) { - if (endColumn > line.Length + 1) { endColumn = line.Length + 1; } - text.Append(line.Substring(0,endColumn-1)); + var actualEndColumn = (endColumn > line.Length + 1) ? line.Length + 1 : endColumn; + text.Append(line.Substring(0, actualEndColumn - 1)); } #endregion From 0eb2f9bc1678ea3bededec2f5e6aac30ef9d43e5 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 20:33:57 +1100 Subject: [PATCH 22/30] more sonar work --- .../ServiceEnvironmentManagement.cs | 7 +- main/OpenCover.Framework/Filter.cs | 70 +++-- main/OpenCover.Framework/HelperExtensions.cs | 3 - .../Manager/ProfilerManager.cs | 2 +- .../Model/InstrumentationModelBuilder.cs | 8 +- .../Model/InstrumentationPoint.cs | 14 +- .../Persistance/BasePersistance.cs | 240 +++++++++++------- .../ProfilerRegistration.cs | 2 +- .../Service/IProfilerCommunication.cs | 18 +- .../Symbols/CecilSymbolManager.cs | 93 +++---- .../Utility/IPerfCounters.cs | 2 +- .../Utility/PerfCounters.cs | 11 +- .../ProfilerBaseFixture.cs | 2 +- .../UITesting/UITestingHelper.cs | 2 +- main/OpenCover.Test/Framework/FilterTests.cs | 57 ++--- .../Symbols/CecilSymbolManagerTests.cs | 2 +- main/OpenCover.Test/Samples/SimpleXUnit.cs | 2 +- 17 files changed, 293 insertions(+), 242 deletions(-) diff --git a/main/OpenCover.Console/ServiceEnvironmentManagement.cs b/main/OpenCover.Console/ServiceEnvironmentManagement.cs index 2f593cdad..8a1c53009 100644 --- a/main/OpenCover.Console/ServiceEnvironmentManagement.cs +++ b/main/OpenCover.Console/ServiceEnvironmentManagement.cs @@ -16,15 +16,12 @@ */ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; using OpenCover.Framework; -using System.ServiceProcess; -using System.ComponentModel; namespace OpenCover.Console { @@ -58,7 +55,7 @@ public void PrepareServiceEnvironment(string serviceName, ServiceEnvironment env // variables in the registry for the service, otherwise it's better to temporarily set it for the account, // assuming we can find out the account SID // Network Service works better with environments is better on the service too - var serviceAccountName = MachineQualifiedServiceAccountName(this._serviceName); + var serviceAccountName = MachineQualifiedServiceAccountName(_serviceName); if (serviceAccountName != "LocalSystem") { _serviceAccountSid = LookupAccountSid(serviceAccountName); @@ -83,7 +80,7 @@ public static string MachineQualifiedServiceAccountName(string serviceName) { serviceAccountName = Environment.MachineName + serviceAccountName.Substring(1); } - else if (serviceAccountName.ToLower().Contains("localsystem")) + else if (serviceAccountName.ToLowerInvariant().Contains("localsystem")) { serviceAccountName = "NT Authority\\SYSTEM"; } diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index b617e4a6b..b6ec194eb 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -38,7 +38,7 @@ public class Filter : IFilter /// Standard constructor /// /// Indicates if the input strings for this class are already Regular Expressions - public Filter(bool useRegexFilters = false) + public Filter(bool useRegexFilters) { InclusionFilters = new List(); ExclusionFilters = new List(); @@ -228,48 +228,72 @@ public void AddAttributeExclusionFilters(string[] exclusionFilters) /// /// Is this entity (method/type) excluded due to an attributeFilter /// - /// The entity to test + /// The entity to test /// - public bool ExcludeByAttribute(IMemberDefinition entity) + public bool ExcludeByAttribute(IMemberDefinition originalEntity) { if (ExcludedAttributes.Count == 0) return false; + var entity = originalEntity; while (true) { if (entity == null) return false; - if (ExcludeByAttribute((ICustomAttributeProvider)entity)) - return true; - - if (ExcludeByAttribute(entity.DeclaringType)) - return true; + bool excludeByAttribute; + if (IsExcludedByAttributeSimple(entity, out excludeByAttribute)) + return excludeByAttribute; - if (entity.DeclaringType == null || !entity.Name.StartsWith("<")) + MethodDefinition target; + if (!GetDeclaringMethod(entity, out target)) return false; - var match = Regex.Match(entity.Name, @"\<(?.+)\>.+"); - if (match.Groups["name"] == null) return false; - var name = match.Groups["name"].Value; - var target = entity.DeclaringType.Methods.FirstOrDefault(m => m.Name == name); - if (target == null) return false; - if (target.IsGetter) - { - var getMethod = entity.DeclaringType.Properties.FirstOrDefault(p => p.GetMethod == target); - entity = getMethod; - continue; - } - if (target.IsSetter) + if (target.IsGetter || target.IsSetter) { - var setMethod = entity.DeclaringType.Properties.FirstOrDefault(p => p.SetMethod == target); - entity = setMethod; + entity = entity.DeclaringType.Properties.FirstOrDefault(p => p.GetMethod == target || p.SetMethod == target); continue; } entity = target; } } + /// + /// Look for the declaring method e.g. if method is some type of lambda, getter/setter etc + /// + /// + /// + /// + private static bool GetDeclaringMethod(IMemberDefinition entity, out MethodDefinition target) + { + target = null; + var match = Regex.Match(entity.Name, @"\<(?.+)\>.+"); + if (match.Groups["name"] == null) + return false; + + var name = match.Groups["name"].Value; + target = entity.DeclaringType.Methods.FirstOrDefault(m => m.Name == name); + if (target == null) + return false; + return true; + } + + private bool IsExcludedByAttributeSimple(IMemberDefinition entity, out bool excludeByAttribute) + { + excludeByAttribute = true; + if (ExcludeByAttribute((ICustomAttributeProvider) entity)) + return true; + + if (ExcludeByAttribute(entity.DeclaringType)) + return true; + + if (entity.DeclaringType != null && entity.Name.StartsWith("<")) + return false; + + excludeByAttribute = false; + return true; + } + private bool ExcludeByAttribute(ICustomAttributeProvider entity) { return (from excludeAttribute in ExcludedAttributes diff --git a/main/OpenCover.Framework/HelperExtensions.cs b/main/OpenCover.Framework/HelperExtensions.cs index aa3122f1d..ae3cd2777 100644 --- a/main/OpenCover.Framework/HelperExtensions.cs +++ b/main/OpenCover.Framework/HelperExtensions.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace OpenCover.Framework { diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index 652fb8790..8db9d40c8 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -343,7 +343,7 @@ private WaitCallback ProcessBlock(ManagedBufferBlock block, } while (_messageQueue.Count > 200); } break; - case 2: + default: // 2 return; } } diff --git a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs index ec307989a..1492d89a2 100644 --- a/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs +++ b/main/OpenCover.Framework/Model/InstrumentationModelBuilder.cs @@ -68,12 +68,12 @@ private Module CreateModule(bool full) public Module BuildModuleTestModel(Module module, bool full) { - module = module ?? CreateModule(full); - module.TrackedMethods = _symbolManager.GetTrackedMethods(); - return module; + var m = module ?? CreateModule(full); + m.TrackedMethods = _symbolManager.GetTrackedMethods(); + return m; } - private string HashFile(string sPath) + private static string HashFile(string sPath) { using (var sr = new StreamReader(sPath)) using (var prov = new SHA1CryptoServiceProvider()) diff --git a/main/OpenCover.Framework/Model/InstrumentationPoint.cs b/main/OpenCover.Framework/Model/InstrumentationPoint.cs index 78117483a..6281c546d 100644 --- a/main/OpenCover.Framework/Model/InstrumentationPoint.cs +++ b/main/OpenCover.Framework/Model/InstrumentationPoint.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Threading; using System.Xml.Serialization; namespace OpenCover.Framework.Model @@ -74,17 +72,17 @@ public static int GetVisitCount(uint spid) } /// - /// Add a number of recorded visit pints against this identifier + /// Add a number of recorded visit ppints against this identifier /// /// the sequence point identifier - NOTE 0 is not used /// the id of a tracked method - Note 0 means no method currently tracking - /// the number of visit points to add - public static bool AddVisitCount(uint spid, uint trackedMethodId, int sum = 1) + /// the number of visit points to add + public static bool AddVisitCount(uint spid, uint trackedMethodId, int amount) { if (spid != 0 && spid < InstrumentPoints.Count) { var point = InstrumentPoints[(int) spid]; - point.VisitCount += sum; + point.VisitCount += amount; if (point.VisitCount < 0) point.VisitCount = int.MaxValue; if (trackedMethodId != 0) @@ -93,12 +91,12 @@ public static bool AddVisitCount(uint spid, uint trackedMethodId, int sum = 1) var tracked = point._tracked.Find(x => x.UniqueId == trackedMethodId); if (tracked == null) { - tracked = new TrackedMethodRef {UniqueId = trackedMethodId, VisitCount = sum}; + tracked = new TrackedMethodRef {UniqueId = trackedMethodId, VisitCount = amount}; point._tracked.Add(tracked); } else { - tracked.VisitCount += sum; + tracked.VisitCount += amount; if (tracked.VisitCount < 0) tracked.VisitCount = int.MaxValue; } diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 002a936bc..3c32ff3ff 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -157,41 +157,43 @@ public bool IsTracking(string modulePath) /// public virtual void Commit() { - if (CoverageSession.Modules != null) { - MarkSkippedMethods(); - TransformSequences(); - CalculateCoverage(); - if (CommandLine.HideSkipped != null && CommandLine.HideSkipped.Any()) { - foreach (var skippedMethod in CommandLine.HideSkipped.OrderBy(x => x)) - { - switch (skippedMethod) - { - case SkippedMethod.File: - RemoveSkippedMethods(SkippedMethod.File); - RemoveEmptyClasses(); - RemoveUnreferencedFiles(); - break; - case SkippedMethod.Filter: - RemoveSkippedModules(SkippedMethod.Filter); - RemoveSkippedClasses(SkippedMethod.Filter); - break; - case SkippedMethod.MissingPdb: - RemoveSkippedModules(SkippedMethod.MissingPdb); - break; - case SkippedMethod.Attribute: - RemoveSkippedClasses(SkippedMethod.Attribute); - RemoveSkippedMethods(SkippedMethod.Attribute); - RemoveEmptyClasses(); - break; - case SkippedMethod.AutoImplementedProperty: - RemoveSkippedMethods(SkippedMethod.Attribute); - RemoveEmptyClasses(); - break; - } - } - } - } + if (CoverageSession.Modules == null) + return; + MarkSkippedMethods(); + TransformSequences(); + CalculateCoverage(); + if (CommandLine.HideSkipped == null || !CommandLine.HideSkipped.Any()) + return; + foreach (var skippedMethod in CommandLine.HideSkipped.OrderBy(x => x)) + ProcessSkippedAction(skippedMethod); + } + private void ProcessSkippedAction(SkippedMethod skippedMethod) + { + switch (skippedMethod) + { + case SkippedMethod.File: + RemoveSkippedMethods(SkippedMethod.File); + RemoveEmptyClasses(); + RemoveUnreferencedFiles(); + break; + case SkippedMethod.Filter: + RemoveSkippedModules(SkippedMethod.Filter); + RemoveSkippedClasses(SkippedMethod.Filter); + break; + case SkippedMethod.MissingPdb: + RemoveSkippedModules(SkippedMethod.MissingPdb); + break; + case SkippedMethod.Attribute: + RemoveSkippedClasses(SkippedMethod.Attribute); + RemoveSkippedMethods(SkippedMethod.Attribute); + RemoveEmptyClasses(); + break; + case SkippedMethod.AutoImplementedProperty: + RemoveSkippedMethods(SkippedMethod.Attribute); + RemoveEmptyClasses(); + break; + } } private void RemoveSkippedModules(SkippedMethod skipped) @@ -281,86 +283,128 @@ private void CalculateCoverage() foreach (var @class in (module.Classes ?? new Class[0]).Where(x => x != null && !x.ShouldSerializeSkippedDueTo())) { foreach (var method in (@class.Methods ?? new Method[0]).Where(x => x != null && !x.ShouldSerializeSkippedDueTo())) - { - if (method.MethodPoint != null) - { - method.Visited = (method.MethodPoint.VisitCount > 0); - } + ProcessMethodData(method, @class); - method.Summary.NumBranchPoints = method.BranchPoints == null ? 0 : method.BranchPoints.Count(); - method.Summary.VisitedBranchPoints = method.BranchPoints == null ? 0 : method.BranchPoints.Count(pt => pt.VisitCount != 0); - method.Summary.NumSequencePoints = method.SequencePoints == null ? 0 : method.SequencePoints.Count(); - method.Summary.VisitedSequencePoints = method.SequencePoints == null ? 0 : method.SequencePoints.Count(pt => pt.VisitCount != 0); + ProcessClassData(@class, module); + } + ProcessModuleData(module); + } + CalculateCoverage(CoverageSession.Summary); + } - if (method.Summary.NumSequencePoints > 0) - method.Summary.NumBranchPoints += 1; + private void ProcessModuleData(Module module) + { + AddPoints(CoverageSession.Summary, module.Summary); + CalculateCoverage(module.Summary); - if (method.Summary.VisitedSequencePoints > 0) - method.Summary.VisitedBranchPoints += 1; + if (CoverageSession.Summary.MinCyclomaticComplexity == 0) + CoverageSession.Summary.MinCyclomaticComplexity = module.Summary.MinCyclomaticComplexity; - if (method.FileRef != null) - { - method.Summary.NumMethods = 1; - method.Summary.VisitedMethods = (method.Visited) ? 1 : 0; - } + CoverageSession.Summary.MinCyclomaticComplexity = Math.Min(CoverageSession.Summary.MinCyclomaticComplexity, + module.Summary.MinCyclomaticComplexity); + CoverageSession.Summary.MaxCyclomaticComplexity = Math.Max(CoverageSession.Summary.MaxCyclomaticComplexity, + module.Summary.MaxCyclomaticComplexity); + } - AddPoints(@class.Summary, method.Summary); - CalculateCoverage(method.Summary); + private static void ProcessClassData(Class @class, Module module) + { + @class.Summary.NumClasses = (@class.Summary.NumMethods > 0) ? 1 : 0; + @class.Summary.VisitedClasses = (@class.Summary.VisitedMethods > 0) ? 1 : 0; - method.SequenceCoverage = method.Summary.SequenceCoverage; - method.BranchCoverage = method.Summary.BranchCoverage; + AddPoints(module.Summary, @class.Summary); + CalculateCoverage(@class.Summary); - method.Summary.MinCyclomaticComplexity = method.Summary.MaxCyclomaticComplexity = Math.Max(1, method.CyclomaticComplexity); + if (module.Summary.MinCyclomaticComplexity == 0) + module.Summary.MinCyclomaticComplexity = @class.Summary.MinCyclomaticComplexity; - method.NPathComplexity = 0; - var nPaths = new Dictionary(); - if (method.BranchPoints != null && method.BranchPoints.Length != 0) { - foreach (var bp in method.BranchPoints.Where(b => b != null)) { - if (nPaths.ContainsKey(bp.Offset)) { - nPaths[bp.Offset] += 1; - } else { - nPaths.Add(bp.Offset, 1); - } - } - } - foreach(var branches in nPaths.Values) { - if (method.NPathComplexity == 0) { - method.NPathComplexity = branches; - } else { - method.NPathComplexity *= branches; - } - } + module.Summary.MinCyclomaticComplexity = Math.Min(module.Summary.MinCyclomaticComplexity, + @class.Summary.MinCyclomaticComplexity); + module.Summary.MaxCyclomaticComplexity = Math.Max(module.Summary.MaxCyclomaticComplexity, + @class.Summary.MaxCyclomaticComplexity); + } - if (@class.Summary.MinCyclomaticComplexity == 0) - @class.Summary.MinCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; - - @class.Summary.MinCyclomaticComplexity = Math.Min(@class.Summary.MinCyclomaticComplexity, method.CyclomaticComplexity); - @class.Summary.MaxCyclomaticComplexity = Math.Max(@class.Summary.MaxCyclomaticComplexity, method.CyclomaticComplexity); - } + private static void ProcessMethodData(Method method, Class @class) + { + if (method.MethodPoint != null) + { + method.Visited = (method.MethodPoint.VisitCount > 0); + } - @class.Summary.NumClasses = (@class.Summary.NumMethods > 0) ? 1 : 0; - @class.Summary.VisitedClasses = (@class.Summary.VisitedMethods > 0) ? 1 : 0; + method.Summary.NumBranchPoints = method.BranchPoints == null ? 0 : method.BranchPoints.Count(); + method.Summary.VisitedBranchPoints = method.BranchPoints == null + ? 0 + : method.BranchPoints.Count(pt => pt.VisitCount != 0); + method.Summary.NumSequencePoints = method.SequencePoints == null ? 0 : method.SequencePoints.Count(); + method.Summary.VisitedSequencePoints = method.SequencePoints == null + ? 0 + : method.SequencePoints.Count(pt => pt.VisitCount != 0); - AddPoints(module.Summary, @class.Summary); - CalculateCoverage(@class.Summary); + if (method.Summary.NumSequencePoints > 0) + method.Summary.NumBranchPoints += 1; - if (module.Summary.MinCyclomaticComplexity == 0) - module.Summary.MinCyclomaticComplexity = @class.Summary.MinCyclomaticComplexity; + if (method.Summary.VisitedSequencePoints > 0) + method.Summary.VisitedBranchPoints += 1; - module.Summary.MinCyclomaticComplexity = Math.Min(module.Summary.MinCyclomaticComplexity, @class.Summary.MinCyclomaticComplexity); - module.Summary.MaxCyclomaticComplexity = Math.Max(module.Summary.MaxCyclomaticComplexity, @class.Summary.MaxCyclomaticComplexity); - } + if (method.FileRef != null) + { + method.Summary.NumMethods = 1; + method.Summary.VisitedMethods = (method.Visited) ? 1 : 0; + } + + AddPoints(@class.Summary, method.Summary); + CalculateCoverage(method.Summary); + + method.SequenceCoverage = method.Summary.SequenceCoverage; + method.BranchCoverage = method.Summary.BranchCoverage; + + CalculateNPathComplexity(method); + + CalculateCyclomaticComplexity(method, @class); + } + + private static void CalculateCyclomaticComplexity(Method method, Class @class) + { + method.Summary.MinCyclomaticComplexity = + method.Summary.MaxCyclomaticComplexity = Math.Max(1, method.CyclomaticComplexity); - AddPoints(CoverageSession.Summary, module.Summary); - CalculateCoverage(module.Summary); + if (@class.Summary.MinCyclomaticComplexity == 0) + @class.Summary.MinCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; - if (CoverageSession.Summary.MinCyclomaticComplexity == 0) - CoverageSession.Summary.MinCyclomaticComplexity = module.Summary.MinCyclomaticComplexity; + @class.Summary.MinCyclomaticComplexity = Math.Min(@class.Summary.MinCyclomaticComplexity, + method.CyclomaticComplexity); + @class.Summary.MaxCyclomaticComplexity = Math.Max(@class.Summary.MaxCyclomaticComplexity, + method.CyclomaticComplexity); + } - CoverageSession.Summary.MinCyclomaticComplexity = Math.Min(CoverageSession.Summary.MinCyclomaticComplexity, module.Summary.MinCyclomaticComplexity); - CoverageSession.Summary.MaxCyclomaticComplexity = Math.Max(CoverageSession.Summary.MaxCyclomaticComplexity, module.Summary.MaxCyclomaticComplexity); + private static void CalculateNPathComplexity(Method method) + { + method.NPathComplexity = 0; + var nPaths = new Dictionary(); + if (method.BranchPoints != null && method.BranchPoints.Length != 0) + { + foreach (var bp in method.BranchPoints.Where(b => b != null)) + { + if (nPaths.ContainsKey(bp.Offset)) + { + nPaths[bp.Offset] += 1; + } + else + { + nPaths.Add(bp.Offset, 1); + } + } + } + foreach (var branches in nPaths.Values) + { + if (method.NPathComplexity == 0) + { + method.NPathComplexity = branches; + } + else + { + method.NPathComplexity *= branches; + } } - CalculateCoverage(CoverageSession.Summary); } private static void MapFileReferences(IEnumerable points, IDictionary filesDictionary) @@ -499,7 +543,7 @@ public void SaveVisitData(byte[] data) var spid = BitConverter.ToUInt32(data, idx); if (spid < (uint)MSG_IdType.IT_MethodEnter) { - if (!InstrumentationPoint.AddVisitCount(spid, _trackedMethodId)) + if (!InstrumentationPoint.AddVisitCount(spid, _trackedMethodId, 1)) { _logger.ErrorFormat("Failed to add a visit to {0} with tracking method {1}. Max point count is {2}", spid, _trackedMethodId, InstrumentationPoint.Count); diff --git a/main/OpenCover.Framework/ProfilerRegistration.cs b/main/OpenCover.Framework/ProfilerRegistration.cs index 8c91ff07e..d076f9735 100644 --- a/main/OpenCover.Framework/ProfilerRegistration.cs +++ b/main/OpenCover.Framework/ProfilerRegistration.cs @@ -29,7 +29,7 @@ public class ExitApplicationWithoutReportingException : Exception /// Intentionally not unit tested - as this is calling regsvr32 which does what it does and does not need more testing from me /// [ExcludeFromCoverage("Intentionally not unit tested - as this is calling regsvr32 which does what it does and does not need more testing from me")] - public class ProfilerRegistration + public static class ProfilerRegistration { private const string UserRegistrationString = "/n /i:user"; diff --git a/main/OpenCover.Framework/Service/IProfilerCommunication.cs b/main/OpenCover.Framework/Service/IProfilerCommunication.cs index 2c17dab2a..eb9a760f3 100644 --- a/main/OpenCover.Framework/Service/IProfilerCommunication.cs +++ b/main/OpenCover.Framework/Service/IProfilerCommunication.cs @@ -3,27 +3,11 @@ // // This source code is released under the MIT License; see the accompanying license file. // -using System; -using System.Net.Security; + using OpenCover.Framework.Model; namespace OpenCover.Framework.Service { - //public class SequencePoint - //{ - // public UInt32 Ordinal { get; set; } - // public UInt32 UniqueId { get; set; } - // public int Offset { get; set; } - //} - - //public class BranchPoint - //{ - // public UInt32 Ordinal { get; set; } - // public UInt32 UniqueId { get; set; } - // public int Offset { get; set; } - // public int Path { get; set; } - //} - /// /// Defines the tye of operations the profiler will make /// diff --git a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs index 0c76f6bea..ef5533a43 100644 --- a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs +++ b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs @@ -33,7 +33,7 @@ public static MethodBody SafeGetMethodBody(this MethodDefinition methodDefinitio } catch (Exception) { - //Console.WriteLine("Exception whilst trying to get the body of method {0}", methodDefinition.FullName); + return null; } return null; } @@ -92,21 +92,15 @@ private static SymbolFolder FindSymbolsFolder(string fileName, string targetfold if (!string.IsNullOrEmpty(targetfolder) && Directory.Exists(targetfolder)) { var name = Path.GetFileName(fileName); - //Console.WriteLine(targetfolder); if (name != null) { - if (System.IO.File.Exists(Path.Combine(targetfolder, - Path.GetFileNameWithoutExtension(fileName) + ".pdb"))) - { - if (System.IO.File.Exists(Path.Combine(targetfolder, name))) + if (System.IO.File.Exists(Path.Combine(targetfolder, Path.GetFileNameWithoutExtension(fileName) + ".pdb")) && + System.IO.File.Exists(Path.Combine(targetfolder, name))) return new SymbolFolder(targetfolder, new PdbReaderProvider()); - } - if (System.IO.File.Exists(Path.Combine(targetfolder, fileName + ".mdb"))) - { - if (System.IO.File.Exists(Path.Combine(targetfolder, name))) + if (System.IO.File.Exists(Path.Combine(targetfolder, fileName + ".mdb")) && + System.IO.File.Exists(Path.Combine(targetfolder, name))) return new SymbolFolder(targetfolder, new MdbReaderProvider()); - } } } return null; @@ -155,12 +149,9 @@ public AssemblyDefinition SourceAssembly { Environment.CurrentDirectory = currentPath; } - if (_sourceAssembly == null) + if (_sourceAssembly == null && _logger.IsDebugEnabled) { - if (_logger.IsDebugEnabled) - { - _logger.DebugFormat("Cannot instrument {0} as no PDB/MDB could be loaded", ModulePath); - } + _logger.DebugFormat("Cannot instrument {0} as no PDB/MDB could be loaded", ModulePath); } } return _sourceAssembly; @@ -185,7 +176,9 @@ public Class[] GetInstrumentableTypes() IEnumerable typeDefinitions = SourceAssembly.MainModule.Types; var assemblyPath = ModuleName; - if (ModulePath.Contains (assemblyPath)) { assemblyPath = ModulePath; } + if (ModulePath.Contains(assemblyPath)) + assemblyPath = ModulePath; + GetInstrumentableTypes(typeDefinitions, classes, _filter, assemblyPath); return classes.ToArray(); } @@ -198,39 +191,47 @@ private static void GetInstrumentableTypes(IEnumerable typeDefin continue; if (typeDefinition.IsInterface && typeDefinition.IsAbstract) continue; - var @class = new Class { FullName = typeDefinition.FullName }; - if (!filter.InstrumentClass(assemblyPath, @class.FullName)) - { - @class.MarkAsSkipped(SkippedMethod.Filter); - } - else if (filter.ExcludeByAttribute(typeDefinition)) - { - @class.MarkAsSkipped(SkippedMethod.Attribute); - } - var list = new List(); - if (!@class.ShouldSerializeSkippedDueTo()) - { - var files = from methodDefinition in typeDefinition.Methods - where methodDefinition.SafeGetMethodBody() != null && methodDefinition.Body.Instructions != null - from instruction in methodDefinition.Body.Instructions - where instruction.SequencePoint != null - select instruction.SequencePoint.Document.Url; - - list.AddRange(files.Distinct()); - } + var @class = BuildClass(filter, assemblyPath, typeDefinition); // only instrument types that are not structs and have instrumentable points - if (!typeDefinition.IsValueType || list.Count > 0) - { - @class.Files = list.Distinct().Select(file => new File { FullPath = file }).ToArray(); + if (!typeDefinition.IsValueType || @class.Files.Maybe(f => f.Length) > 0) classes.Add(@class); - } + if (typeDefinition.HasNestedTypes) GetInstrumentableTypes(typeDefinition.NestedTypes, classes, filter, assemblyPath); } } + private static Class BuildClass(IFilter filter, string assemblyPath, TypeDefinition typeDefinition) + { + var @class = new Class {FullName = typeDefinition.FullName}; + if (!filter.InstrumentClass(assemblyPath, @class.FullName)) + { + @class.MarkAsSkipped(SkippedMethod.Filter); + } + else if (filter.ExcludeByAttribute(typeDefinition)) + { + @class.MarkAsSkipped(SkippedMethod.Attribute); + } + + var list = new List(); + if (!@class.ShouldSerializeSkippedDueTo()) + { + var files = from methodDefinition in typeDefinition.Methods + where methodDefinition.SafeGetMethodBody() != null && methodDefinition.Body.Instructions != null + from instruction in methodDefinition.Body.Instructions + where instruction.SequencePoint != null + select instruction.SequencePoint.Document.Url; + + list.AddRange(files.Distinct()); + } + + if (!typeDefinition.IsValueType || list.Count > 0) + @class.Files = list.Distinct().Select(file => new File {FullPath = file}).ToArray(); + return @class; + } + public Method[] GetMethodsForType(Class type, File[] files) { var methods = new List(); @@ -409,7 +410,7 @@ private void GetSequencePointsForToken(int token, List list) } } - private static Regex isMovenext = new Regex(@"\<[^\s>]+\>\w__\w(\w)?::MoveNext\(\)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); + private static readonly Regex IsMovenext = new Regex(@"\<[^\s>]+\>\w__\w(\w)?::MoveNext\(\)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); private void GetBranchPointsForToken(int token, List list) { var methodDefinition = GetMethodDefinition(token); @@ -419,11 +420,12 @@ private void GetBranchPointsForToken(int token, List list) { UInt32 ordinal = 0; var safeMethodBody = methodDefinition.SafeGetMethodBody(); - if (safeMethodBody == null) return; + if (safeMethodBody == null) + return; var instructions = safeMethodBody.Instructions; // if method is a generated MoveNext skip first branch (could be a switch or a branch) - var skipFirstBranch = isMovenext.IsMatch(methodDefinition.FullName); + var skipFirstBranch = IsMovenext.IsMatch(methodDefinition.FullName); foreach (var instruction in instructions.Where(instruction => instruction.OpCode.FlowControl == FlowControl.Cond_Branch)) { @@ -433,7 +435,8 @@ private void GetBranchPointsForToken(int token, List list) continue; } - if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition)) continue; + if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition)) + continue; var pathCounter = 0; diff --git a/main/OpenCover.Framework/Utility/IPerfCounters.cs b/main/OpenCover.Framework/Utility/IPerfCounters.cs index d0158b4a1..5eff8140d 100644 --- a/main/OpenCover.Framework/Utility/IPerfCounters.cs +++ b/main/OpenCover.Framework/Utility/IPerfCounters.cs @@ -13,7 +13,7 @@ public interface IPerfCounters /// /// Report on the size of the memory queue /// - int CurrentMemoryQueueSize { set; } + long CurrentMemoryQueueSize { get; set; } /// /// Increment the number of blocks received diff --git a/main/OpenCover.Framework/Utility/PerfCounters.cs b/main/OpenCover.Framework/Utility/PerfCounters.cs index a8feb4832..5c65768ea 100644 --- a/main/OpenCover.Framework/Utility/PerfCounters.cs +++ b/main/OpenCover.Framework/Utility/PerfCounters.cs @@ -14,7 +14,11 @@ public class PerfCounters : IPerfCounters /// /// get the current queue size /// - public int CurrentMemoryQueueSize { set { _memoryQueue.RawValue = value; } } + public long CurrentMemoryQueueSize + { + get { return _memoryQueue.RawValue; } + set { _memoryQueue.RawValue = value; } + } /// /// Increment the block size @@ -33,7 +37,6 @@ public PerfCounters() ResetCounters(); } - //private const string InstanceName = "OpenCover"; private const string CategoryName = "OpenCover"; private const string MemoryQueue = "MemoryQueue"; private const string QueueThroughput = "QueueThroughput"; @@ -77,13 +80,14 @@ public class NullPerfCounter : IPerfCounters /// A null performance counters implementation /// // ReSharper disable once UnusedAutoPropertyAccessor.Local - public int CurrentMemoryQueueSize { set; private get; } + public long CurrentMemoryQueueSize { set; get; } /// /// Increment the number of blocks received /// public void IncrementBlocksReceived() { + // null implementation } /// @@ -91,6 +95,7 @@ public void IncrementBlocksReceived() /// public void ResetCounters() { + // null implementation } } } \ No newline at end of file diff --git a/main/OpenCover.Integration.Test/ProfilerBaseFixture.cs b/main/OpenCover.Integration.Test/ProfilerBaseFixture.cs index 704fb0a5d..cf105d241 100644 --- a/main/OpenCover.Integration.Test/ProfilerBaseFixture.cs +++ b/main/OpenCover.Integration.Test/ProfilerBaseFixture.cs @@ -39,7 +39,7 @@ public abstract class ProfilerBaseFixture [SetUp] public void SetUp() { - _filter = new Filter(); + _filter = new Filter(false); _filter.AddFilter("-[mscorlib]*"); _filter.AddFilter("-[System]*"); _filter.AddFilter("-[System.*]*"); diff --git a/main/OpenCover.Support/UITesting/UITestingHelper.cs b/main/OpenCover.Support/UITesting/UITestingHelper.cs index ef94fbb9c..8968291f5 100644 --- a/main/OpenCover.Support/UITesting/UITestingHelper.cs +++ b/main/OpenCover.Support/UITesting/UITestingHelper.cs @@ -8,7 +8,7 @@ namespace OpenCover.Support.UITesting { // ReSharper disable once InconsistentNaming - public class UITestingHelper + public static class UITestingHelper { public static void PropagateRequiredEnvironmentVariables(object data) { diff --git a/main/OpenCover.Test/Framework/FilterTests.cs b/main/OpenCover.Test/Framework/FilterTests.cs index ccc9e0f50..919166ffe 100644 --- a/main/OpenCover.Test/Framework/FilterTests.cs +++ b/main/OpenCover.Test/Framework/FilterTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Mono.Cecil; using Mono.Collections.Generic; @@ -106,7 +105,7 @@ public void AddFilter_ThrowsException_WhenInvalid_AssemblyClassPair( [ValueSource("_invalidFilterExpressions")]string assemblyClassPair) { // arrange - var filter = new Filter(); + var filter = new Filter(false); // act/assert Assert.Catch(() => filter.AddFilter(assemblyClassPair), @@ -118,7 +117,7 @@ public void AddFilter_Adds_ValidAssemblyClassPair( [ValueSource("_filterExpressions")]FilterData assemblyClassPair) { // arrange - var filter = new Filter(); + var filter = new Filter(false); // act filter.AddFilter(assemblyClassPair.FilterExpression); @@ -204,7 +203,7 @@ public void UseAssembly_Tests( [ValueSource("_useAssemblyData")]UseAssemblyData data) { // arrange - var filter = new Filter(); + var filter = new Filter(false); data.Filters.ForEach(filter.AddFilter); // act @@ -342,7 +341,7 @@ public void InstrumentClass_Tests( [ValueSource("_instrumentClassData")]InstrumentClassData data) { // arrange - var filter = new Filter(); + var filter = new Filter(false); data.Filters.ForEach(filter.AddFilter); // act @@ -357,7 +356,7 @@ public void InstrumentClass_Tests( [Test] public void AddAttributeExclusionFilters_HandlesNull() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(null); @@ -367,7 +366,7 @@ public void AddAttributeExclusionFilters_HandlesNull() [Test] public void AddAttributeExclusionFilters_Handles_Null_Elements() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { null, "" }); @@ -377,7 +376,7 @@ public void AddAttributeExclusionFilters_Handles_Null_Elements() [Test] public void AddAttributeExclusionFilters_Escapes_Elements_And_Matches() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { ".*" }); @@ -387,7 +386,7 @@ public void AddAttributeExclusionFilters_Escapes_Elements_And_Matches() [Test] public void Entity_Is_Not_Excluded_If_No_Filters_Set() { - var filter = new Filter(); + var filter = new Filter(false); var entity = new Mock(); Assert.IsFalse(filter.ExcludeByAttribute(entity.Object)); @@ -396,7 +395,7 @@ public void Entity_Is_Not_Excluded_If_No_Filters_Set() [Test] public void AddFileExclusionFilters_HandlesNull() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddFileExclusionFilters(null); @@ -406,7 +405,7 @@ public void AddFileExclusionFilters_HandlesNull() [Test] public void AddFileExclusionFilters_Handles_Null_Elements() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddFileExclusionFilters(new[] { null, "" }); @@ -416,7 +415,7 @@ public void AddFileExclusionFilters_Handles_Null_Elements() [Test] public void AddFileExclusionFilters_Escapes_Elements_And_Matches() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddFileExclusionFilters(new[] { ".*" }); @@ -426,7 +425,7 @@ public void AddFileExclusionFilters_Escapes_Elements_And_Matches() [Test] public void AddTestFileFilters_HandlesNull() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddTestFileFilters(null); @@ -436,7 +435,7 @@ public void AddTestFileFilters_HandlesNull() [Test] public void AssemblyIsIncludedForTestMethodGatheringWhenFilterMatches() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddTestFileFilters(new[] { "A*" }); @@ -448,7 +447,7 @@ public void AssemblyIsIncludedForTestMethodGatheringWhenFilterMatches() [Test] public void AddTestFileFilters_Handles_Null_Elements() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddTestFileFilters(new[] { null, "" }); @@ -458,7 +457,7 @@ public void AddTestFileFilters_Handles_Null_Elements() [Test] public void AddTestFileFilters_Escapes_Elements_And_Matches() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddTestFileFilters(new[] { ".*" }); @@ -505,7 +504,7 @@ public void AddTestFileFilters_DoesNotWrap_ForRegexFilters() [Test] public void File_Is_Not_Excluded_If_No_Filters_Set() { - var filter = new Filter(); + var filter = new Filter(false); Assert.IsFalse(filter.ExcludeByFile("xyz.cs")); } @@ -513,7 +512,7 @@ public void File_Is_Not_Excluded_If_No_Filters_Set() [Test] public void File_Is_Not_Excluded_If_No_File_Not_Supplied() { - var filter = new Filter(); + var filter = new Filter(false); Assert.IsFalse(filter.ExcludeByFile("")); } @@ -521,7 +520,7 @@ public void File_Is_Not_Excluded_If_No_File_Not_Supplied() [Test] public void File_Is_Not_Excluded_If_Does_Not_Match_Filter() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddFileExclusionFilters(new[] { "XXX.*" }); Assert.IsFalse(filter.ExcludeByFile("YYY.cs")); @@ -530,7 +529,7 @@ public void File_Is_Not_Excluded_If_Does_Not_Match_Filter() [Test] public void File_Is_Excluded_If_Matches_Filter() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddFileExclusionFilters(new[] { "XXX.*" }); Assert.IsTrue(filter.ExcludeByFile("XXX.cs")); @@ -543,7 +542,7 @@ public void Can_Identify_Excluded_Methods() var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.Concrete).FullName); - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { "*ExcludeMethodAttribute" }); foreach (var methodDefinition in type.Methods) @@ -561,7 +560,7 @@ public void Can_Identify_Excluded_Properties() var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.Concrete).FullName); - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { "*ExcludeMethodAttribute" }); foreach (var propertyDefinition in type.Properties) @@ -577,7 +576,7 @@ public void Can_Identify_Excluded_Anonymous_Issue99() var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.Anonymous).FullName); - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { "*ExcludeMethodAttribute" }); foreach (var methodDefinition in type.Methods.Where(x => x.Name.Contains("EXCLUDE"))) @@ -594,7 +593,7 @@ public void Can_Identify_Included_Anonymous_Issue99() var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.Anonymous).FullName); - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { "*ExcludeMethodAttribute" }); foreach (var methodDefinition in type.Methods.Where(x => x.Name.Contains("INCLUDE"))) @@ -607,7 +606,7 @@ public void Can_Identify_Included_Anonymous_Issue99() [Test] public void Handles_Issue117() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { "*ExcludeMethodAttribute" }); var mockDefinition = new Mock(); @@ -627,7 +626,7 @@ public void Can_Identify_Excluded_Assemblies() var sourceAssembly = AssemblyDefinition.ReadAssembly(typeof(Samples.Concrete).Assembly.Location); // act - var filter = new Filter(); + var filter = new Filter(false); Assert.False(filter.ExcludeByAttribute(sourceAssembly)); // assert @@ -670,7 +669,7 @@ public void Can_Identify_Excluded_Types(string typeName) var sourceAssembly = AssemblyDefinition.ReadAssembly(typeof(Samples.Concrete).Assembly.Location); // act - var filter = new Filter(); + var filter = new Filter(false); var allTypes = AllTypes(sourceAssembly.MainModule); var typeDefinition = allTypes.First(x => x.Name == typeName); @@ -698,7 +697,7 @@ public void CanIdentify_AutoImplementedProperties() var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.DeclaredMethodClass).FullName); // act/assert - var filter = new Filter(); + var filter = new Filter(false); var wasTested = false; foreach (var methodDefinition in type.Methods .Where(x => x.IsGetter || x.IsSetter).Where(x => x.Name.EndsWith("AutoProperty"))) diff --git a/main/OpenCover.Test/Framework/Symbols/CecilSymbolManagerTests.cs b/main/OpenCover.Test/Framework/Symbols/CecilSymbolManagerTests.cs index 1f05e2d39..77fb938d3 100644 --- a/main/OpenCover.Test/Framework/Symbols/CecilSymbolManagerTests.cs +++ b/main/OpenCover.Test/Framework/Symbols/CecilSymbolManagerTests.cs @@ -661,7 +661,7 @@ public void Can_Exclude_A_Method_By_An_FileFilter() public void Can_Exclude_AutoImplmentedProperties() { // arrange - var filter = new Filter(); + var filter = new Filter(false); _mockFilter .Setup(x => x.InstrumentClass(It.IsAny(), It.IsAny())) .Returns(true); diff --git a/main/OpenCover.Test/Samples/SimpleXUnit.cs b/main/OpenCover.Test/Samples/SimpleXUnit.cs index 14259e2d2..d1d7d6fdf 100644 --- a/main/OpenCover.Test/Samples/SimpleXUnit.cs +++ b/main/OpenCover.Test/Samples/SimpleXUnit.cs @@ -13,7 +13,7 @@ public class SimpleXUnit [Fact] public void AddAttributeExclusionFilters_Handles_Null_Elements() { - var filter = new Filter(); + var filter = new Filter(false); filter.AddAttributeExclusionFilters(new[] { null, "" }); From aa61da30c3edcb2caa3e97ca5fa7f936a598f4e3 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 21:14:48 +1100 Subject: [PATCH 23/30] some more sonar issues --- main/OpenCover.Console/Program.cs | 23 ++++++------------- .../Persistance/BasePersistance.cs | 5 ++-- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs index 6d4644af9..674439e5f 100644 --- a/main/OpenCover.Console/Program.cs +++ b/main/OpenCover.Console/Program.cs @@ -45,8 +45,6 @@ static int Main(string[] args) try { - //throw new NullReferenceException(); - CommandLineParser parser; if (!ParseCommandLine(args, out parser)) return parser.ReturnCodeOffset + 1; @@ -409,13 +407,9 @@ from @class in module.Classes.Where(c => !c.ShouldSerializeSkippedDueTo()) if (@class.Methods == null) continue; - if ((@class.Methods.Any(x => !x.ShouldSerializeSkippedDueTo() && x.SequencePoints.Any(y => y.VisitCount > 0)))) - { - } - else if ((@class.Methods.Any(x => x.FileRef != null))) - { - unvisitedClasses.Add(@class.FullName); - } + if (!(@class.Methods.Any(x => !x.ShouldSerializeSkippedDueTo() && x.SequencePoints.Any(y => y.VisitCount > 0)))) + if ((@class.Methods.Any(x => x.FileRef != null))) + unvisitedClasses.Add(@class.FullName); if (@class.Methods.Any(x => x.Visited)) { @@ -429,13 +423,9 @@ from @class in module.Classes.Where(c => !c.ShouldSerializeSkippedDueTo()) foreach (var method in @class.Methods.Where(x=> !x.ShouldSerializeSkippedDueTo())) { - if ((method.SequencePoints.Any(x => x.VisitCount > 0))) - { - } - else if (method.FileRef != null) - { - unvisitedMethods.Add(string.Format("{0}", method.FullName)); - } + if (!(method.SequencePoints.Any(x => x.VisitCount > 0))) + if (method.FileRef != null) + unvisitedMethods.Add(string.Format("{0}", method.FullName)); altTotalMethods += 1; if (method.Visited) @@ -591,6 +581,7 @@ private static bool ParseCommandLine(string[] args, out CommandLineParser parser using (var service = new ServiceController(parser.Target)) { var name = service.DisplayName; + System.Console.WriteLine("Service '{0}' found", name); } } catch (Exception) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 3c32ff3ff..440fc35b0 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -364,8 +364,8 @@ private static void ProcessMethodData(Method method, Class @class) private static void CalculateCyclomaticComplexity(Method method, Class @class) { - method.Summary.MinCyclomaticComplexity = - method.Summary.MaxCyclomaticComplexity = Math.Max(1, method.CyclomaticComplexity); + method.Summary.MinCyclomaticComplexity = Math.Max(1, method.CyclomaticComplexity); + method.Summary.MaxCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; if (@class.Summary.MinCyclomaticComplexity == 0) @class.Summary.MinCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; @@ -497,7 +497,6 @@ public bool GetBranchPointsForFunction(string modulePath, int functionToken, out private Method GetMethod(string modulePath, int functionToken, out Class @class) { @class = null; - //c = null; lock (Protection) { var module = CoverageSession.Modules From cbb013aa5f115c865e01268187fca7c31c837806 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 21:44:40 +1100 Subject: [PATCH 24/30] added some test scenarios for issue #512 --- main/OpenCover.Test/Framework/FilterTests.cs | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/main/OpenCover.Test/Framework/FilterTests.cs b/main/OpenCover.Test/Framework/FilterTests.cs index 919166ffe..764fa0527 100644 --- a/main/OpenCover.Test/Framework/FilterTests.cs +++ b/main/OpenCover.Test/Framework/FilterTests.cs @@ -717,6 +717,28 @@ public void CanIdentify_AutoImplementedProperties() Assert.IsTrue(wasTested); } + #region scenarios for issue reported by user #512 + [TestCase(@"+[*]* -[*.Tests]*", @"Target", true)] + [TestCase(@"+[*]* -[*.Tests]*", @"Target.Tests", false)] + [TestCase(@"+[*]* -[*.Tests]* +[*.Tests]*", @"Target.Tests", false)] + [TestCase(@"+[*]* -[*.Tests]*", @"Target.Tests", false)] + [TestCase(@"+[*.Tests]*", @"Target.Tests", true)] + #endregion + public void CanHandle_AssemblyFilters_reported(string filterArg, string assembly, bool canUse) + { + // arrange + var filter = new Filter(false); + foreach (var f in filterArg.Split(' ')) + { + filter.AddFilter(f); + } + + // act + + // assert + Assert.AreEqual(canUse, filter.UseAssembly("nunit-agent.exe", assembly)); + } + [Test] [TestCase("A1.B1", false)] [TestCase("A1.B2", true)] @@ -876,6 +898,7 @@ public void Can_BuildFilter_From_CommandLine(string[] commandLine, bool matchAss // issue found by user #329 [TestCase(@"+[Open*]* -[OpenCover.T*]* -[*nunit*]*", @"C:\Release\nunit-console.exe.exe", true, true)] + #endregion #region Cover last branches with invalid path chars (Path.GetInvalidPathChars) From 091194f2702bff7d13a90b8673b44b2c1124a49c Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 25 Jan 2016 21:56:30 +1100 Subject: [PATCH 25/30] more minor sonar issues --- main/OpenCover.Framework/Filter.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index b6ec194eb..b1534d5cf 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -67,7 +67,9 @@ public bool UseAssembly(string processPath, string assemblyPath) return true; var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (assemblyNameAdd) + matchingInclusionFilters.AddRange(InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); + return matchingInclusionFilters.Any(); } @@ -130,7 +132,9 @@ public bool InstrumentClass(string processPath, string assemblyPath, string clas } var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath); - if (assemblyNameAdd) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); } + if (assemblyNameAdd) + matchingInclusionFilters.AddRange(InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); + return matchingInclusionFilters.Any(inclusionFilter => inclusionFilter.IsMatchingClassName(className)); } @@ -378,10 +382,10 @@ public bool IsAutoImplementedProperty(MethodDefinition method) public bool InstrumentProcess(string processPath) { if (string.IsNullOrEmpty(processPath)) - { return false; - } - if (!ExclusionFilters.Any() && !InclusionFilters.Any()) return true; + + if (!ExclusionFilters.Any() && !InclusionFilters.Any()) + return true; var processName = string.Empty; var processNameAdd = false; From 8ead96b69efd49134081ea23b1c559806cfe547f Mon Sep 17 00:00:00 2001 From: ddur Date: Mon, 25 Jan 2016 21:30:45 +0100 Subject: [PATCH 26/30] SonarQube: Refactor --- main/OpenCover.Framework/Model/Method.cs | 24 +- .../Model/SequencePoint.cs | 10 +- .../Persistance/BasePersistance.cs | 381 ++++++------------ .../Utility/CodeCoverageStringTextSource.cs | 17 +- .../Utility/SourceRepository.cs | 18 - .../Framework/Utility/SourceRepositoryTest.cs | 4 - 6 files changed, 177 insertions(+), 277 deletions(-) diff --git a/main/OpenCover.Framework/Model/Method.cs b/main/OpenCover.Framework/Model/Method.cs index 9dc76a762..bcfa46e07 100644 --- a/main/OpenCover.Framework/Model/Method.cs +++ b/main/OpenCover.Framework/Model/Method.cs @@ -31,15 +31,35 @@ public class Method : SummarySkippedEntity /// public FileRef FileRef { get; set; } + internal UInt32 FileRefUniqueId { + get { return FileRef == null? 0 : FileRef.UniqueId; } + } + /// /// A list of sequence points that have been produced for this method /// - public SequencePoint[] SequencePoints { get; set; } + public SequencePoint[] SequencePoints { + get { + return sequencePoints; + } + set { + sequencePoints = value ?? new SequencePoint[0]; + } + } + private SequencePoint[] sequencePoints = new SequencePoint[0]; /// /// A list of branch points that have been identified for this method /// - public BranchPoint[] BranchPoints { get; set; } + public BranchPoint[] BranchPoints { + get { + return branchPoints; + } + set { + branchPoints = value ?? new BranchPoint[0]; + } + } + private BranchPoint[] branchPoints = new BranchPoint[0]; /// /// A method point to identify the entry of a method diff --git a/main/OpenCover.Framework/Model/SequencePoint.cs b/main/OpenCover.Framework/Model/SequencePoint.cs index 1f1a62221..762d1ded5 100644 --- a/main/OpenCover.Framework/Model/SequencePoint.cs +++ b/main/OpenCover.Framework/Model/SequencePoint.cs @@ -66,7 +66,15 @@ public class SequencePoint : InstrumentationPoint, IDocumentReference [XmlAttribute("url")] public string Document { get; set; } - internal List BranchPoints { get; set; } + internal List BranchPoints { + get{ + return branchPoints; + } + set{ + branchPoints = value ?? new List(); + } + } + private List branchPoints = new List(); /// /// Property diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 808fbb098..9078ca6b2 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -245,7 +245,7 @@ private void RemoveUnreferencedFiles() { module.Files = (from file in module.Files ?? new File[0] from @class in module.Classes ?? new Class[0] - where (@class.Methods ?? new Method[0]).Where(x=>x.FileRef != null).Any(x => x.FileRef.UniqueId == file.UniqueId) + where (@class.Methods ?? new Method[0]).Where(x=>x.FileRef != null).Any(x => x.FileRefUniqueId == file.UniqueId) select file).Distinct().ToArray(); } } @@ -559,11 +559,6 @@ static void TransformSequences_Initialize (IEnumerable methods) { foreach (var method in methods) { #region Cleanup - // remove nulls - if (method.SequencePoints == null) - method.SequencePoints = new SequencePoint[0]; - if (method.BranchPoints == null) - method.BranchPoints = new BranchPoint[0]; // No sequences in method, but branches present? => remove branches if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { method.BranchPoints = new BranchPoint[0]; @@ -627,39 +622,35 @@ private static void TransformSequences_JoinWithBranches (IEnumerable met } } - // Compiled for speed, treat as .Singleline for multiline SequencePoint, do not waste time to capture Groups (speed) - private static readonly RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; - // "Contract" and "." and "Requires/Ensures" can be separated by spaces and newlines (valid c# syntax)! - private static readonly Regex contractRegex = new Regex(@"^Contract\s*\.\s*(Requi|Ensu)res", regexOptions); - private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) { - foreach (var method in methods) { + foreach (var method in methods + .Where (m => m.FileRefUniqueId != 0 + && m.SequencePoints.Length != 0)) { - if (method == null - || method.FileRef == null - || method.FileRef.UniqueId == 0 - || method.SequencePoints == null - || method.SequencePoints.Length == 0 - ) { - continue; - } - // Get method source if availabile - var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); - - // Do we have C# source? - if (source != null - && source.FileFound - && source.FileType == FileType.CSharp ) { + var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRefUniqueId); + if (source != null) { - if (source.FileTime != DateTime.MinValue - && moduleTime != DateTime.MinValue - && source.FileTime > moduleTime) { + if (source.IsChanged (moduleTime)) { ("Source file is modified: " + source.FilePath).InformUser(); return; } + if (!TransformSequences_RemoveCompilerGeneratedBranches (method, source)) { + return; // empty sequence found -> source.IsChanged (failed access to file-times) + } + } + } + } + + private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source) + { + // Do we have C# source? + if (source.FileType == FileType.CSharp) { + + if (source.FileFound) { + #region Use line/col-sorted SequencePoint's offset and content to Remove Compiler Generated Branches // initialize offset with unreachable values @@ -669,95 +660,102 @@ private static void TransformSequences_RemoveCompilerGeneratedBranches (IEnumera if (!method.IsGenerated) { // order SequencePoints by source order (Line/Column) - var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp => sp.StartLine).ThenBy(sp => sp.StartColumn).Where(sp => sp.FileId == method.FileRef.UniqueId).ToArray(); + var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp => sp.StartLine).ThenBy(sp => sp.StartColumn).Where(sp => sp.FileId == method.FileRefUniqueId).ToArray(); // find getter/setter/static-method "{" offset - if (sourceLineOrderedSps.Length > 0 && sourceRepository.IsLeftCurlyBraceSequencePoint(sourceLineOrderedSps[0])) { + if (sourceLineOrderedSps.Length > 0 && source.GetText(sourceLineOrderedSps[0]) == "{") { startOffset = sourceLineOrderedSps[0].Offset; // find method "}" offset - if (sourceLineOrderedSps.Length > 1 && sourceRepository.IsRightCurlyBraceSequencePoint(sourceLineOrderedSps.Last())) { + if (sourceLineOrderedSps.Length > 1 && source.GetText(sourceLineOrderedSps.Last()) == "}") { finalOffset = sourceLineOrderedSps.Last().Offset; } } // find method "{" offset - else if (sourceLineOrderedSps.Length > 1 && sourceRepository.IsLeftCurlyBraceSequencePoint(sourceLineOrderedSps[1])) { + else if (sourceLineOrderedSps.Length > 1 && source.GetText(sourceLineOrderedSps[1]) == "{") { startOffset = sourceLineOrderedSps[1].Offset; // find method "}" offset - if (sourceLineOrderedSps.Length > 2 && sourceRepository.IsRightCurlyBraceSequencePoint(sourceLineOrderedSps.Last())) { - finalOffset = sourceLineOrderedSps.Last().Offset; - } - } else { // "{" not found, try to find "}" offset - if (sourceLineOrderedSps.Length > 1 && sourceRepository.IsRightCurlyBraceSequencePoint(sourceLineOrderedSps.Last())) { + if (sourceLineOrderedSps.Length > 2 && source.GetText(sourceLineOrderedSps.Last()) == "}") { finalOffset = sourceLineOrderedSps.Last().Offset; } + // "{" not found, try to find "}" offset + } else if (sourceLineOrderedSps.Length > 1 && source.GetText(sourceLineOrderedSps.Last()) == "}") { + finalOffset = sourceLineOrderedSps.Last().Offset; } } - // Method offsets found or not found, now check foreach sequence point - foreach (var sp in method.SequencePoints) { - if (sp != null - && sp.FileId == method.FileRef.UniqueId - && sp.BranchPoints != null - && sp.BranchPoints.Count != 0) { - } else { - continue; - } - - if (sp.Offset <= startOffset || sp.Offset >= finalOffset) { - // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset - // this will exclude "{" and "}" compiler generated branches and majority of ccrewrite Code-Contract's - sp.BranchPoints = new List(); - } else { // branches not removed - // check for other options by reading SequencePoint source - var text = sourceRepository.GetSequencePointText(sp); // text is never null - if (text == string.Empty) { - ("Empty sequence-point at line: " + sp.StartLine + " column: " + sp.StartColumn).InformUser(); - ("Source file: " + source.FilePath).InformUser(); - return; - } - // Contract.Requires/Ensures is occasionally left inside method offset - // Quick check for minimum length and "C" before using Regex - if (text.Length > 18 && text[0] == 'C') { - // Use Regex here! "Contract" and "." and "Requires/Ensures" - // can be separated by spaces and newlines - if (contractRegex.IsMatch(text)) { - sp.BranchPoints = new List(); - } - // "in" keyword? - } else if (text == "in") { - // Remove generated ::MoveNext branches within "in" keyword - // Not always removed in CecilSymbolManager (enumerated KeyValuePair) - sp.BranchPoints = new List(); - } - } + if (!TransformSequences_RemoveCompilerGeneratedBranches (method, source, startOffset, finalOffset)) { + return false; // return error/failure to caller } #endregion - } - else { + } else { + // Do as much possible without source // This will remove generated branches within "{", "}" and "in" (single-line SequencePoints) // but cannot remove Code Contract ccrewite generated branches foreach (var sp in method.SequencePoints) { - if (sp != null - && sp.BranchPoints != null - && sp.BranchPoints.Count != 0 + if (sp.BranchPoints.Count != 0 && sp.StartLine == sp.EndLine - && sp.EndColumn - sp.StartColumn <= 2 - ) { + && sp.EndColumn - sp.StartColumn <= 2) { + // Zero, one or two character sequence point should not contain branches // Never found 0 character sequencePoint // Never found 1 character sequencePoint except "{" and "}" // Never found 2 character sequencePoint except "in" keyword // Afaik, c# cannot express branch condition in one or two characters of source code - // x|y if(x) while(x) switch(x){...} case: x?. x?? x==y x?y:z; for(...) foreach(...) x is y + // "x|y" "if(x)" "while(x)" "switch(x){...}" "case:" "x?." "x??" "x==y" "x?y:z;" "for(...)" "foreach(...)" "x is y" // "do" keyword does not generate SequencePoint sp.BranchPoints = new List(); } } } } + return true; + } + + // Compiled for speed, treat as .Singleline for multiline SequencePoint, do not waste time to capture Groups (speed) + private static readonly RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; + // "Contract" and "." and "Requires/Ensures" can be separated by spaces and newlines (valid c# syntax)! + private static readonly Regex contractRegex = new Regex(@"^Contract\s*\.\s*(Requi|Ensu)res", regexOptions); + + private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source, long startOffset, long finalOffset) { + + // Method offsets found or not found, now check foreach sequence point + foreach (var sp in method.SequencePoints + .Where (sp => sp.FileId == method.FileRefUniqueId + && sp.BranchPoints.Count != 0)) { + + if (sp.Offset <= startOffset || sp.Offset >= finalOffset) { + // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset + // this will exclude "{" and "}" compiler generated branches and majority of ccrewrite Code-Contract's + sp.BranchPoints = new List(); + + } else { // branches not removed + // check for other options by reading SequencePoint source + var text = source.GetText(sp); // text is never null + if (text == string.Empty) { + ("Empty sequence-point at line: " + sp.StartLine + " column: " + sp.StartColumn).InformUser(); + ("Source file: " + source.FilePath).InformUser(); + return false; // signal error to caller's caller loop (break) + } + // Contract.Requires/Ensures is occasionally left inside method offset + // Quick check for minimum length and "C" before using Regex + if (text.Length > 18 && text[0] == 'C') { + // Use Regex here! "Contract" and "." and "Requires/Ensures" + // can be separated by spaces and newlines + if (contractRegex.IsMatch(text)) { + sp.BranchPoints = new List(); + } + // "in" keyword? + } else if (text == "in") { + // Remove generated ::MoveNext branches within "in" keyword + // Not always removed in CecilSymbolManager (enumerated KeyValuePair) + sp.BranchPoints = new List(); + } + } + } + return true; } /// @@ -776,7 +774,7 @@ private static void TransformSequences_ReduceBranches (IEnumerable metho var branchExits = new Dictionary(); foreach (var sp in method.SequencePoints) { // SequencePoint has branches attached? - if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) { + if (sp.BranchPoints.Count != 0) { // Merge sp.BranchPoints using EndOffset as branchExits key branchExits.Clear(); foreach (var branchPoint in sp.BranchPoints) { @@ -814,14 +812,9 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable { // From Methods with Source and visited SequencePoints var sequencePointsQuery = methods - .Where(m => m != null - && m.FileRef != null - && m.FileRef.UniqueId != 0 - && m.SequencePoints != null - && m.SequencePoints.Length != 0 - ) + .Where (m => m.FileRefUniqueId != 0 && m.SequencePoints.Length != 0) .SelectMany (m => m.SequencePoints) - .Where(sp => sp != null && sp.FileId != 0 && sp.VisitCount != 0); + .Where (sp => sp.FileId != 0 && sp.VisitCount != 0); var sequencePointsSet = new HashSet(new SequencePointComparer()); var toRemoveMethodSequencePoint = new List>(); @@ -833,71 +826,30 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable } } - // select false-positive-unvisited - foreach (var method in methods) { - if (method != null - && method.FileRef != null - && method.FileRef.UniqueId != 0 - && method.SequencePoints != null - && method.SequencePoints.Length != 0 - && method.IsGenerated) { - } else { - continue; - } + // Check generated methods + foreach (var method in methods + .Where (m => m.FileRefUniqueId != 0 + && m.SequencePoints.Length != 0 + && m.IsGenerated)) { // Select duplicate and false-positive unvisited sequence points // (Sequence point duplicated by generated method and left unvisited) - foreach (var sp in method.SequencePoints) { - if (sp != null - && sp.FileId == method.FileRef.UniqueId - && sp.VisitCount == 0) { // unvisited only - } else { - continue; - } + foreach (var sp in method.SequencePoints + .Where (sp => sp.FileId == method.FileRefUniqueId + && sp.VisitCount == 0) ) { + if (sequencePointsSet.Contains(sp)) { // Unvisited duplicate found, add to remove list toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); } } - - // Select false unvisited right-curly-braces at generated "MoveNext" method - // (Curly braces moved to generated "MoveNext" method and left unvisited) - // Source is required here to identify curly braces - if (method.CallName == "MoveNext") { - - // Get method source if availabile - var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRef.UniqueId); - - // Do we have C# source? - if (source != null - && source.FileFound - && source.FileType == FileType.CSharp - && source.FileTime <= moduleTime - ) { - - int countDown = 2; // remove up to two last right-curly-braces - foreach (var sp in method.SequencePoints.Reverse()) { - if (sp != null - && sp.FileId != 0 - && sp.StartLine == sp.EndLine - && sp.StartColumn + 1 == sp.EndColumn - && sp.VisitCount == 0 // unvisited only - ) { - } else { - continue; - } - if (countDown > 0) { - if (sourceRepository.IsRightCurlyBraceSequencePoint(sp)) { - toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); - countDown -= 1; - } - } - else { - break; - } - } - } + + // Get method source if availabile + var source = sourceRepository.GetCodeCoverageStringTextSource(method.FileRefUniqueId); + if (source != null && !source.IsChanged(moduleTime)) { + TransformSequences_RemoveFalsePositiveUnvisited (method, source, toRemoveMethodSequencePoint); } + } // Remove selected SequencePoints @@ -908,107 +860,40 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable } tuple.Item1.SequencePoints = cleanSequencePoints.ToArray(); } + } - #region ToDo? - /* Problems: - * Compiler can move SequencePoint into compiler generated method - * Solution? - * Identify compiler generated methods - * Match each with user method - * Move SequencePoints & branches into user method - */ - #endregion - - #region Examples - /* Duplicate SequencePoint Example - Generated Method * - * - * 100663434 - <_SetItems>b__b * System.Boolean DD.Collections.BitSetArray::<_SetItems>b__b(System.Int32) - * - * - Duplicate SP! * - * - * - * - * - * - Generated Method * - * - * 100663435 - <_SetItems>b__b_0* System.Boolean DD.Collections.BitSetArray::BitSetArray_<_SetItems>b__b_0(System.Int32) - * - * - Duplicate SP! * - * - * - * - * - * - User Method * - * - * 100663375 - * System.Void DD.Collections.BitSetArray::_SetItems(System.Collections.Generic.IEnumerable`1<System.Int32>) - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ - #endregion + private static void TransformSequences_RemoveFalsePositiveUnvisited (Method method, CodeCoverageStringTextSource source, List> toRemoveMethodSequencePoint) + { + // Select false unvisited right-curly-braces at generated "MoveNext" method + // (Curly braces moved to generated "MoveNext" method and left unvisited) + // Source is required here to identify curly braces + if (method.CallName == "MoveNext") { + + // Do we have C# source? + if (source.FileFound && source.FileType == FileType.CSharp) { + + int countDown = 2; // remove up to two last right-curly-braces + foreach (var sp in method.SequencePoints.Reverse()) { + if (sp.FileId == method.FileRefUniqueId + && sp.IsSingleCharSequencePoint + && sp.VisitCount == 0 // unvisited only + ) { + } else { + continue; + } + if (countDown > 0) { + if (source.GetText(sp) == "}") { + toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); + countDown -= 1; + } + } + else { + break; + } + } + } + } } - + } } diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index c77749630..dcdbb74d3 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -51,8 +51,8 @@ public class CodeCoverageStringTextSource /// /// Last write DateTime /// - public DateTime FileTime { get { return timeStamp; } } - private readonly DateTime timeStamp = DateTime.MinValue; + public DateTime FileTime { get { return fileTime; } } + private readonly DateTime fileTime = DateTime.MinValue; private readonly string textSource; @@ -79,7 +79,7 @@ public CodeCoverageStringTextSource(string source, string filePath = "") } if (this.fileFound) { try { - timeStamp = System.IO.File.GetLastWriteTime (this.filePath); + fileTime = System.IO.File.GetLastWriteTime (this.filePath); } catch (Exception e) { e.InformUser(); } @@ -250,7 +250,16 @@ public string GetLine ( int LineNo ) { return retString; } - + + /// + /// True if referenceTime != 0 and FileTime > referenceTime + /// + /// + /// + public bool IsChanged (DateTime referenceTime) { + return referenceTime != DateTime.MinValue && fileTime > referenceTime; + } + /// /// Get line-parsed source from file name /// diff --git a/main/OpenCover.Framework/Utility/SourceRepository.cs b/main/OpenCover.Framework/Utility/SourceRepository.cs index e730ebd2b..649c238fa 100644 --- a/main/OpenCover.Framework/Utility/SourceRepository.cs +++ b/main/OpenCover.Framework/Utility/SourceRepository.cs @@ -53,24 +53,6 @@ public string GetSequencePointText (SequencePoint sp) { } return ""; } - /// - /// True if SequencePoint source-string == "{" - /// ATTN: Do not use within .Where (condition) - /// - /// - /// - public bool IsLeftCurlyBraceSequencePoint (SequencePoint sp) { - return sp.IsSingleCharSequencePoint && this.GetSequencePointText(sp) == "{"; - } - /// - /// True if SequencePoint source-string == "}" - /// ATTN: Do not use within .Where (condition) - /// - /// - /// - public bool IsRightCurlyBraceSequencePoint (SequencePoint sp) { - return sp.IsSingleCharSequencePoint && this.GetSequencePointText(sp) == "}"; - } #region IDictionary implementation diff --git a/main/OpenCover.Test/Framework/Utility/SourceRepositoryTest.cs b/main/OpenCover.Test/Framework/Utility/SourceRepositoryTest.cs index 088eed646..c0f15358e 100644 --- a/main/OpenCover.Test/Framework/Utility/SourceRepositoryTest.cs +++ b/main/OpenCover.Test/Framework/Utility/SourceRepositoryTest.cs @@ -189,10 +189,6 @@ public void CreateGetSourceAndSequencePoints() Assert.True (sRepo.GetSequencePointText(spLeft) == "{"); Assert.True (sRepo.GetSequencePointText(spRight) == "}"); - Assert.True (sRepo.IsLeftCurlyBraceSequencePoint(spLeft)); - Assert.True (sRepo.IsRightCurlyBraceSequencePoint(spRight)); - Assert.False (sRepo.IsLeftCurlyBraceSequencePoint(spRight)); - Assert.False (sRepo.IsRightCurlyBraceSequencePoint(spLeft)); } } } From 0d1bb17bb102d2bac0151d77143a653cb56527dc Mon Sep 17 00:00:00 2001 From: ddur Date: Mon, 25 Jan 2016 22:20:46 +0100 Subject: [PATCH 27/30] Reorder definitions by call order --- .../Persistance/BasePersistance.cs | 183 ++++++++---------- 1 file changed, 84 insertions(+), 99 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index abdc7532a..4c7dfe498 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -611,47 +611,17 @@ private void TransformSequences() { static void TransformSequences_Initialize (IEnumerable methods) { foreach (var method in methods) { - #region Cleanup // No sequences in method, but branches present? => remove branches if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { method.BranchPoints = new BranchPoint[0]; } - #endregion - } - } - - private static void TransformSequences_AddSources (IList files, IEnumerable methods, IDictionary sourceRepository) - { - if (files == null || !files.Any()) - return; - - // Dictionary with stored source file names per module - var filesDictionary = new Dictionary(); - - foreach (var file in files. - Where (file => !String.IsNullOrWhiteSpace(file.FullPath) - && !filesDictionary.ContainsKey(file.FullPath))) - { - var source = CodeCoverageStringTextSource.GetSource(file.FullPath); // never reurns null - if (source.FileType == FileType.CSharp) - sourceRepository.Add (file.UniqueId, source); - filesDictionary.Add(file.FullPath, file.UniqueId); - } - - foreach (var method in methods) { - #region Add file references - if (method.SequencePoints.Length != 0) - MapFileReferences(method.SequencePoints, filesDictionary); - if (method.BranchPoints.Length != 0) - MapFileReferences(method.BranchPoints, filesDictionary); - #endregion } } private static void TransformSequences_JoinWithBranches (IEnumerable methods) { foreach (var method in methods) { - #region Join BranchPoints children to SequencePoint parent + if (method.SequencePoints.Length != 0 && method.BranchPoints.Length != 0) { // Quick match branches to sequence using SP&BP sort order by IL offset // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset @@ -673,7 +643,32 @@ private static void TransformSequences_JoinWithBranches (IEnumerable met } } } - #endregion + } + } + + private static void TransformSequences_AddSources (IEnumerable files, IEnumerable methods, IDictionary sourceRepository) + { + if (files == null || !files.Any()) + return; + + // Dictionary with stored source file names per module + var filesDictionary = new Dictionary(); + + foreach (var file in files. + Where (file => !String.IsNullOrWhiteSpace(file.FullPath) + && !filesDictionary.ContainsKey(file.FullPath))) + { + var source = CodeCoverageStringTextSource.GetSource(file.FullPath); // never reurns null + if (source.FileType == FileType.CSharp) + sourceRepository.Add (file.UniqueId, source); + filesDictionary.Add(file.FullPath, file.UniqueId); + } + + foreach (var method in methods) { + if (method.SequencePoints.Length != 0) + MapFileReferences(method.SequencePoints, filesDictionary); + if (method.BranchPoints.Length != 0) + MapFileReferences(method.BranchPoints, filesDictionary); } } @@ -706,8 +701,6 @@ private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method m if (source.FileFound) { - #region Use line/col-sorted SequencePoint's offset and content to Remove Compiler Generated Branches - // initialize offset with unreachable values long startOffset = long.MinValue; long finalOffset = long.MaxValue; @@ -742,8 +735,6 @@ private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method m return false; // return error/failure to caller } - #endregion - } else { // Do as much possible without source @@ -776,7 +767,7 @@ private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method m private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source, long startOffset, long finalOffset) { - // Method offsets found or not found, now check foreach sequence point + // foreach sequence point foreach (var sp in method.SequencePoints .Where (sp => sp.FileId == method.FileRefUniqueId && sp.BranchPoints.Count != 0)) { @@ -813,57 +804,7 @@ private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method m return true; } - /// - /// Computes reduced SequencePoint branch coverage - /// by finding common exit offset (switch/case) - /// - /// - private static void TransformSequences_ReduceBranches (IEnumerable methods) - { - foreach (var method in methods) { - - #region Merge Branch-Exits for each Sequence - - // Collection of validBranchPoints (child/connected to parent SequencePoint) - var validBranchPoints = new List(); - var branchExits = new Dictionary(); - foreach (var sp in method.SequencePoints) { - // SequencePoint has branches attached? - if (sp.BranchPoints.Count != 0) { - // Merge sp.BranchPoints using EndOffset as branchExits key - branchExits.Clear(); - foreach (var branchPoint in sp.BranchPoints) { - if (!branchExits.ContainsKey(branchPoint.EndOffset)) { - branchExits[branchPoint.EndOffset] = branchPoint; - // insert branch - } else { - branchExits[branchPoint.EndOffset].VisitCount += branchPoint.VisitCount; - // update branch - } - } - // Update SequencePoint counters - sp.BranchExitsCount = 0; - sp.BranchExitsVisit = 0; - foreach (var branchPoint in branchExits.Values) { - sp.BranchExitsCount += 1; - sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; - } - // Add to validBranchPoints - validBranchPoints.AddRange(sp.BranchPoints); - sp.BranchPoints = new List(); - } - } - // Replace original method branchPoints with valid (filtered and joined) branches. - // Order is Required by FilePersistanceTest because it does not sets .Offset. - // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) - method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); - - #endregion - } - } - - - private static void TransformSequences_RemoveFalsePositiveUnvisited (IList methods, SourceRepository sourceRepository, DateTime moduleTime) + private static void TransformSequences_RemoveFalsePositiveUnvisited (IEnumerable methods, SourceRepository sourceRepository, DateTime moduleTime) { // From Methods with Source and visited SequencePoints var sequencePointsQuery = methods @@ -913,7 +854,7 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (IList> toRemoveMethodSequencePoint) + private static void TransformSequences_RemoveFalsePositiveUnvisited (Method method, CodeCoverageStringTextSource source, ICollection> toRemoveMethodSequencePoint) { // Select false unvisited right-curly-braces at generated "MoveNext" method // (Curly braces moved to generated "MoveNext" method and left unvisited) @@ -927,22 +868,66 @@ private static void TransformSequences_RemoveFalsePositiveUnvisited (Method meth foreach (var sp in method.SequencePoints.Reverse()) { if (sp.FileId == method.FileRefUniqueId && sp.IsSingleCharSequencePoint - && sp.VisitCount == 0 // unvisited only - ) { - } else { - continue; + && sp.VisitCount == 0) { // unvisited only + + if (countDown > 0) { + if (source.GetText(sp) == "}") { + toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); + countDown -= 1; + } + } + else { + break; + } } - if (countDown > 0) { - if (source.GetText(sp) == "}") { - toRemoveMethodSequencePoint.Add (new Tuple(method, sp)); - countDown -= 1; + } + } + } + } + + /// + /// Computes reduced SequencePoint branch coverage + /// by finding common exit offset (switch/case) + /// + /// + private static void TransformSequences_ReduceBranches (IEnumerable methods) + { + foreach (var method in methods) { + + // Collection of validBranchPoints (child/connected to parent SequencePoint) + var validBranchPoints = new List(); + var branchExits = new Dictionary(); + foreach (var sp in method.SequencePoints) { + // SequencePoint has branches attached? + if (sp.BranchPoints.Count != 0) { + // Merge sp.BranchPoints using EndOffset as branchExits key + branchExits.Clear(); + foreach (var branchPoint in sp.BranchPoints) { + if (!branchExits.ContainsKey(branchPoint.EndOffset)) { + branchExits[branchPoint.EndOffset] = branchPoint; + // insert branch + } else { + branchExits[branchPoint.EndOffset].VisitCount += branchPoint.VisitCount; + // update branch } } - else { - break; + // Update SequencePoint counters + sp.BranchExitsCount = 0; + sp.BranchExitsVisit = 0; + foreach (var branchPoint in branchExits.Values) { + sp.BranchExitsCount += 1; + sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; } + // Add to validBranchPoints + validBranchPoints.AddRange(sp.BranchPoints); + sp.BranchPoints = new List(); } } + // Replace original method branchPoints with valid (filtered and joined) branches. + // Order is Required by FilePersistanceTest because it does not sets .Offset. + // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) + method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); + } } From 84ea6952e3e0496209e4fd9baa5e26b5561c4b9b Mon Sep 17 00:00:00 2001 From: ddur Date: Mon, 25 Jan 2016 22:23:32 +0100 Subject: [PATCH 28/30] SonarQube: naming convention? --- main/OpenCover.Framework/Model/Method.cs | 12 ++++++------ main/OpenCover.Framework/Model/SequencePoint.cs | 6 +++--- .../Utility/CodeCoverageStringTextSource.cs | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/main/OpenCover.Framework/Model/Method.cs b/main/OpenCover.Framework/Model/Method.cs index 9d2607c5c..1da2bb5c7 100644 --- a/main/OpenCover.Framework/Model/Method.cs +++ b/main/OpenCover.Framework/Model/Method.cs @@ -40,26 +40,26 @@ internal UInt32 FileRefUniqueId { /// public SequencePoint[] SequencePoints { get { - return sequencePoints; + return _sequencePoints; } set { - sequencePoints = value ?? new SequencePoint[0]; + _sequencePoints = value ?? new SequencePoint[0]; } } - private SequencePoint[] sequencePoints = new SequencePoint[0]; + private SequencePoint[] _sequencePoints = new SequencePoint[0]; /// /// A list of branch points that have been identified for this method /// public BranchPoint[] BranchPoints { get { - return branchPoints; + return _branchPoints; } set { - branchPoints = value ?? new BranchPoint[0]; + _branchPoints = value ?? new BranchPoint[0]; } } - private BranchPoint[] branchPoints = new BranchPoint[0]; + private BranchPoint[] _branchPoints = new BranchPoint[0]; /// /// A method point to identify the entry of a method diff --git a/main/OpenCover.Framework/Model/SequencePoint.cs b/main/OpenCover.Framework/Model/SequencePoint.cs index 762d1ded5..a335babcb 100644 --- a/main/OpenCover.Framework/Model/SequencePoint.cs +++ b/main/OpenCover.Framework/Model/SequencePoint.cs @@ -68,13 +68,13 @@ public class SequencePoint : InstrumentationPoint, IDocumentReference internal List BranchPoints { get{ - return branchPoints; + return _branchPoints; } set{ - branchPoints = value ?? new List(); + _branchPoints = value ?? new List(); } } - private List branchPoints = new List(); + private List _branchPoints = new List(); /// /// Property diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index 0dc62dbb0..1f25bb0c3 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -50,8 +50,8 @@ public class CodeCoverageStringTextSource /// /// Last write DateTime /// - public DateTime FileTime { get { return fileTime; } } - private readonly DateTime fileTime = DateTime.MinValue; + public DateTime FileTime { get { return _fileTime; } } + private readonly DateTime _fileTime = DateTime.MinValue; private readonly string _textSource; @@ -78,7 +78,7 @@ public CodeCoverageStringTextSource(string source, string filePath = "") } if (_fileFound) { try { - fileTime = System.IO.File.GetLastWriteTime (this._filePath); + _fileTime = System.IO.File.GetLastWriteTime (this._filePath); } catch (Exception e) { e.InformUser(); } @@ -255,7 +255,7 @@ public string GetLine ( int lineNo ) { /// /// public bool IsChanged (DateTime referenceTime) { - return referenceTime != DateTime.MinValue && fileTime > referenceTime; + return referenceTime != DateTime.MinValue && _fileTime > referenceTime; } /// From 482776c52c147d5e52091ee92fbff411ecb6c009 Mon Sep 17 00:00:00 2001 From: sawilde Date: Tue, 26 Jan 2016 11:42:54 +1100 Subject: [PATCH 29/30] #512 deal with situation where assembly casing in filepath is not the same as the extracted assembly name - causing the case sensitive filters to not exclude expected assemblies --- .../Service/ProfilerCommunication.cs | 5 ++- main/OpenCover.Test/Framework/FilterTests.cs | 22 --------- .../Service/ProfilerCommunicationTests.cs | 45 +++++++++++++++++++ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/main/OpenCover.Framework/Service/ProfilerCommunication.cs b/main/OpenCover.Framework/Service/ProfilerCommunication.cs index 2b6771d19..796e86756 100644 --- a/main/OpenCover.Framework/Service/ProfilerCommunication.cs +++ b/main/OpenCover.Framework/Service/ProfilerCommunication.cs @@ -4,6 +4,7 @@ // This source code is released under the MIT License; see the accompanying license file. // using System; +using System.IO; using System.Linq; using OpenCover.Framework.Model; using OpenCover.Framework.Persistance; @@ -32,9 +33,9 @@ public bool TrackAssembly(string processPath, string modulePath, string assembly Module module = null; var builder = _instrumentationModelBuilderFactory.CreateModelBuilder(modulePath, assemblyName); var assemblyPath = assemblyName; - if (modulePath.Contains(assemblyName)) + if (string.Equals((Path.GetFileNameWithoutExtension(modulePath) ?? modulePath), assemblyName, StringComparison.InvariantCultureIgnoreCase)) { - assemblyPath = modulePath; + assemblyPath = modulePath.Replace(assemblyName.ToLowerInvariant(), assemblyName); } if (!_filter.UseAssembly(processPath, assemblyPath)) { diff --git a/main/OpenCover.Test/Framework/FilterTests.cs b/main/OpenCover.Test/Framework/FilterTests.cs index 764fa0527..8cff9a559 100644 --- a/main/OpenCover.Test/Framework/FilterTests.cs +++ b/main/OpenCover.Test/Framework/FilterTests.cs @@ -717,28 +717,6 @@ public void CanIdentify_AutoImplementedProperties() Assert.IsTrue(wasTested); } - #region scenarios for issue reported by user #512 - [TestCase(@"+[*]* -[*.Tests]*", @"Target", true)] - [TestCase(@"+[*]* -[*.Tests]*", @"Target.Tests", false)] - [TestCase(@"+[*]* -[*.Tests]* +[*.Tests]*", @"Target.Tests", false)] - [TestCase(@"+[*]* -[*.Tests]*", @"Target.Tests", false)] - [TestCase(@"+[*.Tests]*", @"Target.Tests", true)] - #endregion - public void CanHandle_AssemblyFilters_reported(string filterArg, string assembly, bool canUse) - { - // arrange - var filter = new Filter(false); - foreach (var f in filterArg.Split(' ')) - { - filter.AddFilter(f); - } - - // act - - // assert - Assert.AreEqual(canUse, filter.UseAssembly("nunit-agent.exe", assembly)); - } - [Test] [TestCase("A1.B1", false)] [TestCase("A1.B2", true)] diff --git a/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs b/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs index 28214b4a2..66025a435 100644 --- a/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs +++ b/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs @@ -383,5 +383,50 @@ public void TrackProcessResponse_IsFulfilledByFilter(bool expected) // assert Assert.AreEqual(expected, response); } + + // issue #512 when filter matches on correctly cased path (folder) but assembly itself is not the correct case to match (regex is case-sensitive) + // change due to process filters - this originally failed due to matching on the path (folder name) which had the correct case + [Test] + public void TrackAssembly_Adds_AssemblyToModel_When_PathCaseIsLowerCase() + { + // path supplied by profiler - note case of assembly name - GetModuleInfo appears to be a precarious beast + var suppliedPath = @"C:\Projects\external\dotnet\corefx\bin\tests\AnyOS.AnyCPU.Debug\System.Threading.Tasks.Extensions.Tests\dnxcore50\system.threading.tasks.extensions.tests.dll"; + + // module name passed by profiler - note the expected case + var assemblyName = "System.Threading.Tasks.Extensions.Tests"; + + // arrange + // this path is what is needed for filters to work - note the case of the assembly at the end + var modulePath = @"C:\Projects\external\dotnet\corefx\bin\tests\AnyOS.AnyCPU.Debug\System.Threading.Tasks.Extensions.Tests\dnxcore50\System.Threading.Tasks.Extensions.Tests.dll"; + Container.GetMock() + .Setup(x => x.UseAssembly(It.IsAny(), modulePath)) + .Returns(true); + + Container.GetMock() + .Setup(x => x.ExcludeByAttribute(It.IsAny())) + .Returns(false); + + var mockModelBuilder = new Mock(); + Container.GetMock() + .Setup(x => x.CreateModelBuilder(It.IsAny(), It.IsAny())) + .Returns(mockModelBuilder.Object); + + mockModelBuilder + .SetupGet(x => x.CanInstrument) + .Returns(true); + + mockModelBuilder + .Setup(x => x.BuildModuleModel(It.IsAny())) + .Returns(new Module()); + + // act + var track = Instance.TrackAssembly("processName", suppliedPath, assemblyName); + + // assert + Assert.IsTrue(track); + Container.GetMock() + .Verify(x => x.PersistModule(It.IsAny()), Times.Once()); + } + } } From 4f2c356f156f6cba5fca129b1fed431b64f5f225 Mon Sep 17 00:00:00 2001 From: sawilde Date: Tue, 26 Jan 2016 21:17:09 +1100 Subject: [PATCH 30/30] #512 - revert change that led to broken filter --- .../Service/ProfilerCommunication.cs | 8 +--- .../Service/ProfilerCommunicationTests.cs | 45 ------------------- 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/main/OpenCover.Framework/Service/ProfilerCommunication.cs b/main/OpenCover.Framework/Service/ProfilerCommunication.cs index 796e86756..34ce65cd3 100644 --- a/main/OpenCover.Framework/Service/ProfilerCommunication.cs +++ b/main/OpenCover.Framework/Service/ProfilerCommunication.cs @@ -32,12 +32,8 @@ public bool TrackAssembly(string processPath, string modulePath, string assembly return true; Module module = null; var builder = _instrumentationModelBuilderFactory.CreateModelBuilder(modulePath, assemblyName); - var assemblyPath = assemblyName; - if (string.Equals((Path.GetFileNameWithoutExtension(modulePath) ?? modulePath), assemblyName, StringComparison.InvariantCultureIgnoreCase)) - { - assemblyPath = modulePath.Replace(assemblyName.ToLowerInvariant(), assemblyName); - } - if (!_filter.UseAssembly(processPath, assemblyPath)) + + if (!_filter.UseAssembly(processPath, assemblyName)) { module = builder.BuildModuleModel(false); module.MarkAsSkipped(SkippedMethod.Filter); diff --git a/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs b/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs index 66025a435..28214b4a2 100644 --- a/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs +++ b/main/OpenCover.Test/Framework/Service/ProfilerCommunicationTests.cs @@ -383,50 +383,5 @@ public void TrackProcessResponse_IsFulfilledByFilter(bool expected) // assert Assert.AreEqual(expected, response); } - - // issue #512 when filter matches on correctly cased path (folder) but assembly itself is not the correct case to match (regex is case-sensitive) - // change due to process filters - this originally failed due to matching on the path (folder name) which had the correct case - [Test] - public void TrackAssembly_Adds_AssemblyToModel_When_PathCaseIsLowerCase() - { - // path supplied by profiler - note case of assembly name - GetModuleInfo appears to be a precarious beast - var suppliedPath = @"C:\Projects\external\dotnet\corefx\bin\tests\AnyOS.AnyCPU.Debug\System.Threading.Tasks.Extensions.Tests\dnxcore50\system.threading.tasks.extensions.tests.dll"; - - // module name passed by profiler - note the expected case - var assemblyName = "System.Threading.Tasks.Extensions.Tests"; - - // arrange - // this path is what is needed for filters to work - note the case of the assembly at the end - var modulePath = @"C:\Projects\external\dotnet\corefx\bin\tests\AnyOS.AnyCPU.Debug\System.Threading.Tasks.Extensions.Tests\dnxcore50\System.Threading.Tasks.Extensions.Tests.dll"; - Container.GetMock() - .Setup(x => x.UseAssembly(It.IsAny(), modulePath)) - .Returns(true); - - Container.GetMock() - .Setup(x => x.ExcludeByAttribute(It.IsAny())) - .Returns(false); - - var mockModelBuilder = new Mock(); - Container.GetMock() - .Setup(x => x.CreateModelBuilder(It.IsAny(), It.IsAny())) - .Returns(mockModelBuilder.Object); - - mockModelBuilder - .SetupGet(x => x.CanInstrument) - .Returns(true); - - mockModelBuilder - .Setup(x => x.BuildModuleModel(It.IsAny())) - .Returns(new Module()); - - // act - var track = Instance.TrackAssembly("processName", suppliedPath, assemblyName); - - // assert - Assert.IsTrue(track); - Container.GetMock() - .Verify(x => x.PersistModule(It.IsAny()), Times.Once()); - } - } }