Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kcov zig 4merge (for discussion) #424

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug",
"program": "${workspaceFolder}/build/src/kcov",
"args": [
"./cov",
"--include-path=/Users/bytedance/DevCamp/jstring",
"--clean",
"/Users/bytedance/DevCamp/jstring/zig-out/bin/pcre_test"
],
"cwd": "${workspaceFolder}/../jstring"
}
]
}
94 changes: 71 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,62 @@
# A fork of `kcov` for better covering Zig

This is a rather than naive fork of wonderful `kcov` for better supporting Zig projects.

## It adds the ability to auto recognize Zig's `unreachable` and `@panic` for auto ignoring.

Here is a screenshot of auto ignoring `unreachable`.

![zig-unreachable-example](https://github.com/liyu1981/kcov/blob/master/nocover/zig-unreachable.png?raw=true)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this is nice information, but when "native" kcov supports it, I think it won't be needed (as it's shown in the output anyway).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, I will remove this in later cleaned up PR.


Here is another screenshot of auto ignoring `@panic`.

![zig-panic-example](https://github.com/liyu1981/kcov/blob/master/nocover/zig-panic.png?raw=true)

## It also adds the ability in c/c++ source file of using `/* no-cover */` to mark a line to be ignored.

Here is a screenshot of manual ignoring by placing `/* no-cover */` in c source file.

![c-no-cover example](https://github.com/liyu1981/kcov/blob/master/nocover/c-nocover.png?raw=true)

## Usage

There is no change of original `kcov` usage, it will just work. Please follow the below original Kcov README.

### But how can I get the binary?

The best way is to compile from source. It can be done as follows (you will need `cmake`, `ninja`, `llvm@>16` as I tried)

```
git clone https://github.com/liyu1981/kcov.git
cd kcov
mkdir build
cd build
CC="clang" CXX="clang++" cmake -G Ninja ..
ninja
```

after building is done. The binary is at `build/src/kcov`. Copy somewhere and use it.

(Or you can download a copy of Apple Silicon version binary from the release section.)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make a release shortly after merge of this, and then the osx homebrew is usually updated quite quickly.

I suppose that can be added to the README, or another documentation file. Since not all distributions are up to date, I don't want to in general recommend installing from there.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same to above


## File Support

- for Zig, support source file with `.zig` extension.
- for C/C++, support source file with `.c/.cpp/.cc` extension.

## Original Kcov Readme

[![Coveralls coverage status](https://img.shields.io/coveralls/SimonKagstrom/kcov.svg)](https://coveralls.io/r/SimonKagstrom/kcov?branch=master)
[![Codecov coverage status](https://codecov.io/gh/SimonKagstrom/kcov/branch/master/graph/badge.svg)](https://codecov.io/gh/SimonKagstrom/kcov)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/2844/badge.svg)](https://scan.coverity.com/projects/2844)
![Docker Pulls](https://img.shields.io/docker/pulls/kcov/kcov.svg)

[![PayPal Donate](https://img.shields.io/badge/paypal-donate-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=simon.kagstrom%40gmail%2ecom&lc=US&item_name=Simon%20Kagstrom&item_number=kcov&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) [![Github All Releases](https://img.shields.io/github/downloads/atom/atom/total.svg)](https://github.com/SimonKagstrom/kcov/)

## *kcov*
## _kcov_

Kcov is a FreeBSD/Linux/OSX code coverage tester for compiled languages, Python
and Bash. Kcov was originally a fork of [Bcov](http://bcov.sf.net), but has
and Bash. Kcov was originally a fork of [Bcov](http://bcov.sf.net), but has
since evolved to support a large feature set in addition to that of Bcov.

Kcov, like Bcov, uses DWARF debugging information for compiled programs to
Expand All @@ -16,28 +65,27 @@ switches.

For a video introduction, [look at this presentation from SwedenCPP](https://www.youtube.com/watch?v=1QMHbp5LUKg)

Installing
----------
## Installing

Refer to the [INSTALL](INSTALL.md) file for build instructions, or use our official Docker images:

* [kcov/kcov](https://hub.docker.com/r/kcov/kcov/) for releases since v31.
- [kcov/kcov](https://hub.docker.com/r/kcov/kcov/) for releases since v31.

## How to use it

How to use it
-------------
Basic usage is straight-forward:

```
kcov /path/to/outdir executable [args for the executable]
```

*/path/to/outdir* will contain lcov-style HTML output generated
_/path/to/outdir_ will contain lcov-style HTML output generated
continuously while the application runs. Kcov will also write cobertura-
compatible XML output and generic JSON coverage information and can easily
be integrated in various CI systems.

Filtering output
----------------
## Filtering output

It's often useful to filter output, since e.g., /usr/include is seldom of interest.
This can be done in two ways:

Expand All @@ -47,8 +95,8 @@ kcov --exclude-pattern=/usr/include --include-pattern=part/of/path,other/path \
```

which will do a string-comparison and include everything which contains
*part/of/path* or *other/path* but exclude everything that has the
*/usr/include* string in it.
_part/of/path_ or _other/path_ but exclude everything that has the
_/usr/include_ string in it.

```
kcov --include-path=/my/src/path /path/to/outdir executable
Expand All @@ -57,8 +105,8 @@ kcov --exclude-path=/usr/include /path/to/outdir executable

Does the same thing, but with proper path lookups.

Merging multiple kcov runs
--------------------------
## Merging multiple kcov runs

Kcov can also merge the results of multiple earlier runs. To use this mode,
call kcov with `--merge`, an output path and one or more paths to an earlier
run, e.g.,
Expand All @@ -68,20 +116,20 @@ kcov --merge /tmp/merged-output /tmp/kcov-output1 /tmp/kcov-output2
kcov --merge /tmp/merged-output /tmp/kcov-output* # With a wildcard
```

Use from continuous integration systems
---------------------------------------
## Use from continuous integration systems

kcov is easy to integrate with [travis-ci](http://travis-ci.org) together with
[coveralls.io](http://coveralls.io) or [codecov.io](http://codecov.io). It can also
be used from Jenkins, [SonarQube](http://sonarqube.org) and [GitLab CI](http://gitlab.com).
Refer to

* [coveralls](doc/coveralls.md) for details about travis-ci + coveralls, or
* [codecov](doc/codecov.md) for details about travis-ci + codecov
* [jenkins](doc/jenkins.md) for details about how to integrate in Jenkins
* [sonarqube](doc/sonarqube.md) for how to use kcov and sonarqube together
* [gitlab](doc/gitlab.md) for use with GitLab
- [coveralls](doc/coveralls.md) for details about travis-ci + coveralls, or
- [codecov](doc/codecov.md) for details about travis-ci + codecov
- [jenkins](doc/jenkins.md) for details about how to integrate in Jenkins
- [sonarqube](doc/sonarqube.md) for how to use kcov and sonarqube together
- [gitlab](doc/gitlab.md) for use with GitLab

## More information

More information
----------------
kcov is written by Simon Kagstrom <simon.kagstrom@gmail.com> and more
information can be found at [the web page](http://simonkagstrom.github.io/kcov/index.html)
Binary file added nocover/c-nocover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nocover/zig-panic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nocover/zig-unreachable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ set (${KCOV}_SRCS
writers/html-writer.cc
writers/sonarqube-xml-writer.cc
writers/writer-base.cc
writers/nocover.cc
${ELF_SRCS}
${MACHO_SRCS}
include/capabilities.hh
Expand Down
9 changes: 8 additions & 1 deletion src/writers/codecov-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class type_info;
#include <sstream>

#include "writer-base.hh"
#include "nocover.hh"

namespace kcov
{
Expand Down Expand Up @@ -134,6 +135,12 @@ class CodecovWriter : public WriterBase
IReporter::LineExecutionCount cnt = m_reporter.getLineExecutionCount(file->m_name, n);
std::string hitScore = "0";

std::string& line_str = file->m_lineMap.at(n);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kcov now builds with c++17, so you can use auto & for these.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it.

std::string& file_name = file->m_fileName;
if (!shouldCover(line_str, file_name)) {
continue;
}

if (m_maxPossibleHits == IFileParser::HITS_UNLIMITED || m_maxPossibleHits == IFileParser::HITS_SINGLE)
{
if (cnt.m_hits) {
Expand Down Expand Up @@ -167,7 +174,7 @@ class CodecovWriter : public WriterBase
linesBlock += "\n";


std::string out =
std::string out =
" \"" + filename + "\": {\n" +
linesBlock +
" }";
Expand Down
51 changes: 37 additions & 14 deletions src/writers/html-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <fstream>

#include "writer-base.hh"
#include "nocover.hh"

using namespace kcov;

Expand Down Expand Up @@ -72,6 +73,11 @@ class HtmlWriter : public WriterBase
"\"line\":\"", n);
outJson << escape_json(line) << "\"";

std::string& line_str = file->m_lineMap[n];
std::string& file_name = file->m_name;
bool should_cover = shouldCover(line_str, file_name);
const std::string& no_cover_class = "lineNoCov";

if (m_reporter.lineIsCode(file->m_name, n))
{
IReporter::LineExecutionCount cnt = m_reporter.getLineExecutionCount(file->m_name, n);
Expand All @@ -90,18 +96,21 @@ class HtmlWriter : public WriterBase
lineClass = "linePartCov";
}

outJson << fmt(",\"class\":\"%s\","
"\"hits\":\"%u\",", lineClass.c_str(), cnt.m_hits);

// Don't report order for zeroes
if (cnt.m_order)
outJson << fmt("\"order\":\"%llu\",", (unsigned long long) cnt.m_order);
if (lineClass == no_cover_class && !should_cover) {
// should not cover, so skip, but if there are some hits (when lineClass is not no cov), go else for normal marking
} else {
outJson << fmt(",\"class\":\"%s\","
"\"hits\":\"%u\",", lineClass.c_str(), cnt.m_hits);
// Don't report order for zeroes
if (cnt.m_order)
outJson << fmt("\"order\":\"%llu\",", (unsigned long long) cnt.m_order);

if (m_maxPossibleHits != IFileParser::HITS_SINGLE)
outJson << fmt("\"possible_hits\":\"%u\",", cnt.m_possibleHits);
if (m_maxPossibleHits != IFileParser::HITS_SINGLE)
outJson << fmt("\"possible_hits\":\"%u\",", cnt.m_possibleHits);

nExecutedLines += !!cnt.m_hits;
nCodeLines++;
nExecutedLines += !!cnt.m_hits;
nCodeLines++;
}
}
outJson << "},\n";

Expand Down Expand Up @@ -252,15 +261,29 @@ class HtmlWriter : public WriterBase
if (!res)
continue;

// since we may ignored some from previous individual writeOne functions for each file, here use the sum from
// files instead of summary
int inFilesTotalCodeLines = 0;
int inFilesTotalExecutedLines = 0;
for (FileMap_t::const_iterator it = m_files.begin(); it != m_files.end(); ++it)
{
inFilesTotalCodeLines += it->second->m_codeLines;
inFilesTotalExecutedLines += it->second->m_executedLines;
}

// Skip entries (merged ones) that shouldn't be included in the totals
if (summary.m_includeInTotals)
{
nTotalCodeLines += summary.m_lines;
nTotalExecutedLines += summary.m_executedLines;
nTotalCodeLines += inFilesTotalCodeLines;
nTotalExecutedLines += inFilesTotalExecutedLines;
// nTotalCodeLines += summary.m_lines;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the comment

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

// nTotalExecutedLines += summary.m_executedLines;
}

std::string datum = getIndexHeader(fmt("%s/index.html", de->d_name), name, name, summary.m_lines,
summary.m_executedLines);
std::string datum = getIndexHeader(fmt("%s/index.html", de->d_name), name, name, inFilesTotalCodeLines,
inFilesTotalExecutedLines);
// std::string datum = getIndexHeader(fmt("%s/index.html", de->d_name), name, name, summary.m_lines,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... also here

// summary.m_executedLines);

if (name == conf.keyAsString("merged-name"))
merged += datum;
Expand Down
18 changes: 14 additions & 4 deletions src/writers/json-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class type_info;
#include <fstream>

#include "writer-base.hh"
#include "nocover.hh"

using namespace kcov;

Expand Down Expand Up @@ -61,12 +62,21 @@ class JsonWriter : public WriterBase
for (unsigned int n = 1; n < file->m_lastLineNr; n++)
{
IReporter::LineExecutionCount cnt = m_reporter.getLineExecutionCount(file->m_name, n);

const std::string& line_str = file->m_lineMap[n];
const std::string& file_name = it->first;
bool should_cover = shouldCover(line_str, file_name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that all these can probably be moved to reporter.cc instead, to the lineIsCode method. I.e., you could do something like shouldCover(...) && it->second->lineIsCode(...) there, and then you can probably remove all changes to the writers.

At least it's something to try out.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good suggestion, will do


if (m_reporter.lineIsCode(file->m_name, n))
{
nExecutedLines += !!cnt.m_hits;
nCodeLines++;
nTotalExecutedLines += !!cnt.m_hits;
nTotalCodeLines++;
if (should_cover) {
nExecutedLines += !!cnt.m_hits;
nCodeLines++;
nTotalExecutedLines += !!cnt.m_hits;
nTotalCodeLines++;
} else {
// skip this from counting
}
}
}
if (nCodeLines > 0)
Expand Down
Loading
Loading