Skip to content

Commit

Permalink
Merge pull request lucaslorentz#30 from havocbcn/master
Browse files Browse the repository at this point in the history
Added mini-OpenCover report support to integrate SonarQube
  • Loading branch information
lucaslorentz authored Feb 25, 2018
2 parents 05ab17b + b6ac6a2 commit 2f7fbd4
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ coverage-html
coverage.json
coverage.xml
coverage-hits.txt
opencovercoverage.xml
bin
obj
.vs
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $MiniCover uninstrument
$MiniCover htmlreport --threshold 90
$MiniCover xmlreport --threshold 90
$MiniCover report --threshold 90
$MiniCover opencoverreport --threshold 90

if [ "${TRAVIS_PULL_REQUEST}" = "false" ] && [ "${TRAVIS_BRANCH}" = "master" ]; then
dotnet pack src/MiniCover -c Release --output $PWD/artifacts --version-suffix ci-`date +%Y%m%d%H%M%S`
Expand Down
28 changes: 28 additions & 0 deletions src/MiniCover/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,29 @@ static int Main(string[] args)
});
});

commandLineApplication.Command("opencoverreport", command =>
{
command.Description = "Write an OpenCover-formatted XML report to folder";

var workDirOption = CreateWorkdirOption(command);
var coverageFileOption = CreateCoverageFileOption(command);
var thresholdOption = CreateThresholdOption(command);
var outputOption = command.Option("--output", "Output file for OpenCover report [default: opencovercoverage.xml]", CommandOptionType.SingleValue);
command.HelpOption("-h | --help");

command.OnExecute(() =>
{
UpdateWorkingDirectory(workDirOption);

var coverageFile = GetCoverageFile(coverageFileOption);
var threshold = GetThreshold(thresholdOption);
var result = LoadCoverageFile(coverageFile);
var output = GetOpenCoverXmlReportOutput(outputOption);
OpenCoverReport.Execute(result, output, threshold);
return 0;
});
});

commandLineApplication.Command("reset", command =>
{
command.Description = "Reset hits count";
Expand Down Expand Up @@ -216,6 +239,11 @@ private static string GetXmlReportOutput(CommandOption outputOption)
return outputOption.Value() ?? "coverage.xml";
}

private static string GetOpenCoverXmlReportOutput(CommandOption outputOption)
{
return outputOption.Value() ?? "opencovercoverage.xml";
}

private static string GetCoverageFile(CommandOption coverageFileOption)
{
return coverageFileOption.Value() ?? "coverage.json";
Expand Down
143 changes: 143 additions & 0 deletions src/MiniCover/Reports/OpenCoverReport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using MiniCover.Model;

namespace MiniCover.Reports
{
public static class OpenCoverReport
{
public static void Execute(InstrumentationResult result, string output, float threshold)
{
var hits = File.Exists(result.HitsFile)
? File.ReadAllLines(result.HitsFile).Select(h => int.Parse(h)).ToArray()
: new int[0];
int fileIndex = 0;
int sequencePointMegaCounter = 0;

var data = new XProcessingInstruction("xml-stylesheet", "type='text/xsl' href='coverage.xsl'");

var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), data);

var coverageElement = new XElement(
XName.Get("CoverageSession")
);

var modulesListElement = result.Assemblies.Select(assembly =>
{
var moduleElement = new XElement(
XName.Get("Module"),
new XAttribute(XName.Get("hash"), Guid.NewGuid().ToString())
);

var fullNameElement = new XElement(
XName.Get("FullName"),
new XText(assembly.Name)
);

var moduleNameElement = new XElement(
XName.Get("ModuleName"),
new XText(assembly.Name)
);

Dictionary<SourceFile, int> dctSourceFileCount = new Dictionary<SourceFile, int>();

var filesElement = assembly.SourceFiles.Select(file =>
{
dctSourceFileCount.Add(file.Value, ++fileIndex);
var fileElement = new XElement(
XName.Get("File"),
new XAttribute(XName.Get("uid"), dctSourceFileCount[file.Value]),
new XAttribute(XName.Get("fullPath"), Path.Combine(result.SourcePath, file.Key))
);

return fileElement;
});

var classesElement = assembly.SourceFiles.Select(file =>
{
var hitInstructions = file.Value.Instructions.Where(h => hits.Contains(h.Id)).ToArray();

return file.Value.Instructions
.GroupBy(instruction => new { instruction.Class })
.Select(classes =>
{
var classElement = new XElement(
XName.Get("Class")
);

var classfullNameElement = new XElement(
XName.Get("FullName"),
new XText(classes.Key.Class)
);

var methodsList = classes
.GroupBy(instruction => new { instruction.Method, instruction.MethodFullName })
.Select(method =>
{
var nameElement = new XElement(
XName.Get("Name"),
new XText(method.Key.MethodFullName)
);

var fileRefElement = new XElement(
XName.Get("FileRef"),
new XAttribute(XName.Get("uid"), dctSourceFileCount[file.Value])
);

int sequencePointMiniCounter = 0;

var sequencePoints = method.Select(methodPoint =>
{
var hitCount = hitInstructions.Count(hit => hit.Equals(methodPoint));

return new XElement(
XName.Get("SequencePoint"),
new XAttribute(XName.Get("vc"), hitCount),
new XAttribute(XName.Get("uspid"), ++sequencePointMegaCounter),
new XAttribute(XName.Get("ordinal"), ++sequencePointMiniCounter),
new XAttribute(XName.Get("sl"), methodPoint.StartLine),
new XAttribute(XName.Get("sc"), methodPoint.StartColumn),
new XAttribute(XName.Get("el"), methodPoint.EndLine),
new XAttribute(XName.Get("ec"), methodPoint.EndColumn)
);
});

var methodElement = new XElement(
XName.Get("Method"),
new XAttribute(XName.Get("visited"), method.Any(p => hitInstructions.Any(hit => hit == p))),
new XAttribute(XName.Get("isConstructor"), method.Key.Method == ".ctor")
);

methodElement.Add(nameElement);
methodElement.Add(fileRefElement);
methodElement.Add(sequencePoints);

return methodElement;
});

classElement.Add(classfullNameElement);
classElement.Add(methodsList);

return classElement;
});
});

moduleElement.Add(fullNameElement);
moduleElement.Add(moduleNameElement);
moduleElement.Add(filesElement);
moduleElement.Add(classesElement);

return moduleElement;
});

coverageElement.Add(modulesListElement);

document.Add(coverageElement);

File.WriteAllText(output, document.ToString());
}
}
}

0 comments on commit 2f7fbd4

Please sign in to comment.