Skip to content

Commit 2f3b571

Browse files
author
pfeatherstone
committed
coverage WIP
1 parent 9f72729 commit 2f3b571

File tree

5 files changed

+88
-2
lines changed

5 files changed

+88
-2
lines changed

.github/workflows/coverage.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Coverage
2+
on:
3+
push:
4+
branches:
5+
- '**'
6+
pull_request:
7+
branches:
8+
- '**'
9+
10+
jobs:
11+
build-test:
12+
runs-on: ubuntu-24.04
13+
name: ubuntu-coverage
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Install dependencies
19+
run: |
20+
sudo apt update
21+
sudo apt install -y ninja-build cmake clang llvm
22+
23+
- name: Run CMake configuration and build
24+
run: |
25+
cmake examples -B build -G Ninja \
26+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
27+
-DCMAKE_C_COMPILER=clang \
28+
-DCMAKE_CXX_COMPILER=clang++ \
29+
-DHTTP_BUILD_FUZZERS=ON
30+
cmake --build build --target request_parser --parallel
31+
32+
- name: Extract corpus
33+
run: |
34+
35+
- name: Run fuzzers
36+
run: |
37+
./build/RelWithDebInfo/request_parser /tmp/corpus/ examples/fuzz/seeds/request_parser/ -max_total_time=30
38+
39+
- name: Generate coverage report
40+
run: |
41+
llvm-profdata merge -sparse default.profraw -o default.profdata
42+
llvm-cov show ./build/RelWithDebInfo/request_parser \
43+
-instr-profile=default.profdata \
44+
-format=html \
45+
-output-dir=coverage-report
46+
47+
- name: Upload coverage report as artifact
48+
uses: actions/upload-artifact@v3
49+
with:
50+
name: coverage-report
51+
path: coverage-report

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
**/build
2-
**/.vscode
2+
**/.vscode
3+
**/default.profraw
4+
**/default.profdata
5+
**/fuzzer.profdata

examples/CMakeLists.txt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
cmake_minimum_required(VERSION 3.13)
22
project(Http)
33

4+
# Helpers
5+
set(IS_CLANG "$<CXX_COMPILER_ID:Clang>")
6+
47
# Deps
58
include(FetchContent)
69
find_package(Threads REQUIRED)
@@ -17,11 +20,15 @@ FetchContent_Declare(
1720
URL_HASH MD5=3edffaacd2cfe63c240ef1b99497c74f)
1821
FetchContent_MakeAvailable(Boost)
1922

23+
# Options
24+
option(HTTP_BUILD_FUZZERS "Builds Fuzz tests (requires clang)" OFF)
25+
2026
# Lib
2127
add_library(http ${CMAKE_CURRENT_SOURCE_DIR}/../src/http.cpp)
2228
target_compile_features(http PUBLIC cxx_std_17)
2329
target_include_directories(http PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../src)
2430
target_link_libraries(http PUBLIC OpenSSL::SSL OpenSSL::Crypto Boost::asio)
31+
target_compile_options(http PRIVATE $<$<AND:${IS_CLANG},$<BOOL:${HTTP_BUILD_FUZZERS}>>:-fprofile-instr-generate -fcoverage-mapping>)
2532

2633
# Examples
2734
function(add_executable_20 target_name)
@@ -54,4 +61,16 @@ add_executable(tests
5461
target_compile_features(tests PUBLIC cxx_std_20)
5562
target_link_options(tests PRIVATE $<$<CONFIG:Release>:-s>)
5663
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/extra)
57-
target_link_libraries(tests PRIVATE http)
64+
target_link_libraries(tests PRIVATE http)
65+
66+
# Fuzz tests
67+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND HTTP_BUILD_FUZZERS)
68+
function(add_fuzz target_name)
69+
add_executable(${target_name} ${ARGN})
70+
target_link_libraries(${target_name} PRIVATE http)
71+
target_compile_options(${target_name} PRIVATE -fprofile-instr-generate -fcoverage-mapping)
72+
target_link_options(${target_name} PRIVATE -fsanitize=fuzzer -fprofile-instr-generate -fcoverage-mapping)
73+
endfunction()
74+
75+
add_fuzz(request_parser fuzz/request_parser.cpp)
76+
endif()

examples/fuzz/request_parser.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <cstdint>
2+
#include <cstddef>
3+
#include <http.h>
4+
5+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
6+
{
7+
std::string buf(reinterpret_cast<const char*>(data), size);
8+
http::request req{};
9+
std::error_code ec{};
10+
http::parser<http::request> parser;
11+
parser.parse(req, buf, ec);
12+
return 0;
13+
}

examples/fuzz/seeds.tgz

863 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)