Skip to content

Commit bf0443f

Browse files
Fix issue #17 + add unit tests (#18)
* Add unit tests * Fix #17
2 parents cc6a701 + 76672d4 commit bf0443f

File tree

5 files changed

+178
-1
lines changed

5 files changed

+178
-1
lines changed

.github/workflows/ut.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Unit tests
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v3
15+
16+
- name: Set up dependencies
17+
run: |
18+
sudo apt-get update
19+
sudo apt-get install -y cmake build-essential
20+
21+
- name: Configure CMake
22+
run: |
23+
cmake -Bbuild -DTEST_ENABLED=ON -DSAMPLE_ENABLED=ON .
24+
25+
- name: Build project
26+
run: |
27+
cmake --build build
28+
29+
- name: Run unit tests
30+
run: |
31+
./build/tests/uprof-tests --reporter JUnit::out=test-results.xml --reporter console::out=-::colour-mode=ansi --success
32+
33+
- name: Test report
34+
uses: dorny/test-reporter@v2
35+
if: ${{ !cancelled() }}
36+
with:
37+
name: Unit Tests
38+
path: test-results.xml
39+
reporter: java-junit

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
33

44
OPTION(PROFILE_ENABLED "Whether library performs profiling operations or does nothing" ON)
55
OPTION(SAMPLE_ENABLED "Whether sample binary is built or not" OFF)
6+
OPTION(TEST_ENABLED "Whether unit tests binary is built or not" OFF)
67
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
78
OPTION(GPU_MONITOR_NVIDIA "Whether NVidiaMonitor class for monitoring NVidia GPUs is compiled and embedded to the library" OFF)
89

@@ -11,3 +12,7 @@ ADD_SUBDIRECTORY(lib)
1112
IF(SAMPLE_ENABLED)
1213
ADD_SUBDIRECTORY(sample)
1314
ENDIF()
15+
16+
IF(TEST_ENABLED)
17+
ADD_SUBDIRECTORY(tests)
18+
ENDIF()

lib/eventsfile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ void EventsFile::write(const std::string& event, unsigned long long timestamp, c
5656
string line = ss.str();
5757

5858
// Total size of all rotating files should never exceed the defined max cap size
59+
std::lock_guard<std::mutex> guard(m_fileMutex);
5960
if (m_maxCapSize > 0 && m_currentFileSize + line.size() > m_maxCapSize / ROTATING_FILES_NUMBER) {
6061
rotateFile();
6162
}
6263

63-
std::lock_guard<std::mutex> guard(m_fileMutex);
6464
m_file << line;
6565
m_file.flush();
6666
m_currentFileSize += line.size();

tests/CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
PROJECT(uprof-tests DESCRIPTION "Unit tests")
2+
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
3+
4+
SET( CMAKE_USE_RELATIVE_PATHS ON)
5+
6+
INCLUDE(FetchContent)
7+
8+
FETCHCONTENT_DECLARE(
9+
Catch2
10+
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
11+
GIT_TAG v3.8.1 # or a later release
12+
)
13+
14+
FETCHCONTENT_MAKEAVAILABLE(Catch2)
15+
16+
LIST(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
17+
INCLUDE(CTest)
18+
INCLUDE(Catch)
19+
20+
ADD_EXECUTABLE(${PROJECT_NAME}
21+
test.cpp
22+
)
23+
24+
target_link_libraries(${PROJECT_NAME}
25+
Catch2::Catch2WithMain
26+
cppuprofile
27+
)

tests/test.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Software Name : cppuprofile
2+
// SPDX-FileCopyrightText: Copyright (c) 2025 Orange
3+
// SPDX-License-Identifier: BSD-3-Clause
4+
//
5+
// This software is distributed under the BSD License;
6+
// see the LICENSE file for more details.
7+
//
8+
// Author: Cédric CHEDALEUX <cedric.chedaleux@orange.com> et al
9+
10+
#include <catch2/catch_test_macros.hpp>
11+
#include <unistd.h>
12+
#include <uprofile.h>
13+
14+
static const std::string filename = "./test.log";
15+
16+
bool fileExists(const std::string& filename) {
17+
std::ifstream file(filename);
18+
return file.is_open();
19+
}
20+
21+
int fileSize(const std::string& filename) {
22+
std::ifstream file(filename, std::ios::binary | std::ios::ate);
23+
if (!file.good()) return 0;
24+
return file.tellg();
25+
}
26+
27+
TEST_CASE("Uprofile instant metrics", "[instant]")
28+
{
29+
uprofile::start(filename.c_str());
30+
31+
SECTION("Instant CPU Usage")
32+
{
33+
std::vector<float> loads = uprofile::getInstantCpuUsage();
34+
for (auto it = loads.cbegin(); it != loads.cend(); ++it) {
35+
REQUIRE(*it >= 0.);
36+
REQUIRE(*it <= 100.0);
37+
}
38+
}
39+
40+
SECTION("No update in the file")
41+
{
42+
std::ifstream file(filename, std::ios::binary | std::ios::ate);
43+
REQUIRE(file.good());
44+
REQUIRE(file.tellg() == 0);
45+
file.close();
46+
sleep(1);
47+
file.open(filename, std::ios::binary | std::ios::ate);
48+
REQUIRE(file.tellg() == 0);
49+
}
50+
51+
uprofile::stop();
52+
std::remove(filename.c_str());
53+
}
54+
55+
TEST_CASE("Uprofile monitoring metrics", "[monitoring]")
56+
{
57+
uprofile::start(filename.c_str());
58+
uprofile::startCPUUsageMonitoring(200);
59+
SECTION("File existency")
60+
{
61+
REQUIRE( fileExists(filename) );
62+
}
63+
64+
SECTION("File update")
65+
{
66+
// Check that the file grows over time
67+
auto size = fileSize(filename);
68+
sleep(1);
69+
REQUIRE(fileSize(filename) > size);
70+
}
71+
uprofile::stop();
72+
std::remove(filename.c_str());
73+
}
74+
75+
TEST_CASE("Uprofile rotating files", "[rotation]")
76+
{
77+
// The two rotating files will have a maximum of 100 bytes in total
78+
int maxSize = 100; // bytes
79+
uprofile::start(filename.c_str(), maxSize);
80+
81+
// Enable all monitoring to stress the library
82+
uprofile::startCPUUsageMonitoring(50);
83+
uprofile::startSystemMemoryMonitoring(50);
84+
uprofile::startProcessMemoryMonitoring(50);
85+
86+
size_t pos = filename.rfind('.');
87+
std::string file1 = filename;
88+
std::string file2 = filename;
89+
file1.insert(pos,"_0");
90+
file2.insert(pos,"_1");
91+
92+
SECTION("Two rotating files")
93+
{
94+
// Wait a couple of seconds to have several rotations
95+
sleep(2);
96+
REQUIRE( fileExists(file1) );
97+
REQUIRE( fileExists(file2) );
98+
99+
// Check total size does not exceed the limit
100+
REQUIRE (fileSize(file1) + fileSize(file2) < maxSize);
101+
}
102+
103+
uprofile::stop();
104+
std::remove(file1.c_str());
105+
std::remove(file2.c_str());
106+
}

0 commit comments

Comments
 (0)