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

feat(kcov): add code coverage support for tests + fuzzers #193

Merged
merged 32 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a55af06
Facilitate cheap zls build-on-save diagnostics
InKryption Jul 5, 2024
c24e842
add kcov functionality and update fuzz testing code
0xNineteen Jul 10, 2024
d313c91
Merge branch 'main' of https://github.com/Syndica/sig into 19/kcov
0xNineteen Jul 10, 2024
becfee9
fit formatting
0xNineteen Jul 10, 2024
44b64b8
polish up fuzz code
0xNineteen Jul 10, 2024
370b897
ci test
0xNineteen Jul 11, 2024
16945d3
fix yaml syntax
0xNineteen Jul 11, 2024
bfd9913
update deps
0xNineteen Jul 11, 2024
a3c4c2f
add zig deps
0xNineteen Jul 11, 2024
2b79b6e
update script to not fail if open fails
0xNineteen Jul 11, 2024
c78a94d
fix paths
0xNineteen Jul 11, 2024
2b4c9be
sort based on percentage covered
0xNineteen Jul 11, 2024
13247b6
remove test branch from action
0xNineteen Jul 11, 2024
a57378f
improv(gossip,accountsdb): improve test coverage on important methods…
0xNineteen Jul 15, 2024
2207b60
feat(gossip): add GossipTable fuzz testing (#197)
0xNineteen Jul 15, 2024
48acc97
Merge branch 'main' of https://github.com/Syndica/sig into 19/kcov
0xNineteen Jul 15, 2024
6164dab
fix lint
0xNineteen Jul 15, 2024
faf8588
test fix
0xNineteen Jul 16, 2024
73f56be
fix unnecessary var
0xNineteen Jul 16, 2024
308f629
fix table fuzzing bug
0xNineteen Jul 16, 2024
4af13ce
remove double returns
0xNineteen Jul 16, 2024
1ddc1eb
fix action switch in fuzz
0xNineteen Jul 16, 2024
3adcaa5
remove else prong
0xNineteen Jul 16, 2024
35ecaac
change to random enum value
0xNineteen Jul 16, 2024
acb760d
change null check format
0xNineteen Jul 16, 2024
f071623
update loop iter
0xNineteen Jul 16, 2024
15d8581
Merge branch 'main' of https://github.com/Syndica/sig into 19/kcov
0xNineteen Jul 16, 2024
11ed538
move buf closer to its usage
0xNineteen Jul 17, 2024
eb28c8e
address ink comments
0xNineteen Jul 17, 2024
fa29308
Merge branch 'main' of https://github.com/Syndica/sig into 19/kcov
0xNineteen Jul 17, 2024
889f988
address yewman comments
0xNineteen Jul 17, 2024
3e84738
update duration comments
0xNineteen Jul 17, 2024
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
38 changes: 38 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ jobs:
- name: test
run: zig build test

kcov_test:
strategy:
matrix:
os: [ubuntu-latest]
runs-on: ${{matrix.os}}
steps:
- name: checkout
uses: actions/checkout@v2
with:
submodules: recursive

- name: setup-zig
uses: goto-bus-stop/setup-zig@v1
with:
version: 0.13.0

- name: Set up dependencies
run: sudo apt-get update

- name: Install kcov
run: |
sudo apt-get install -y binutils-dev libssl-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev
git clone https://github.com/SimonKagstrom/kcov.git
cd kcov
mkdir build
cd build
cmake ..
make
sudo make install

- name: Run kcov
run: |
bash scripts/kcov_test.sh

- name: Print coverage report
run: |
python parse_kcov.py kcov-output/test/coverage.json

benchmarks:
strategy:
matrix:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ zig-out/
data/

index_storage/
kcov-output

/gossip-dumps

Expand Down
14 changes: 14 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/zig-out/bin/test",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "zig build"
}
]
}
13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "zig build",
"type": "shell",
"command": "zig",
"args": [
"build"
],
}
]
}
79 changes: 79 additions & 0 deletions docs/fuzzing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# fuzzing documentation

supported components:
- gossip
- accountsdb

main code paths:
- `fuzz.zig` <- main entrypoint
- `gossip/fuzz_table.zig`
- `gossip/fuzz_service.zig`
- `accountsdb/fuzz.zig`
- `scripts/` <- kcov + fuzz bash scripts

