Skip to content

Commit 82dfbeb

Browse files
committed
add unit-tests
1 parent e7869b7 commit 82dfbeb

File tree

3 files changed

+140
-8
lines changed

3 files changed

+140
-8
lines changed

.devcontainer/devcontainer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"--privileged",
2121
"--device",
2222
"/dev/bus/usb:/dev/bus/usb",
23-
"--device=/dev/ttyUSB0:/dev/ttyUSB0",
24-
"--group-add=dialout"
23+
"--device-cgroup-rule=c 188:* rwm",
24+
"--device-cgroup-rule=c 166:* rwm",
25+
"--group-add=dialout",
26+
"--volume=/dev/serial/by-id:/dev/serial/by-id:ro"
2527
]
2628
}

CMakeLists.txt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,28 @@ set_target_properties(${PROJECT_N} PROPERTIES
7878

7979
target_include_directories(${PROJECT_N} PUBLIC ${PROJECT_SOURCE_DIR}/src)
8080

81-
add_executable(serial_tests tests/serial_test.cpp)
82-
target_link_libraries(serial_tests PRIVATE ${PROJECT_N} gtest_main)
81+
add_executable(serial_integration_tests tests/serial_test.cpp)
82+
target_link_libraries(serial_integration_tests PRIVATE ${PROJECT_N} gtest_main)
8383

84-
target_include_directories(serial_tests PRIVATE ${PROJECT_SOURCE_DIR}/src)
84+
target_include_directories(serial_integration_tests PRIVATE ${PROJECT_SOURCE_DIR}/src)
8585

86-
add_custom_command(TARGET serial_tests POST_BUILD
86+
add_custom_command(TARGET serial_integration_tests POST_BUILD
8787
COMMAND ${CMAKE_COMMAND} -E copy_if_different
8888
$<TARGET_FILE:${PROJECT_N}>
89-
$<TARGET_FILE_DIR:serial_tests>
89+
$<TARGET_FILE_DIR:serial_integration_tests>
9090
COMMENT "Copy shared library next to test binary")
9191

92+
# Unit test target covering additional API aspects
93+
add_executable(serial_unit_tests tests/serial_unit_tests.cpp)
94+
target_link_libraries(serial_unit_tests PRIVATE ${PROJECT_N} gtest_main)
95+
target_include_directories(serial_unit_tests PRIVATE ${PROJECT_SOURCE_DIR}/src)
96+
97+
add_custom_command(TARGET serial_unit_tests POST_BUILD
98+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
99+
$<TARGET_FILE:${PROJECT_N}>
100+
$<TARGET_FILE_DIR:serial_unit_tests>
101+
COMMENT "Copy shared library next to unit test binary")
102+
92103
enable_testing()
93-
add_test(NAME SerialEchoTest COMMAND serial_tests /dev/ttyUSB0)
104+
add_test(NAME SerialEchoTest COMMAND serial_integration_tests /dev/ttyUSB0)
105+
add_test(NAME SerialUnitTests COMMAND serial_unit_tests)

tests/serial_unit_tests.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include "serial.h"
2+
#include "status_codes.h"
3+
4+
#include <atomic>
5+
#include <cstring>
6+
#include <gtest/gtest.h>
7+
#include <iostream>
8+
9+
namespace
10+
{
11+
// Helper storage for callback tests
12+
std::atomic<int>* g_err_ptr = nullptr;
13+
14+
void errorCallback(int code)
15+
{
16+
if (g_err_ptr != nullptr)
17+
{
18+
*g_err_ptr = code;
19+
}
20+
}
21+
} // namespace
22+
23+
// ------------------------------- Error path --------------------------------
24+
TEST(SerialOpenTest, InvalidPathInvokesErrorCallback)
25+
{
26+
std::atomic<int> err_code{0};
27+
28+
g_err_ptr = &err_code;
29+
serialOnError(errorCallback);
30+
31+
intptr_t handle = serialOpen((void*)"/dev/__does_not_exist__", 115200, 8, 0, 0);
32+
EXPECT_EQ(handle, 0);
33+
EXPECT_EQ(err_code.load(), static_cast<int>(StatusCodes::INVALID_HANDLE_ERROR));
34+
35+
// Reset to nullptr so other tests don't see our callback
36+
serialOnError(nullptr);
37+
}
38+
39+
// ------------------------ serialGetPortsInfo checks ------------------------
40+
TEST(SerialGetPortsInfoTest, BufferTooSmallTriggersError)
41+
{
42+
char sep[] = ";";
43+
char buffer[4];
44+
std::atomic<int> err_code{0};
45+
46+
g_err_ptr = &err_code;
47+
serialOnError(errorCallback);
48+
49+
int res = serialGetPortsInfo(buffer, sizeof(buffer), sep);
50+
EXPECT_EQ(res, 0); // function indicates failure via 0
51+
EXPECT_EQ(err_code.load(), static_cast<int>(StatusCodes::BUFFER_ERROR));
52+
53+
serialOnError(nullptr);
54+
}
55+
56+
TEST(SerialGetPortsInfoTest, LargeBufferReturnsZeroOrOne)
57+
{
58+
char sep[] = ";";
59+
char buffer[4096] = {0};
60+
61+
std::atomic<int> err_code{0};
62+
g_err_ptr = &err_code;
63+
serialOnError(errorCallback);
64+
65+
int res = serialGetPortsInfo(buffer, sizeof(buffer), sep);
66+
EXPECT_GE(res, 0);
67+
// res is 0 (no ports) or 1 (ports found)
68+
EXPECT_LE(res, 1);
69+
// Acceptable error codes: none or NOT_FOUND_ERROR (e.g., dir missing)
70+
if (err_code != 0)
71+
{
72+
EXPECT_EQ(err_code.load(), static_cast<int>(StatusCodes::NOT_FOUND_ERROR));
73+
}
74+
75+
serialOnError(nullptr);
76+
}
77+
78+
// ---------------------------- Port listing helper ---------------------------
79+
TEST(SerialGetPortsInfoTest, PrintAvailablePorts)
80+
{
81+
char sep[] = ";";
82+
char buffer[4096] = {0};
83+
84+
int res = serialGetPortsInfo(buffer, sizeof(buffer), sep);
85+
EXPECT_GE(res, 0);
86+
87+
std::string ports_str(buffer);
88+
if (!ports_str.empty())
89+
{
90+
std::cout << "\nAvailable serial ports (by-id):\n";
91+
size_t start = 0;
92+
while (true)
93+
{
94+
size_t pos = ports_str.find(sep, start);
95+
std::string token = ports_str.substr(start, pos - start);
96+
std::cout << " " << token << "\n";
97+
if (pos == std::string::npos)
98+
{
99+
break;
100+
}
101+
start = pos + std::strlen(sep);
102+
}
103+
}
104+
else
105+
{
106+
std::cout << "\nNo serial devices found in /dev/serial/by-id\n";
107+
}
108+
}
109+
110+
// --------------------------- Stubbed no-op APIs ----------------------------
111+
TEST(SerialStubbedFunctions, DoNotCrash)
112+
{
113+
serialClearBufferIn(0);
114+
serialClearBufferOut(0);
115+
serialAbortRead(0);
116+
serialAbortWrite(0);
117+
SUCCEED(); // reached here without segfaults
118+
}

0 commit comments

Comments
 (0)