From 63e197fa739f3bc778c788898d15d43b63e6e5b2 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Thu, 23 Jul 2026 14:57:51 -0400 Subject: [PATCH] more catch2 tests for base functions; --- tests/BitManipulation_Tests.cpp | 64 +++++++++++++++++++++++ tests/Clock_Tests.cpp | 49 ++++++++++++++++++ tests/StopWatch_Tests.cpp | 38 ++++++++++++++ tests/Timer_Tests.cpp | 76 +++++++++++++++++++++++++++ tests/Utils_Tests.cpp | 91 +++++++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+) create mode 100644 tests/BitManipulation_Tests.cpp create mode 100644 tests/Clock_Tests.cpp create mode 100644 tests/StopWatch_Tests.cpp create mode 100644 tests/Timer_Tests.cpp create mode 100644 tests/Utils_Tests.cpp diff --git a/tests/BitManipulation_Tests.cpp b/tests/BitManipulation_Tests.cpp new file mode 100644 index 00000000..a3c8b5d1 --- /dev/null +++ b/tests/BitManipulation_Tests.cpp @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Test Suite + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2026 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "common/BitManipulation.h" + +#include + +#include +#include + +TEST_CASE("BitManipulation bit macros set, clear, and read values", "[common][bitmanipulation]") +{ + std::array buffer = {}; + + REQUIRE(READ_BIT(buffer.data(), 0U) == 0U); + WRITE_BIT(buffer.data(), 0U, true); + REQUIRE(READ_BIT(buffer.data(), 0U) != 0U); + REQUIRE(buffer[0U] == 0x80U); + + WRITE_BIT(buffer.data(), 0U, false); + REQUIRE(READ_BIT(buffer.data(), 0U) == 0U); + REQUIRE(buffer[0U] == 0x00U); + + WRITE_BIT(buffer.data(), 9U, true); + REQUIRE(READ_BIT(buffer.data(), 9U) != 0U); + REQUIRE(buffer[1U] == 0x40U); + + WRITE_BIT(buffer.data(), 9U, false); + REQUIRE(READ_BIT(buffer.data(), 9U) == 0U); + REQUIRE(buffer[1U] == 0x00U); +} + +TEST_CASE("BitManipulation integer macros round-trip values", "[common][bitmanipulation]") +{ + std::array buffer = {}; + + SET_UINT32(0x12345678U, buffer.data(), 0U); + uint32_t value32 = GET_UINT32(buffer.data(), 0U); + REQUIRE(value32 == 0x12345678U); + REQUIRE(buffer[0U] == 0x12U); + REQUIRE(buffer[1U] == 0x34U); + REQUIRE(buffer[2U] == 0x56U); + REQUIRE(buffer[3U] == 0x78U); + + SET_UINT24(0x00ABCDEFU, buffer.data(), 4U); + uint32_t value24 = GET_UINT24(buffer.data(), 4U); + REQUIRE(value24 == 0x00ABCDEFU); + REQUIRE(buffer[4U] == 0xABU); + REQUIRE(buffer[5U] == 0xCDU); + REQUIRE(buffer[6U] == 0xEFU); + + SET_UINT16(0xBEEFU, buffer.data(), 8U); + uint32_t value16 = GET_UINT16(buffer.data(), 8U); + REQUIRE(value16 == 0xBEEFU); + REQUIRE(buffer[8U] == 0xBEU); + REQUIRE(buffer[9U] == 0xEFU); +} \ No newline at end of file diff --git a/tests/Clock_Tests.cpp b/tests/Clock_Tests.cpp new file mode 100644 index 00000000..def0b420 --- /dev/null +++ b/tests/Clock_Tests.cpp @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Test Suite + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2026 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "common/Clock.h" + +#include + +#include +#include + +using namespace system_clock; + +TEST_CASE("Clock conversion helpers are consistent", "[common][clock]") +{ + REQUIRE(msToJiffies(0U) == 0U); + REQUIRE(msToJiffies(1000U) == 65536U); + REQUIRE(msToJiffies(250U) == 16384U); + REQUIRE(jiffiesToMs(0U) == 0U); + REQUIRE(jiffiesToMs(65536U) == 1000U); + REQUIRE(jiffiesToMs(16384U) == 250U); +} + +TEST_CASE("Clock HRC helpers report elapsed time", "[common][clock]") +{ + auto start = hrc::now(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + auto end = hrc::now(); + + REQUIRE(hrc::diff(end, start) >= 10U); + REQUIRE(hrc::diffNow(start) >= 10U); + + auto startUS = hrc::now(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + REQUIRE(hrc::diffNowUS(startUS) >= 10000U); +} + +TEST_CASE("Clock NTP helpers are self-consistent", "[common][clock]") +{ + uint64_t now = ntp::now(); + REQUIRE(ntp::diff(now, now) == 0U); + REQUIRE(ntp::diffNow(now) < 1000U); +} \ No newline at end of file diff --git a/tests/StopWatch_Tests.cpp b/tests/StopWatch_Tests.cpp new file mode 100644 index 00000000..aeb46ed0 --- /dev/null +++ b/tests/StopWatch_Tests.cpp @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Test Suite + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2026 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "common/StopWatch.h" + +#include + +#include +#include + +TEST_CASE("StopWatch time increases over time", "[common][stopwatch]") +{ + StopWatch stopWatch; + uint64_t first = stopWatch.time(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + uint64_t second = stopWatch.time(); + + REQUIRE(second >= first); +} + +TEST_CASE("StopWatch measures elapsed time after start", "[common][stopwatch]") +{ + StopWatch stopWatch; + REQUIRE(stopWatch.start() >= 0U); + + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + uint32_t elapsed = stopWatch.elapsed(); + REQUIRE(elapsed >= 10U); + REQUIRE(elapsed < 1000U); +} \ No newline at end of file diff --git a/tests/Timer_Tests.cpp b/tests/Timer_Tests.cpp new file mode 100644 index 00000000..3d639873 --- /dev/null +++ b/tests/Timer_Tests.cpp @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Test Suite + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2026 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "common/Timer.h" + +#include + +TEST_CASE("Timer defaults to stopped with no timeout", "[common][timer]") +{ + Timer timer; + + REQUIRE(timer.getTimeout() == 0U); + REQUIRE(timer.getTimer() == 0U); + REQUIRE(timer.getRemaining() == 0U); + REQUIRE_FALSE(timer.isRunning()); + REQUIRE_FALSE(timer.hasExpired()); + REQUIRE_FALSE(timer.isPaused()); +} + +TEST_CASE("Timer counts ticks and expires at the configured timeout", "[common][timer]") +{ + Timer timer(1000U, 1U, 500U); + + REQUIRE(timer.getTimeout() == 1U); + REQUIRE_FALSE(timer.isRunning()); + + timer.start(); + REQUIRE(timer.isRunning()); + REQUIRE_FALSE(timer.hasExpired()); + REQUIRE(timer.getTimer() == 0U); + + timer.clock(500U); + REQUIRE_FALSE(timer.hasExpired()); + REQUIRE(timer.getTimer() == 0U); + REQUIRE(timer.getRemaining() == 1U); + + timer.clock(1000U); + REQUIRE(timer.hasExpired()); + REQUIRE(timer.getTimer() == 1U); + REQUIRE(timer.getRemaining() == 0U); +} + +TEST_CASE("Timer pause resume stop and reset behave consistently", "[common][timer]") +{ + Timer timer(1000U, 2U, 0U); + + timer.start(); + timer.clock(1000U); + REQUIRE_FALSE(timer.hasExpired()); + + timer.pause(); + REQUIRE(timer.isPaused()); + timer.clock(2000U); + REQUIRE(timer.getTimer() == 1U); + + timer.resume(); + REQUIRE_FALSE(timer.isPaused()); + timer.clock(1000U); + REQUIRE(timer.hasExpired()); + + timer.stop(); + REQUIRE_FALSE(timer.isRunning()); + REQUIRE_FALSE(timer.hasExpired()); + REQUIRE(timer.getTimer() == 0U); + + timer.setTimeout(0U, 0U); + REQUIRE(timer.getTimeout() == 0U); + REQUIRE(timer.getRemaining() == 0U); +} \ No newline at end of file diff --git a/tests/Utils_Tests.cpp b/tests/Utils_Tests.cpp new file mode 100644 index 00000000..b9b7d71a --- /dev/null +++ b/tests/Utils_Tests.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Test Suite + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2026 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "common/Utils.h" + +#include + +#include +#include +#include + +TEST_CASE("Utils string helpers convert case and format values", "[common][utils]") +{ + REQUIRE(strtolower("AbC123!?") == "abc123!?"); + REQUIRE(strtoupper("AbC123!?") == "ABC123!?"); + REQUIRE(__BOOL_STR(true) == "true"); + REQUIRE(__BOOL_STR(false) == "false"); + REQUIRE(__INT_STR(-42) == "-42"); + REQUIRE(__INT_HEX_STR(42) == "2a"); + REQUIRE(__FLOAT_STR(3.5F) == "3.5"); +} + +TEST_CASE("Utils IP helpers convert to and from packed values", "[common][utils]") +{ + REQUIRE(__IP_FROM_UINT(0x7F000001U) == "127.0.0.1"); + REQUIRE(__IP_FROM_STR("192.168.1.20") == 0xC0A80114U); + REQUIRE(__IP_FROM_STR("10.0.0.1") == 0x0A000001U); +} + +TEST_CASE("Utils endian helpers reverse byte order", "[common][utils]") +{ + REQUIRE(Utils::reverseEndian(uint16_t(0x1234U)) == 0x3412U); + REQUIRE(Utils::reverseEndian(uint32_t(0x12345678U)) == 0x78563412U); + REQUIRE(Utils::reverseEndian(uint64_t(0x0123456789ABCDEFULL)) == 0xEFCDAB8967452301ULL); +} + +TEST_CASE("Utils bit helpers round-trip bit buffers", "[common][utils]") +{ + std::array source = {0xA5U, 0x5AU, 0xFFU, 0x00U}; + std::array target = {}; + + REQUIRE(Utils::getBits(source.data(), target.data(), 0U, 16U) == 16U); + REQUIRE(target[0U] == 0xA5U); + REQUIRE(target[1U] == 0x5AU); + + std::array shifted = {}; + REQUIRE(Utils::setBits(target.data(), shifted.data(), 8U, 24U) == 16U); + REQUIRE(shifted[1U] == 0xA5U); + REQUIRE(shifted[2U] == 0x5AU); + + std::array ranged = {}; + REQUIRE(Utils::getBitRange(source.data(), ranged.data(), 8U, 16U) == 16U); + REQUIRE(ranged[0U] == 0x5AU); + REQUIRE(ranged[1U] == 0xFFU); + + std::array back = {}; + REQUIRE(Utils::setBitRange(ranged.data(), back.data(), 4U, 16U) == 16U); + + std::array verify = {}; + REQUIRE(Utils::getBitRange(back.data(), verify.data(), 4U, 16U) == 16U); + REQUIRE(verify[0U] == ranged[0U]); + REQUIRE(verify[1U] == ranged[1U]); +} + +TEST_CASE("Utils binary helpers convert between 6-bit and bit buffers", "[common][utils]") +{ + std::array bits = {}; + Utils::hex2Bin(0x2DU, bits.data(), 0U); + + REQUIRE(bits[0U] == 0xB4U); + REQUIRE(Utils::bin2Hex(bits.data(), 0U) == 0x2DU); + + std::array shifted = {}; + Utils::hex2Bin(0x15U, shifted.data(), 3U); + REQUIRE(Utils::bin2Hex(shifted.data(), 3U) == 0x15U); +} + +TEST_CASE("Utils bit count helpers return population counts", "[common][utils]") +{ + REQUIRE(Utils::countBits8(0x00U) == 0U); + REQUIRE(Utils::countBits8(0xFFU) == 8U); + REQUIRE(Utils::countBits32(0xF0F0F0F0U) == 16U); + REQUIRE(Utils::countBits64(0xFFFF0000FFFF0000ULL) == 32U); +} \ No newline at end of file