Skip to content
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
97 changes: 97 additions & 0 deletions .github/workflows/code_coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Unit Tests and Code Coverage

on:
push:
branches: [ "main" ]

workflow_dispatch:

jobs:
build:
runs-on: ubuntu-22.04
# 22 has gcc 11 and clang 14
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get install -y cmake ninja-build \
libxrandr-dev libxinerama-dev \
libxcursor-dev libxi-dev libgl1-mesa-dev \
gcovr lcov

# Do we need a very modern compiler?
# - name: Install clang18
# run: |
# wget https://apt.llvm.org/llvm.sh
# chmod a+x llvm.sh
# echo ""|sudo ./llvm.sh 18

- name: Create build directory
run: |
mkdir build
du -hs build

# This can be used to login to the runner and debug
# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3

- name: Configure CMake
run: |
# The following settings are needed for clang-18
#export CC=/usr/bin/clang-18
#export CXX=/usr/bin/clang++-18
#export CXXFLAGS="-std=c++20"
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DENABLE_GEOM2D_UNIT_TESTS=ON \
-DBUILD_GMOCK=OFF \
-DINSTALL_GTEST=OFF

- name: Build with Ninja
run: ninja -C build

- name: Run tests
run: |
ninja -C build test

- name: Configure lcov to capture branch coverage
run: |
cp /etc/lcovrc /dev/shm
cat /dev/shm/lcovrc |sed 's/branch_coverage = 0/branch_coverage = 1/g' > ~/.lcovrc

- name: Collect coverage
run: |
ninja -C build cov

# The following article describes how to publish code coverage to codecov.io:
# https://dev.to/askrodney/cmake-coverage-example-with-github-actions-and-codecovio-5bjp
# I can't get it to work, though. We can just download the html, for now.
# - name: Generate JSON coverage report
# working-directory: ./build
# run: |
# gcovr -r .. . --branches --cobertura > coverage.xml

- name: Upload build artifact
uses: actions/upload-artifact@v3
with:
name: TEST_Geometry2D_linux_amd64_artifact1
path: build/bin/TEST_Geometry2D

- name: Publish coverage artifact
uses: actions/upload-artifact@v3
with:
name: code-coverage
path: build/coverage


# - name: Upload Release Asset
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing its `id`
# asset_path: ./build/ryzen_mon_glgui
# asset_name: ryzen_mon_glgui_artifact1.zip # Name of the asset to display on the release page
# asset_content_type: application/zip
40 changes: 40 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,43 @@ if (EXISTS "${CMAKE_SOURCE_DIR}/${C_CXX_HEADERS_DIR}" AND IS_DIRECTORY "${CMAKE_
endif (EXISTS "${CMAKE_SOURCE_DIR}/${C_CXX_HEADERS_DIR}" AND IS_DIRECTORY "${CMAKE_SOURCE_DIR}/${C_CXX_HEADERS_DIR}")

include_directories("${CMAKE_SOURCE_DIR}/third_party")


# Define an option to enable/disable unit tests
option(ENABLE_GEOM2D_UNIT_TESTS "Enable unit tests for /olcUTIL_Geometry2D" OFF)

# unit tests
# I use this with: cmake -G Ninja -DBUILD_GMOCK=OFF -DINSTALL_GTEST=OFF -DENABLE_GEOM2D_UNIT_TESTS=ON ..
if(ENABLE_GEOM2D_UNIT_TESTS)
enable_testing()

# Code Coverage
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake")
include(coverage)
# the following pattern excludes all tests from coverage report
add_coverage_target("*/tests/*")

# Fetch Google Test
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
FetchContent_MakeAvailable(googletest)

add_executable(unit_tests
tests/test_circle.cpp # TODO: use cmake to find all test files
)

# Disable optimization for coverage
# TODO: only tested with gcc
target_compile_options(unit_tests PRIVATE
-O0 -fprofile-arcs -ftest-coverage --coverage
)
target_link_options(unit_tests PRIVATE --coverage)

target_link_libraries(unit_tests gtest_main)

add_test(NAME unit_tests COMMAND unit_tests)
endif()
51 changes: 51 additions & 0 deletions cmake/coverage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function(add_coverage_target exclude)

find_program(GCOV gcov)
if (NOT GCOV)
message(WARNING "program gcov not found")
endif()

find_program(LCOV lcov)
if (NOT LCOV)
message(WARNING "program lcov not found")
endif()

find_program(GENHTML genhtml)
if (NOT GENHTML)
message(WARNING "program genhtml not found")
endif()

if (LCOV AND GCOV AND GENHTML)
# the following link describes how to write unit tests for header only libraries
# https://stackoverflow.com/questions/9666800/getting-useful-gcov-results-for-header-only-libraries
set(covname cov.info)
# the original file set all compile options here, but I prefer to set them in the CMakeLists.txt
#add_compile_options(-fprofile-arcs -ftest-coverage)
#add_link_options(--coverage)
add_custom_target(cov DEPENDS ${covname})

# lcov on ubuntu 22 doesn't support --branch-coverage
set(COV_OPT
"" # i modify /etc/lcovrc in the github action
#"--branch-coverage"
#"--rc lcov_branch_coverage=1" # this doesn't work with -l option
)
# option for genhtml --rc genhtml_branch_coverage=1

add_custom_command(
OUTPUT ${covname}
COMMAND ${LCOV} -c -o ${covname} ${COV_OPT} -d . -b . --gcov-tool ${GCOV} #--ignore-errors mismatch
# In the following I explicitly exclude system headers from the coverage report
COMMAND ${LCOV} -r ${covname} ${COV_OPT} -o ${covname} ${exclude} "\*/googletest/\*" "\*/g++\*/bits/\*" "'*/g++-v13/*'"
COMMAND ${LCOV} -l ${covname} ${COV_OPT}
COMMAND ${GENHTML} ${covname} --rc lcov_branch_coverage=1 -output coverage
COMMAND ${LCOV} -l ${covname} ${COV_OPT} 2>/dev/null | grep Total | sed 's/|//g' | sed 's/Total://g' | awk '{print $1}' | sed s/%//g > coverage/total
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES ${covname}
)
else()
message(WARNING "unable to add target `cov`: missing coverage tools")
endif()

endfunction()
54 changes: 54 additions & 0 deletions tests/test_circle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <gtest/gtest.h>
#include "../olcUTIL_Geometry2D.h"

using namespace olc::utils::geom2d;

class CircleTest : public ::testing::Test
{
protected:
void SetUp() override
{
// Initialize the circle
c = circle<float>({{0.0f, 0.0f}, 10.0f});
}

circle<float> c;
};

// The test name consists of the module that is tested, the scenario under which it is tested and the expected behavior

TEST_F(CircleTest, circle_contains_PointOnCircleBoundary_True)
{
// Create a point on the circle boundary
olc::v_2d<float> p(0.0f, 10.0f);

// Check if the circle contains the point
bool result = contains(c, p);

// Assert that the result is true
ASSERT_TRUE(result);
}

TEST_F(CircleTest, circleContains_PointIsInside_True)
{
// Create a point inside the circle
olc::v_2d<float> p(1.0f, 1.0f);

// Check if the circle contains the point
bool result = contains(c, p);

// Assert that the result is true
ASSERT_TRUE(result);
}

TEST_F(CircleTest, circleContains_PointIsOutside_False)
{
// Create a point outside the circle
olc::v_2d<float> p(12.0f, 12.0f);

// Check if the circle contains the point
bool result = contains(c, p);

// Assert that the result is false
ASSERT_FALSE(result);
}