Skip to content

Commit

Permalink
sonarqube-writer: Add output support for the SonarQube coverage plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Kagstrom committed Jan 15, 2016
1 parent 2572d06 commit 95814ff
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ set (${KCOV}_SRCS
writers/cobertura-writer.cc
${coveralls_SRCS}
writers/html-writer.cc
writers/sonarqube-xml-writer.cc
writers/writer-base.cc
${LINUX_SRCS}
)
Expand Down
10 changes: 10 additions & 0 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "writers/html-writer.hh"
#include "writers/coveralls-writer.hh"
#include "writers/cobertura-writer.hh"
#include "writers/sonarqube-xml-writer.hh"

using namespace kcov;

Expand Down Expand Up @@ -164,12 +165,15 @@ static int runMergeMode()
base, base + "/kcov-merged", "[merged]", true);
IWriter &mergeCoberturaWriter = createCoberturaWriter(mergeParser, mergeReporter,
base + "kcov-merged/cobertura.xml");
IWriter &mergeSonarqubeWriter = createSonarqubeWriter(mergeParser, mergeReporter,
base + "kcov-merged/sonarqube.xml");
IWriter &mergeCoverallsWriter = createCoverallsWriter(mergeParser, mergeReporter);
(void)mkdir(fmt("%s/kcov-merged", base.c_str()).c_str(), 0755);

output.registerWriter(mergeParser);
output.registerWriter(mergeHtmlWriter);
output.registerWriter(mergeCoberturaWriter);
output.registerWriter(mergeSonarqubeWriter);
output.registerWriter(mergeCoverallsWriter);

output.start();
Expand Down Expand Up @@ -227,6 +231,8 @@ int main(int argc, const char *argv[])
base, out, conf.keyAsString("binary-name"));
IWriter &coberturaWriter = createCoberturaWriter(*parser, reporter,
out + "/cobertura.xml");
IWriter &sonarqubeWriter = createSonarqubeWriter(*parser, reporter,
out + "/sonarqube.xml");

// The merge parser is both a parser, a writer and a collector (!)
IMergeParser &mergeParser = createMergeParser(reporter, base, out, filter);
Expand All @@ -235,6 +241,8 @@ int main(int argc, const char *argv[])
base, base + "/kcov-merged", "[merged]", false);
IWriter &mergeCoberturaWriter = createCoberturaWriter(mergeParser, mergeReporter,
base + "kcov-merged/cobertura.xml");
IWriter &mergeSonarqubeWriter = createSonarqubeWriter(mergeParser, mergeReporter,
base + "kcov-merged/sonarqube.xml");
(void)mkdir(fmt("%s/kcov-merged", base.c_str()).c_str(), 0755);

reporter.registerListener(mergeParser);
Expand All @@ -245,13 +253,15 @@ int main(int argc, const char *argv[])
if (countMetadata() > 0) {
output.registerWriter(mergeHtmlWriter);
output.registerWriter(mergeCoberturaWriter);
output.registerWriter(mergeSonarqubeWriter);
output.registerWriter(createCoverallsWriter(mergeParser, mergeReporter));
} else {
output.registerWriter(createCoverallsWriter(*parser, reporter));
}

output.registerWriter(htmlWriter);
output.registerWriter(coberturaWriter);
output.registerWriter(sonarqubeWriter);
}

g_engine = engine;
Expand Down
112 changes: 112 additions & 0 deletions src/writers/sonarqube-xml-writer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
namespace std { class type_info; }

#include <reporter.hh>
#include <file-parser.hh>
#include <configuration.hh>
#include <writer.hh>
#include <utils.hh>

#include <string>
#include <list>
#include <unordered_map>
#include <iostream>
#include <fstream>

#include "writer-base.hh"
#include "sonarqube-xml-writer.hh"

using namespace kcov;

class SonarQubeWriter : public WriterBase
{
public:
SonarQubeWriter(IFileParser &parser, IReporter &reporter,
const std::string &outFile) :
WriterBase(parser, reporter),
m_outFile(outFile),
m_maxPossibleHits(parser.maxPossibleHits())
{
}

void onStartup()
{
}

void onStop()
{
}

void write()
{
std::ofstream out(m_outFile);

// Output directory not writable?
if (!out.is_open())
return;

setupCommonPaths();

out << "<!-- Generated by kcov (https://simonkagstrom.github.io/kcov/) -->\n";
out << "<coverage version=\"1\">\n";

for (FileMap_t::const_iterator it = m_files.begin();
it != m_files.end();
++it) {
File *file = it->second;

writeOne(file, out);
}

out << "</coverage>\n";
}

private:
void writeOne(File *file, std::ofstream &out)
{
out << fmt(" <file path=\"%s\">\n", file->m_name.c_str());

for (unsigned int n = 1; n < file->m_lastLineNr; n++) {
if (!m_reporter.lineIsCode(file->m_name, n))
continue;

IReporter::LineExecutionCount cnt =
m_reporter.getLineExecutionCount(file->m_name, n);

std::string covered = cnt.m_hits ? "true" : "false";

out << fmt(" <lineToCover lineNumber=\"%d\" covered=\"%s\"", n, covered.c_str());

if (m_maxPossibleHits == IFileParser::HITS_LIMITED &&
cnt.m_possibleHits > 1) {
out << fmt(" branchesToCover=\"%d\" coveredBranches=\"%d\"", cnt.m_possibleHits, cnt.m_hits);
}

out << "/>\n";
}

out << " </file>\n";
}

std::string getHeader(unsigned int nCodeLines, unsigned int nExecutedLines)
{
return "<?xml version=\"1.0\" ?>\n";
}

const std::string getFooter()
{
return "";
}


std::string m_outFile;
IFileParser::PossibleHits m_maxPossibleHits;
};

namespace kcov
{
IWriter &createSonarqubeWriter(IFileParser &parser, IReporter &reporter,
const std::string &outFile)
{
return *new SonarQubeWriter(parser, reporter, outFile);
}
}
11 changes: 11 additions & 0 deletions src/writers/sonarqube-xml-writer.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

namespace kcov
{
class IFileParser;
class IReporter;
class IOutputHandler;

IWriter &createSonarqubeWriter(IFileParser &elf, IReporter &reporter,
const std::string &outFile);
}

0 comments on commit 95814ff

Please sign in to comment.