Skip to content

Commit 6227c77

Browse files
committed
feat: split v3 tests
1 parent d0ff917 commit 6227c77

15 files changed

Lines changed: 391 additions & 199 deletions

‎CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ if(CPP_BINDINGS_LINUX_STATIC_CXX_RUNTIME)
230230
)
231231
endif()
232232

233-
file(GLOB SRC_UNIT_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.test.cpp")
233+
file(GLOB SRC_UNIT_TESTS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.test.cpp")
234234
file(GLOB TESTS_INTEGRATION "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.test.cpp")
235235
file(GLOB TEST_HELPER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/test_helpers/*.cpp")
236236
set(TEST_SOURCES ${SRC_UNIT_TESTS} ${TESTS_INTEGRATION} ${TEST_HELPER_SOURCES})

‎src/meta.test.cpp‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <cpp_core/interface/meta.h>
2+
3+
#include <cstring>
4+
#include <string_view>
5+
6+
#include <gtest/gtest.h>
7+
8+
TEST(MetaTest, MetadataDescribesLoadedBinding)
9+
{
10+
meta(nullptr);
11+
cpp_core::Meta info{};
12+
meta(&info);
13+
EXPECT_STREQ(info.version_string, CPP_BINDINGS_LINUX_TEST_VERSION);
14+
ASSERT_NE(info.git_commit_hash_full, nullptr);
15+
EXPECT_EQ(std::strlen(info.git_commit_hash_full), 40U);
16+
ASSERT_NE(info.git_commit_hash_short, nullptr);
17+
EXPECT_TRUE(std::string_view(info.git_commit_hash_full).starts_with(info.git_commit_hash_short));
18+
EXPECT_NE(info.prerelease, nullptr);
19+
EXPECT_NE(info.prerelease_type, nullptr);
20+
EXPECT_NE(info.prerelease_number, nullptr);
21+
EXPECT_NE(info.git_tag, nullptr);
22+
EXPECT_NE(info.git_commit_date, nullptr);
23+
EXPECT_NE(info.git_branch, nullptr);
24+
EXPECT_NE(info.git_dirty_suffix, nullptr);
25+
}

‎src/serial_get_data_bits.test.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <cpp_core/interface/serial_get_data_bits.h>
2+
#include <cpp_core/status_code.h>
3+
4+
#include <gtest/gtest.h>
5+
6+
TEST(SerialGetDataBitsTest, PreservesNegativeHandleError)
7+
{
8+
constexpr int expected = static_cast<int>(cpp_core::StatusCode::Connection::kInvalidHandleError);
9+
EXPECT_EQ(cpp_core::toInt(serialGetDataBits(-1)), expected);
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <cpp_core/interface/serial_get_flow_control.h>
2+
#include <cpp_core/status_code.h>
3+
4+
#include <gtest/gtest.h>
5+
6+
TEST(SerialGetFlowControlTest, PreservesNegativeHandleError)
7+
{
8+
constexpr int expected = static_cast<int>(cpp_core::StatusCode::Connection::kInvalidHandleError);
9+
EXPECT_EQ(cpp_core::toInt(serialGetFlowControl(-1)), expected);
10+
}

‎src/serial_get_parity.test.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <cpp_core/interface/serial_get_parity.h>
2+
#include <cpp_core/status_code.h>
3+
4+
#include <gtest/gtest.h>
5+
6+
TEST(SerialGetParityTest, PreservesNegativeHandleError)
7+
{
8+
constexpr int expected = static_cast<int>(cpp_core::StatusCode::Connection::kInvalidHandleError);
9+
EXPECT_EQ(cpp_core::toInt(serialGetParity(-1)), expected);
10+
}

‎src/serial_get_stop_bits.test.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <cpp_core/interface/serial_get_stop_bits.h>
2+
#include <cpp_core/status_code.h>
3+
4+
#include <gtest/gtest.h>
5+
6+
TEST(SerialGetStopBitsTest, PreservesNegativeHandleError)
7+
{
8+
constexpr int expected = static_cast<int>(cpp_core::StatusCode::Connection::kInvalidHandleError);
9+
EXPECT_EQ(cpp_core::toInt(serialGetStopBits(-1)), expected);
10+
}

‎src/serial_open.test.cpp‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#include <cpp_core/interface/serial_open.h>
2+
#include <cpp_core/serial.h>
23
#include <cpp_core/status_code.h>
34

5+
#include "detail/handle_types.hpp"
6+
47
#include <array>
8+
#include <cstdlib>
9+
#include <fcntl.h>
510
#include <string>
611

712
#include <gmock/gmock.h>
@@ -247,3 +252,49 @@ TEST_F(SerialOpenTest, NoErrorCallbackNullPort)
247252

248253
EXPECT_EQ(result, kNotFoundError);
249254
}
255+
256+
TEST_F(SerialOpenTest, RejectsNullAndInvalidOpenConfigurations)
257+
{
258+
EXPECT_EQ(serialOpen("/dev/null", nullptr), static_cast<int>(cpp_core::StatusCode::Control::kSetStateError));
259+
constexpr auto kConfig = cpp_core::SerialConfig::make<9600, cpp_core::DataBits::kEight>();
260+
const auto check = [this](cpp_core::SerialConfig config, int expected) {
261+
error_capture.last_code = 0;
262+
EXPECT_EQ(serialOpen("/dev/null", &config, error_callback), expected);
263+
EXPECT_EQ(error_capture.last_code, expected);
264+
};
265+
auto config = kConfig;
266+
config.parity = static_cast<cpp_core::Parity>(99);
267+
check(config, static_cast<int>(cpp_core::StatusCode::Configuration::kSetParityError));
268+
config = kConfig;
269+
config.stop_bits = static_cast<cpp_core::StopBits>(1);
270+
check(config, static_cast<int>(cpp_core::StatusCode::Configuration::kSetStopBitsError));
271+
config = kConfig;
272+
config.flow_mode = static_cast<cpp_core::FlowControl>(99);
273+
check(config, static_cast<int>(cpp_core::StatusCode::Configuration::kSetFlowControlError));
274+
}
275+
276+
TEST_F(SerialOpenTest, OpensPseudoTerminalWithFlowControlAndTypedSettings)
277+
{
278+
constexpr auto kConfig = cpp_core::SerialConfig::make<9600, cpp_core::DataBits::kEight>();
279+
using cpp_bindings_linux::detail::UniqueFd;
280+
UniqueFd master(posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC));
281+
ASSERT_TRUE(master.valid());
282+
ASSERT_EQ(grantpt(master.get()), 0);
283+
ASSERT_EQ(unlockpt(master.get()), 0);
284+
const char *path = ptsname(master.get());
285+
ASSERT_NE(path, nullptr);
286+
for (auto flow : {cpp_core::FlowControl::kNone, cpp_core::FlowControl::kRtsCts, cpp_core::FlowControl::kXonXoff})
287+
{
288+
auto config = kConfig;
289+
config.flow_mode = flow;
290+
const auto handle = serialOpen(path, &config);
291+
ASSERT_GT(handle, 0);
292+
UniqueFd slave(static_cast<int>(handle));
293+
EXPECT_EQ(serialGetBaudrate(handle), config.baudrate);
294+
EXPECT_EQ(serialGetDataBits(handle), config.data_bits);
295+
EXPECT_EQ(serialGetParity(handle), config.parity);
296+
EXPECT_EQ(serialGetStopBits(handle), config.stop_bits);
297+
EXPECT_EQ(serialGetFlowControl(handle), flow);
298+
EXPECT_EQ(serialClose(slave.release()), 0);
299+
}
300+
}

‎src/serial_read.test.cpp‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <cpp_core/interface/serial_read.h>
22
#include <cpp_core/status_code.h>
33

4+
#include "detail/handle_types.hpp"
5+
46
#include <array>
57
#include <fcntl.h>
68
#include <limits>
@@ -147,3 +149,30 @@ TEST_F(SerialReadTest, ReadWithVariousTimeouts)
147149

148150
close(fd);
149151
}
152+
153+
TEST_F(SerialReadTest, RejectsNullNegativeAndOverflowingTimeouts)
154+
{
155+
constexpr int kTimeoutError = static_cast<int>(cpp_core::StatusCode::Configuration::kSetTimeoutError);
156+
cpp_bindings_linux::detail::UniqueFd fd(open("/dev/null", O_RDWR | O_NONBLOCK));
157+
ASSERT_TRUE(fd.valid());
158+
std::array<std::uint8_t, 4> buffer{};
159+
const auto check = [&](const cpp_core::SerialTimeoutConfig *timeout) {
160+
error_capture.last_code = 0;
161+
EXPECT_EQ(serialRead(fd.get(), buffer.data(), 4, timeout, error_callback), kTimeoutError);
162+
EXPECT_EQ(error_capture.last_code, kTimeoutError);
163+
};
164+
check(nullptr);
165+
for (const auto timeout : {cpp_core::SerialTimeoutConfig{-1, 1}, {1, -1}, {std::numeric_limits<int>::max(), 2}})
166+
{
167+
check(&timeout);
168+
}
169+
}
170+
171+
TEST_F(SerialReadTest, AcceptsZeroTimeoutWithMaximumMultiplier)
172+
{
173+
cpp_bindings_linux::detail::UniqueFd fd(open("/dev/null", O_RDWR | O_NONBLOCK));
174+
ASSERT_TRUE(fd.valid());
175+
std::array<std::uint8_t, 4> buffer{};
176+
const cpp_core::SerialTimeoutConfig zero{0, std::numeric_limits<int>::max()};
177+
EXPECT_EQ(serialRead(fd.get(), buffer.data(), 4, &zero), 0);
178+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <cpp_core/interface/serial_close.h>
2+
#include <cpp_core/interface/serial_read.h>
3+
#include <cpp_core/interface/serial_read_until_sequence.h>
4+
#include <cpp_core/status_code.h>
5+
6+
#include "detail/handle_types.hpp"
7+
8+
#include <array>
9+
#include <cstring>
10+
#include <fcntl.h>
11+
#include <limits>
12+
#include <unistd.h>
13+
14+
#include <gtest/gtest.h>
15+
16+
namespace
17+
{
18+
using cpp_bindings_linux::detail::UniqueFd;
19+
constexpr auto kTimeout = cpp_core::SerialTimeoutConfig::make<10, 1>();
20+
constexpr int kBufferError = static_cast<int>(cpp_core::StatusCode::Io::kBufferError);
21+
} // namespace
22+
23+
TEST(SerialReadUntilSequenceTest, RejectsNullNegativeAndOverflowingTimeouts)
24+
{
25+
constexpr int kTimeoutError = static_cast<int>(cpp_core::StatusCode::Configuration::kSetTimeoutError);
26+
cpp_bindings_linux::detail::UniqueFd fd(open("/dev/null", O_RDWR | O_NONBLOCK));
27+
ASSERT_TRUE(fd.valid());
28+
std::array<std::uint8_t, 4> buffer{};
29+
const auto check = [&](const cpp_core::SerialTimeoutConfig *timeout) {
30+
EXPECT_EQ(serialReadUntilSequence(fd.get(), buffer.data(), 4, timeout, buffer.data(), 1), kTimeoutError);
31+
};
32+
check(nullptr);
33+
for (const auto timeout : {cpp_core::SerialTimeoutConfig{-1, 1}, {1, -1}, {std::numeric_limits<int>::max(), 2}})
34+
{
35+
check(&timeout);
36+
}
37+
}
38+
39+
TEST(SerialReadUntilSequenceTest, ReadsBinarySequenceWithEmbeddedZeroAndLeavesFollowingBytes)
40+
{
41+
std::array<int, 2> fds{};
42+
ASSERT_EQ(pipe2(fds.data(), O_NONBLOCK | O_CLOEXEC), 0);
43+
UniqueFd reader(fds[0]);
44+
UniqueFd writer(fds[1]);
45+
constexpr std::array<std::uint8_t, 8> payload{'a', 'a', 0, 'a', 0, 'b', 'x', 'y'};
46+
constexpr std::array<std::uint8_t, 4> sequence{'a', 0, 'b', 'z'};
47+
ASSERT_EQ(write(writer.get(), payload.data(), payload.size()), static_cast<ssize_t>(payload.size()));
48+
std::array<std::uint8_t, 16> buffer{};
49+
// The explicit size excludes 'z'; the sequence has no C-string terminator.
50+
EXPECT_EQ(serialReadUntilSequence(reader.get(), buffer.data(), 16, &kTimeout, sequence.data(), 3), 6);
51+
EXPECT_EQ(std::memcmp(buffer.data(), payload.data(), 6), 0);
52+
EXPECT_EQ(serialRead(reader.get(), buffer.data(), 2, &kTimeout), 2);
53+
EXPECT_EQ(buffer[0], 'x');
54+
EXPECT_EQ(buffer[1], 'y');
55+
EXPECT_EQ(serialClose(reader.release()), 0);
56+
}
57+
58+
TEST(SerialReadUntilSequenceTest, ValidatesSequenceSizeAndHonorsBufferCapacity)
59+
{
60+
UniqueFd fd(open("/dev/null", O_RDONLY));
61+
ASSERT_TRUE(fd.valid());
62+
std::array<std::uint8_t, 4> buffer{};
63+
EXPECT_EQ(serialReadUntilSequence(fd.get(), buffer.data(), 4, &kTimeout, nullptr, 1), kBufferError);
64+
EXPECT_EQ(serialReadUntilSequence(fd.get(), buffer.data(), 4, &kTimeout, buffer.data(), 0), kBufferError);
65+
EXPECT_EQ(serialReadUntilSequence(fd.get(), buffer.data(), 4, &kTimeout, buffer.data(), -1), kBufferError);
66+
67+
std::array<int, 2> fds{};
68+
ASSERT_EQ(pipe2(fds.data(), O_NONBLOCK | O_CLOEXEC), 0);
69+
UniqueFd reader(fds[0]);
70+
UniqueFd writer(fds[1]);
71+
constexpr std::array<std::uint8_t, 5> payload{'a', 'b', 'c', 'd', 'e'};
72+
ASSERT_EQ(write(writer.get(), payload.data(), payload.size()), static_cast<ssize_t>(payload.size()));
73+
EXPECT_EQ(serialReadUntilSequence(reader.get(), buffer.data(), 4, &kTimeout, payload.data(), 5), 4);
74+
EXPECT_EQ(std::memcmp(buffer.data(), payload.data(), 4), 0);
75+
EXPECT_EQ(serialClose(reader.release()), 0);
76+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <cpp_core/interface/serial_set_event_callback.h>
2+
3+
#include <cstdlib>
4+
5+
#include <gtest/gtest.h>
6+
7+
namespace
8+
{
9+
void portEvent(cpp_core::PortEvent, const char *)
10+
{
11+
}
12+
} // namespace
13+
14+
TEST(SerialSetEventCallbackTest, EventCallbackCanBeStartedReplacedAndStoppedRepeatedly)
15+
{
16+
EXPECT_EQ(serialSetEventCallback(nullptr), 0);
17+
for (int iteration = 0; iteration < 5; ++iteration)
18+
{
19+
EXPECT_EQ(serialSetEventCallback(portEvent), 0);
20+
EXPECT_EQ(serialSetEventCallback(portEvent), 0);
21+
EXPECT_EQ(serialSetEventCallback(nullptr), 0);
22+
}
23+
EXPECT_EQ(serialSetEventCallback(nullptr), 0);
24+
}
25+
26+
TEST(SerialSetEventCallbackDeathTest, ActiveEventListenerIsStoppedOnExit)
27+
{
28+
EXPECT_EXIT(
29+
{
30+
if (serialSetEventCallback(portEvent) != 0)
31+
{
32+
std::exit(1);
33+
}
34+
std::exit(0);
35+
},
36+
::testing::ExitedWithCode(0), "");
37+
}

0 commit comments

Comments
 (0)