kcov will give you coverage information on what was and was not fuzzed
- [https://github.com/SimonKagstrom/kcov](https://github.com/SimonKagstrom/kcov)

*note:* view the full script for helpful install instructions

![](imgs/2024-07-10-09-39-25.png)

![](imgs/2024-07-10-09-39-57.png)

## gossip

### service

gossip supports two types of fuzzing
- *option1*: sending fuzz packets to an arbitrary endpoint
- *option2*: sending fuzz packets directly to a sig client

![](imgs/2024-07-10-09-33-37.png)

example commands:
```bash
# <seed> <n_messages> <to_endpoint> (option1)
./zig-out/bin/fuzz gossip_service 10 4_000 127.0.0.1:8001

# <seed> <n_messages> (option2)
./zig-out/bin/fuzz gossip_service 10 4_000

# (run with random seed for inf)
./zig-out/bin/fuzz gossip_service
```

### table

you can also fuzz the `GossipTable` (see `src/gossip/table.zig`) for reads/writes/trims/remove-old-labels using the following:

example commands:
```bash
# <seed> <n_messages>
./zig-out/bin/fuzz gossip_table 10 4_000

# (run with random seed for inf)
./zig-out/bin/fuzz gossip_table
```

## accounts-db

the fuzzer does a few things
- runs the manager loop which flushes/cleans/shrinks/deletes account files in one thread
- another thread reads/writes accounts and verifies the data read is correct

the goal was to makes sure accounts-db was thread-safe for parallel access while also flushing/cleaning/purging

example command:
```bash
# <seed> <n_messages>
./zig-out/bin/fuzz accountsdb 10 4_000
# (run with random seed for inf)
./zig-out/bin/fuzz accountsdb
```

## running with kcov

commands to run:
- `bash scripts/kcov_fuzz_gossip_service.sh`
- `bash scripts/kcov_fuzz_gossip_table.sh`
- `bash scripts/kcov_fuzz_accountsdb.sh`
Binary file added docs/imgs/2024-07-10-09-33-37.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 docs/imgs/2024-07-10-09-39-25.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 docs/imgs/2024-07-10-09-39-57.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions parse_kcov.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json

# read path from cli
import sys
if len(sys.argv) != 2:
print("Usage: python parse_kcov.py <path_to_coverage.json>")
sys.exit(1)
coverage_path = sys.argv[1]

with open(coverage_path, "r") as f:
coverage = json.load(f)

max_path_length = max(len(file_info["file"]) for file_info in coverage["files"])

# order by coverage percentage
coverage["files"].sort(key=lambda x: float(x["percent_covered"]), reverse=False)

output = ""
for file_info in coverage["files"]:
path = file_info["file"]
path = path.split("sig/")[2]
file_coverage = float(file_info["percent_covered"])

# Determine the color based on the coverage percentage
if file_coverage < 50:
color = "\033[91m" # Red
elif file_coverage < 75:
color = "\033[93m" # Yellow
else:
color = "\033[92m" # Green

# Reset color
reset = "\033[0m"
output += f"{color}{path:<{max_path_length}} --- {file_coverage:>10}%{reset}\n"

print(output)
31 changes: 31 additions & 0 deletions scripts/kcov_fuzz_accountsdb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# to install kcov follow the instructions at:
# https://github.com/SimonKagstrom/kcov/blob/master/INSTALL.md
# to build on mac the following should work:
# ```
# cd /path/to/kcov/
# mkdir build
# cd build
# cmake ..
# make
# make install
# export PATH=$PATH:/path/to/kcov/build/src
# ```

echo "=> Clearing kcov-output directory"
rm -rf kcov-output
mkdir kcov-output

echo "=> Building Sig"
zig build

echo "=> Running kcov on accountsdb"
kcov \
--include-pattern=src/accountsdb/ \
# not sure why this is necessary with --include-pattern but it is
--exclude-pattern=$HOME/.cache \
kcov-output/ \
./zig-out/bin/fuzz accountsdb

# open report
echo "=> Opening kcov-output/index.html"
open kcov-output/index.html
30 changes: 30 additions & 0 deletions scripts/kcov_fuzz_gossip.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# to install kcov follow the instructions at:
# https://github.com/SimonKagstrom/kcov/blob/master/INSTALL.md
# to build on mac the following should work:
# ```
# cd /path/to/kcov/
# mkdir build
# cd build
# cmake ..
# make
# make install
# export PATH=$PATH:/path/to/kcov/build/src
# ```

echo "=> Clearing kcov-output directory"
rm -rf kcov-output
mkdir kcov-output

echo "=> Building Sig"
zig build

echo "=> Running kcov on gossip spy"
kcov \
--include-pattern=src/gossip/ \
--exclude-pattern=$HOME/.cache \
kcov-output/ \
./zig-out/bin/fuzz gossip_service 19 50_000

# open report
echo "=> Opening kcov-output/index.html"
open kcov-output/index.html
30 changes: 30 additions & 0 deletions scripts/kcov_fuzz_gossip_table.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# to install kcov follow the instructions at:
# https://github.com/SimonKagstrom/kcov/blob/master/INSTALL.md
# to build on mac the following should work:
# ```
# cd /path/to/kcov/
# mkdir build
# cd build
# cmake ..
# make
# make install
# export PATH=$PATH:/path/to/kcov/build/src
# ```

echo "=> Clearing kcov-output directory"
rm -rf kcov-output
mkdir kcov-output

echo "=> Building Sig"
zig build

echo "=> Running kcov on gossip spy"
kcov \
--include-pattern=src/gossip/ \
--exclude-pattern=$HOME/.cache \
kcov-output/ \
./zig-out/bin/fuzz gossip_table 19 50_000

# open report
echo "=> Opening kcov-output/index.html"
open kcov-output/index.html
29 changes: 29 additions & 0 deletions scripts/kcov_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# to install kcov follow the instructions at:
# https://github.com/SimonKagstrom/kcov/blob/master/INSTALL.md
# to build on mac the following should work:
# ```
# cd /path/to/kcov/
# mkdir build
# cd build
# cmake ..
# make
# make install
# export PATH=$PATH:/path/to/kcov/build/src
# ```

echo "=> Cleaning up"
rm -rf kcov-output
mkdir kcov-output

echo "=> Building Sig"
zig build

echo "=> Running kcov on tests"
kcov \
--include-pattern=src/ \
--exclude-pattern=$HOME/.cache \
kcov-output \
./zig-out/bin/test

echo "=> Opening kcov-output/index.html"
open kcov-output/index.html || echo "=> Failed to open kcov-output/index.html"
Loading
Loading