From 388a9a65b45926084addb1a73f5e0368754362d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Thu, 19 Dec 2019 00:48:37 +0100 Subject: [PATCH 1/5] changes regarding relative path to source --- .../Reporters/CoberturaReporter.cs | 34 ++++++++++---- .../Reporters/CoberturaReporterTests.cs | 44 ++++++++++++++----- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index d3c11f956..517eb7021 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -32,8 +32,8 @@ public string Report(CoverageResult result) coverage.Add(new XAttribute("timestamp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds)); XElement sources = new XElement("sources"); - var rootDirs = GetRootDirs(result.Modules, result.UseSourceLink).ToList(); - rootDirs.ForEach(x => sources.Add(new XElement("source", x))); + var basePaths = GetBasePaths(result.Modules, result.UseSourceLink).ToList(); + basePaths.ForEach(x => sources.Add(new XElement("source", x))); XElement packages = new XElement("packages"); foreach (var module in result.Modules) @@ -51,7 +51,7 @@ public string Report(CoverageResult result) { XElement @class = new XElement("class"); @class.Add(new XAttribute("name", cls.Key)); - @class.Add(new XAttribute("filename", GetRelativePathFromBase(rootDirs, document.Key, result.UseSourceLink))); + @class.Add(new XAttribute("filename", GetRelativePathFromBase(basePaths, document.Key, result.UseSourceLink))); @class.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(cls.Value))); @@ -133,28 +133,44 @@ public string Report(CoverageResult result) return Encoding.UTF8.GetString(stream.ToArray()); } - private static IEnumerable GetRootDirs(Modules modules, bool useSourceLink) + private static IEnumerable GetBasePaths(Modules modules, bool useSourceLink) { if (useSourceLink) { return new[] { string.Empty }; } - return modules.Values.SelectMany(k => k.Keys).Select(Directory.GetDirectoryRoot).Distinct(); + var pathsGroupedByRootDir = modules.Values.SelectMany(k => k.Keys).GroupBy(Directory.GetDirectoryRoot); + var basePaths = pathsGroupedByRootDir.Select(group => + { + var splittedPaths = group.Select(x => x.Split(Path.DirectorySeparatorChar)).ToList(); + var basePathSegments = new List(); + + splittedPaths[0].Select((value, index) => (value, index)).ToList().ForEach(x => + { + if (splittedPaths.All(s => x.value.Equals(s[x.index]))) + { + basePathSegments.Add(x.value); + } + }); + + return Path.Combine(basePathSegments.ToArray()); + }); + return basePaths; } - private static string GetRelativePathFromBase(IEnumerable rootPaths, string path, bool useSourceLink) + private static string GetRelativePathFromBase(IEnumerable basePaths, string path, bool useSourceLink) { if (useSourceLink) { return path; } - foreach (var root in rootPaths) + foreach (var basePath in basePaths) { - if (path.StartsWith(root)) + if (path.StartsWith(basePath)) { - return path.Substring(root.Length); + return path.Substring(basePath.Length); } } diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 83e4ab057..7b31a6833 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -137,7 +137,7 @@ public void TestEnsureParseMethodStringCorrectly( } [Fact] - public void TestReportWithTwoDifferentDirectories() + public void TestReportWithDifferentDirectories() { CoverageResult result = new CoverageResult(); result.Identifier = Guid.NewGuid().ToString(); @@ -146,43 +146,65 @@ public void TestReportWithTwoDifferentDirectories() string absolutePath1; string absolutePath2; + string absolutePath3; + string absolutePath4; + string absolutePath5; + string absolutePath6; if (isWindows) { - absolutePath1 = @"C:\projA\file.cs"; - absolutePath2 = @"E:\projB\file.cs"; + absolutePath1 = @"C:\projA\dir1\dir10\file1.cs"; + absolutePath2 = @"C:\projA\dir1\dir10\file2.cs"; + absolutePath3 = @"C:\projA\dir1\file3.cs"; + absolutePath4 = @"E:\projB\dir1\file4.cs"; + absolutePath5 = @"E:\projB\dir2\file5.cs"; + absolutePath6 = @"E:\projB\dir3\file6.cs"; } else { - absolutePath1 = @"/projA/file.cs"; - absolutePath2 = @"/projB/file.cs"; + absolutePath1 = @"/projA/dir1/dir10/file1.cs"; + absolutePath2 = @"/projA/dir1/file2.cs"; + absolutePath3 = @"/projA/dir1/file3.cs"; + absolutePath4 = @"/projA/dir2/file4.cs"; + absolutePath5 = @"/projA/dir2/file5.cs"; + absolutePath6 = @"/projA/dir2/file6.cs"; } - var classes = new Classes {{"Class", new Methods()}}; - var documents = new Documents {{absolutePath1, classes}, {absolutePath2, classes}}; + var classes = new Classes { { "Class", new Methods() } }; + var documents = new Documents { { absolutePath1, classes }, + { absolutePath2, classes }, + { absolutePath3, classes }, + { absolutePath4, classes }, + { absolutePath5, classes }, + { absolutePath6, classes } + }; - result.Modules = new Modules {{"Module", documents}}; + result.Modules = new Modules { { "Module", documents } }; CoberturaReporter reporter = new CoberturaReporter(); string report = reporter.Report(result); var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); - List rootPaths = doc.Element("coverage").Element("sources").Elements().Select(e => e.Value).ToList(); + List basePaths = doc.Element("coverage").Element("sources").Elements().Select(e => e.Value).ToList(); List relativePaths = doc.Element("coverage").Element("packages").Element("package") .Element("classes").Elements().Select(e => e.Attribute("filename").Value).ToList(); List possiblePaths = new List(); - foreach (string root in rootPaths) + foreach (string basePath in basePaths) { foreach (string relativePath in relativePaths) { - possiblePaths.Add(Path.Combine(root, relativePath)); + possiblePaths.Add(Path.Join(basePath, relativePath)); } } Assert.Contains(absolutePath1, possiblePaths); Assert.Contains(absolutePath2, possiblePaths); + Assert.Contains(absolutePath3, possiblePaths); + Assert.Contains(absolutePath4, possiblePaths); + Assert.Contains(absolutePath5, possiblePaths); + Assert.Contains(absolutePath6, possiblePaths); } [Fact] From 50c32884ec2d031db4dc021812b8f5be0a646d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Thu, 19 Dec 2019 17:39:04 +0100 Subject: [PATCH 2/5] changes to the concatenation of the path segments --- src/coverlet.core/Reporters/CoberturaReporter.cs | 8 ++++++-- .../Reporters/CoberturaReporterTests.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 517eb7021..c1ccd0cf3 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -144,6 +144,11 @@ private static IEnumerable GetBasePaths(Modules modules, bool useSourceL var basePaths = pathsGroupedByRootDir.Select(group => { var splittedPaths = group.Select(x => x.Split(Path.DirectorySeparatorChar)).ToList(); + if (splittedPaths.Count == 1) + { + return group.Key; + } + var basePathSegments = new List(); splittedPaths[0].Select((value, index) => (value, index)).ToList().ForEach(x => @@ -153,8 +158,7 @@ private static IEnumerable GetBasePaths(Modules modules, bool useSourceL basePathSegments.Add(x.value); } }); - - return Path.Combine(basePathSegments.ToArray()); + return string.Concat(string.Join(Path.DirectorySeparatorChar.ToString(), basePathSegments), Path.DirectorySeparatorChar); }); return basePaths; } diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 7b31a6833..5df732176 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -195,7 +195,7 @@ public void TestReportWithDifferentDirectories() { foreach (string relativePath in relativePaths) { - possiblePaths.Add(Path.Join(basePath, relativePath)); + possiblePaths.Add(Path.Combine(basePath, relativePath)); } } From d75cb0be6d7820d430b38edc928dd556fd54cdf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Thu, 19 Dec 2019 20:43:24 +0100 Subject: [PATCH 3/5] changed order of grouped paths --- src/coverlet.core/Reporters/CoberturaReporter.cs | 2 +- test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index c1ccd0cf3..a61d46ebb 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -143,7 +143,7 @@ private static IEnumerable GetBasePaths(Modules modules, bool useSourceL var pathsGroupedByRootDir = modules.Values.SelectMany(k => k.Keys).GroupBy(Directory.GetDirectoryRoot); var basePaths = pathsGroupedByRootDir.Select(group => { - var splittedPaths = group.Select(x => x.Split(Path.DirectorySeparatorChar)).ToList(); + var splittedPaths = group.Select(x => x.Split(Path.DirectorySeparatorChar)).OrderBy(x => x.Length).ToList(); if (splittedPaths.Count == 1) { return group.Key; diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 5df732176..96e48166e 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -156,7 +156,7 @@ public void TestReportWithDifferentDirectories() absolutePath1 = @"C:\projA\dir1\dir10\file1.cs"; absolutePath2 = @"C:\projA\dir1\dir10\file2.cs"; absolutePath3 = @"C:\projA\dir1\file3.cs"; - absolutePath4 = @"E:\projB\dir1\file4.cs"; + absolutePath4 = @"E:\projB\dir1\dir10\file4.cs"; absolutePath5 = @"E:\projB\dir2\file5.cs"; absolutePath6 = @"E:\projB\dir3\file6.cs"; } From 6eebbff2b4805f8e6688abe33662ae245476e1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Sat, 21 Dec 2019 01:40:05 +0100 Subject: [PATCH 4/5] code review --- .../Reporters/CoberturaReporter.cs | 49 ++++++++++++++----- .../Reporters/CoberturaReporterTests.cs | 15 +++--- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index a61d46ebb..811061480 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -32,8 +32,8 @@ public string Report(CoverageResult result) coverage.Add(new XAttribute("timestamp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds)); XElement sources = new XElement("sources"); - var basePaths = GetBasePaths(result.Modules, result.UseSourceLink).ToList(); - basePaths.ForEach(x => sources.Add(new XElement("source", x))); + var absolutePaths = GetBasePaths(result.Modules, result.UseSourceLink).ToList(); + absolutePaths.ForEach(x => sources.Add(new XElement("source", x))); XElement packages = new XElement("packages"); foreach (var module in result.Modules) @@ -51,7 +51,7 @@ public string Report(CoverageResult result) { XElement @class = new XElement("class"); @class.Add(new XAttribute("name", cls.Key)); - @class.Add(new XAttribute("filename", GetRelativePathFromBase(basePaths, document.Key, result.UseSourceLink))); + @class.Add(new XAttribute("filename", GetRelativePathFromBase(absolutePaths, document.Key, result.UseSourceLink))); @class.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(cls.Value))); @@ -135,32 +135,55 @@ public string Report(CoverageResult result) private static IEnumerable GetBasePaths(Modules modules, bool useSourceLink) { + /* + Workflow + + Path1 c:\dir1\dir2\file1.cs + Path2 c:\dir1\file2.cs + Path3 e:\dir1\file2.cs + + 1) Search for root dir + c:\ -> c:\dir1\dir2\file1.cs + c:\dir1\file2.cs + e:\ -> e:\dir1\file2.cs + + 2) Split path on directory separator i.e. for record c:\ ordered ascending by fragment elements + Path1 = [c:|dir1|file2.cs] + Path2 = [c:|dir1|dir2|file1.cs] + + 3) Find longest shared path comparing indexes + Path1[0] = Path2[0], ..., PathY[0] -> add to final fragment list + Path1[n] = Path2[n], ..., PathY[n] -> add to final fragment list + Path1[n+1] != Path2[n+1], ..., PathY[n+1] -> break, Path1[n] was last shared fragment + + 4) Concat created fragment list + */ if (useSourceLink) { - return new[] { string.Empty }; + return new[] {string.Empty}; } - var pathsGroupedByRootDir = modules.Values.SelectMany(k => k.Keys).GroupBy(Directory.GetDirectoryRoot); - var basePaths = pathsGroupedByRootDir.Select(group => + return modules.Values.SelectMany(k => k.Keys).GroupBy(Directory.GetDirectoryRoot).Select(group => { - var splittedPaths = group.Select(x => x.Split(Path.DirectorySeparatorChar)).OrderBy(x => x.Length).ToList(); + var splittedPaths = group.Select(absolutePath => absolutePath.Split(Path.DirectorySeparatorChar)) + .OrderBy(absolutePath => absolutePath.Length).ToList(); if (splittedPaths.Count == 1) { return group.Key; } - var basePathSegments = new List(); + var basePathFragments = new List(); - splittedPaths[0].Select((value, index) => (value, index)).ToList().ForEach(x => + splittedPaths[0].Select((value, index) => (value, index)).ToList().ForEach(fragmentIndexPair => { - if (splittedPaths.All(s => x.value.Equals(s[x.index]))) + if (splittedPaths.All(s => fragmentIndexPair.value.Equals(s[fragmentIndexPair.index]))) { - basePathSegments.Add(x.value); + basePathFragments.Add(fragmentIndexPair.value); } }); - return string.Concat(string.Join(Path.DirectorySeparatorChar.ToString(), basePathSegments), Path.DirectorySeparatorChar); + return string.Concat(string.Join(Path.DirectorySeparatorChar.ToString(), basePathFragments), + Path.DirectorySeparatorChar); }); - return basePaths; } private static string GetRelativePathFromBase(IEnumerable basePaths, string path, bool useSourceLink) diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 96e48166e..81d512d52 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -142,23 +142,23 @@ public void TestReportWithDifferentDirectories() CoverageResult result = new CoverageResult(); result.Identifier = Guid.NewGuid().ToString(); - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - string absolutePath1; string absolutePath2; string absolutePath3; string absolutePath4; string absolutePath5; string absolutePath6; + string absolutePath7; - if (isWindows) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { absolutePath1 = @"C:\projA\dir1\dir10\file1.cs"; absolutePath2 = @"C:\projA\dir1\dir10\file2.cs"; absolutePath3 = @"C:\projA\dir1\file3.cs"; absolutePath4 = @"E:\projB\dir1\dir10\file4.cs"; absolutePath5 = @"E:\projB\dir2\file5.cs"; - absolutePath6 = @"E:\projB\dir3\file6.cs"; + absolutePath6 = @"F:\file6"; + absolutePath7 = @"F:\"; } else { @@ -167,7 +167,8 @@ public void TestReportWithDifferentDirectories() absolutePath3 = @"/projA/dir1/file3.cs"; absolutePath4 = @"/projA/dir2/file4.cs"; absolutePath5 = @"/projA/dir2/file5.cs"; - absolutePath6 = @"/projA/dir2/file6.cs"; + absolutePath6 = @"/file1.cs"; + absolutePath7 = @"/"; } var classes = new Classes { { "Class", new Methods() } }; @@ -176,7 +177,8 @@ public void TestReportWithDifferentDirectories() { absolutePath3, classes }, { absolutePath4, classes }, { absolutePath5, classes }, - { absolutePath6, classes } + { absolutePath6, classes }, + { absolutePath7, classes } }; result.Modules = new Modules { { "Module", documents } }; @@ -205,6 +207,7 @@ public void TestReportWithDifferentDirectories() Assert.Contains(absolutePath4, possiblePaths); Assert.Contains(absolutePath5, possiblePaths); Assert.Contains(absolutePath6, possiblePaths); + Assert.Contains(absolutePath7, possiblePaths); } [Fact] From 7f24eb147870779a1ec55fa8a6d908429a087698 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sat, 21 Dec 2019 09:10:53 +0100 Subject: [PATCH 5/5] some nits --- src/coverlet.core/Reporters/CoberturaReporter.cs | 7 +++---- .../Reporters/CoberturaReporterTests.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 811061480..cebaa569a 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -160,7 +160,7 @@ private static IEnumerable GetBasePaths(Modules modules, bool useSourceL */ if (useSourceLink) { - return new[] {string.Empty}; + return new[] { string.Empty }; } return modules.Values.SelectMany(k => k.Keys).GroupBy(Directory.GetDirectoryRoot).Select(group => @@ -176,13 +176,12 @@ private static IEnumerable GetBasePaths(Modules modules, bool useSourceL splittedPaths[0].Select((value, index) => (value, index)).ToList().ForEach(fragmentIndexPair => { - if (splittedPaths.All(s => fragmentIndexPair.value.Equals(s[fragmentIndexPair.index]))) + if (splittedPaths.All(sp => fragmentIndexPair.value.Equals(sp[fragmentIndexPair.index]))) { basePathFragments.Add(fragmentIndexPair.value); } }); - return string.Concat(string.Join(Path.DirectorySeparatorChar.ToString(), basePathFragments), - Path.DirectorySeparatorChar); + return string.Concat(string.Join(Path.DirectorySeparatorChar.ToString(), basePathFragments), Path.DirectorySeparatorChar); }); } diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index 81d512d52..6a90f9f5f 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -157,7 +157,7 @@ public void TestReportWithDifferentDirectories() absolutePath3 = @"C:\projA\dir1\file3.cs"; absolutePath4 = @"E:\projB\dir1\dir10\file4.cs"; absolutePath5 = @"E:\projB\dir2\file5.cs"; - absolutePath6 = @"F:\file6"; + absolutePath6 = @"F:\file6.cs"; absolutePath7 = @"F:\"; } else