diff --git a/CMakeLists.txt b/CMakeLists.txt index ce779794..681da760 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,8 @@ file(GLOB dvmcmd_SRC # dvmtest source/header files file(GLOB dvmtests_SRC "tests/nulltest.cpp" + + "tests/p25/lc/*.cpp" ) # digital mode options @@ -360,7 +362,8 @@ FetchContent_Declare( FetchContent_MakeAvailable(Catch2) find_package(Threads REQUIRED) -add_executable(dvmtests ${dvmtests_SRC}) +add_executable(dvmtests ${dvmhost_SRC} ${dvmtests_SRC}) +target_compile_definitions(dvmtests PUBLIC -DCATCH2_TEST_COMPILATION) target_link_libraries(dvmtests PRIVATE Catch2::Catch2WithMain Threads::Threads util) target_include_directories(dvmtests PRIVATE .) endif (ENABLE_TESTS) diff --git a/HostMain.cpp b/HostMain.cpp index d25f9262..cd3489d3 100644 --- a/HostMain.cpp +++ b/HostMain.cpp @@ -105,7 +105,7 @@ uint8_t* g_gitHashBytes = nullptr; // Global Functions // --------------------------------------------------------------------------- -#if !defined(_WIN32) && !defined(_WIN64) +#if !defined(_WIN32) && !defined(_WIN64) && !defined(CATCH2_TEST_COMPILATION) static void sigHandler(int signum) { g_killed = true; @@ -245,7 +245,7 @@ int checkArgs(int argc, char* argv[]) // --------------------------------------------------------------------------- // Program Entry Point // --------------------------------------------------------------------------- - +#if !defined(CATCH2_TEST_COMPILATION) int main(int argc, char** argv) { g_gitHashBytes = new uint8_t[4U]; @@ -314,3 +314,4 @@ int main(int argc, char** argv) return ret; } +#endif \ No newline at end of file diff --git a/Log.cpp b/Log.cpp index 8e7e147d..6ca26224 100644 --- a/Log.cpp +++ b/Log.cpp @@ -38,6 +38,10 @@ #include #endif +#if defined(CATCH2_TEST_COMPILATION) +#include +#endif + #include #include #include @@ -91,6 +95,9 @@ static char LEVELS[] = " DMIWEF"; /// True, if log file is opened, otherwise false. static bool LogOpen() { +#if defined(CATCH2_TEST_COMPILATION) + return true; +#endif if (m_fileLevel == 0U) return true; @@ -158,6 +165,9 @@ static bool ActivityLogOpen() /// Instance of the Network class. void LogSetNetwork(void* network) { +#if defined(CATCH2_TEST_COMPILATION) + return; +#endif // note: The Network class is passed here as a void so we can avoid including the Network.h // header in Log.h. This is dirty and probably terrible... m_network = (network::Network*)network; @@ -170,6 +180,9 @@ void LogSetNetwork(void* network) /// Prefix of the activity log file name. bool ActivityLogInitialise(const std::string& filePath, const std::string& fileRoot) { +#if defined(CATCH2_TEST_COMPILATION) + return true; +#endif m_actFilePath = filePath; m_actFileRoot = fileRoot; m_network = nullptr; @@ -182,6 +195,9 @@ bool ActivityLogInitialise(const std::string& filePath, const std::string& fileR /// void ActivityLogFinalise() { +#if defined(CATCH2_TEST_COMPILATION) + return; +#endif if (m_actFpLog != nullptr) ::fclose(m_actFpLog); } @@ -194,6 +210,9 @@ void ActivityLogFinalise() /// Formatted string to write to activity log. void ActivityLog(const char *mode, const bool sourceRf, const char* msg, ...) { +#if defined(CATCH2_TEST_COMPILATION) + return; +#endif assert(mode != nullptr); assert(msg != nullptr); @@ -268,6 +287,9 @@ bool LogInitialise(const std::string& filePath, const std::string& fileRoot, uin /// void LogFinalise() { +#if defined(CATCH2_TEST_COMPILATION) + return; +#endif if (m_fpLog != nullptr) ::fclose(m_fpLog); } @@ -281,7 +303,9 @@ void LogFinalise() void Log(uint32_t level, const char *module, const char* fmt, ...) { assert(fmt != nullptr); - +#if defined(CATCH2_TEST_COMPILATION) + m_disableTimeDisplay = true; +#endif char buffer[LOG_BUFFER_LEN]; #if defined(_WIN32) || defined(_WIN64) if (!m_disableTimeDisplay) { @@ -341,6 +365,11 @@ void Log(uint32_t level, const char *module, const char* fmt, ...) } } +#if defined(CATCH2_TEST_COMPILATION) + UNSCOPED_INFO(buffer); + return; +#endif + if (level >= m_fileLevel && m_fileLevel != 0U) { bool ret = ::LogOpen(); if (!ret) diff --git a/Utils.cpp b/Utils.cpp index 0b361629..52f77b24 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -96,7 +96,7 @@ void Utils::dump(int level, const std::string& title, const uint8_t* data, uint3 ::sprintf(temp, "%02X ", data[offset + i]); output += temp; } - +#if !defined(CATCH2_TEST_COMPILATION) for (uint32_t i = bytes; i < 16U; i++) output += " "; @@ -112,7 +112,7 @@ void Utils::dump(int level, const std::string& title, const uint8_t* data, uint3 } output += '*'; - +#endif ::Log(level, "DUMP", "%04X: %s", offset, output.c_str()); offset += 16U; diff --git a/tests/nulltest.cpp b/tests/nulltest.cpp index afe7efa0..147fa20f 100644 --- a/tests/nulltest.cpp +++ b/tests/nulltest.cpp @@ -1,3 +1,30 @@ +/** +* Digital Voice Modem - Host Software (Test Suite) +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software / Test Suite +* +*/ +/* +* Copyright (C) 2022 by Natalie Moore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" + #include TEST_CASE("NullTest", "[NullTest]") { diff --git a/tests/p25/lc/HDU_RS_Test.cpp b/tests/p25/lc/HDU_RS_Test.cpp new file mode 100644 index 00000000..e548b1cd --- /dev/null +++ b/tests/p25/lc/HDU_RS_Test.cpp @@ -0,0 +1,114 @@ +/** +* Digital Voice Modem - Host Software (Test Suite) +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software / Test Suite +* +*/ +/* +* Copyright (C) 2023 Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "edac/RS634717.h" +#include "p25/P25Defines.h" +#include "Log.h" +#include "Utils.h" + +using namespace edac; +using namespace p25; + +#include +#include +#include + +TEST_CASE("HDU", "[RS_362017_Test]") { + SECTION("RS_362017_Test") { + bool failed = false; + + INFO("P25 HDU RS (36,20,17) FEC Test"); + + srand((unsigned int)time(NULL)); + RS634717 m_rs = RS634717(); + + uint8_t* random = (uint8_t*)malloc(15U); + + for (size_t i = 0; i < 15U; i++) { + random[i] = rand(); + } + + // HDU Encode + uint8_t rs[P25_HDU_LENGTH_BYTES]; + ::memset(rs, 0x00U, P25_HDU_LENGTH_BYTES); + + for (uint32_t i = 0; i < 15U; i++) + rs[i] = random[i]; + rs[14U] = 0xF0U; + + Utils::dump(2U, "LC::encodeHDU(), HDU", rs, P25_HDU_LENGTH_BYTES); + + // encode RS (36,20,17) FEC + m_rs.encode362017(rs); + + Utils::dump(2U, "LC::encodeHDU(), HDU RS", rs, P25_HDU_LENGTH_BYTES); + + // HDU Decode + rs[9U] >>= 8; + rs[10U] >>= 8; + rs[11U] >>= 8; + rs[12U] >>= 8; + rs[13U] >>= 8; + + Utils::dump(2U, "LC::decodeHDU(), HDU RS (errors injected)", rs, P25_HDU_LENGTH_BYTES); + + // decode RS (36,20,17) FEC + try { + bool ret = m_rs.decode362017(rs); + if (!ret) { + fprintf(stdout, "LC::decodeHDU(), failed to decode RS (36,20,17) FEC\n"); + failed = true; + goto cleanup; + } + } + catch (...) { + Utils::dump(2U, "P25, RS excepted with input data", rs, P25_HDU_LENGTH_BYTES); + failed = true; + goto cleanup; + } + + Utils::dump(2U, "LC::decodeHDU(), HDU", rs, P25_HDU_LENGTH_BYTES); + + for (uint32_t i = 0; i < 15U; i++) { + if (i == 14U) { + if (rs[i] != 0xF0U) { + ::LogDebug("T", "LC::decodeHDU(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + else { + if (rs[i] != random[i]) { + ::LogDebug("T", "LC::decodeHDU(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + } + +cleanup: + delete random; + REQUIRE(failed==false); + } +} diff --git a/tests/p25/lc/LDU1_RS_Test.cpp b/tests/p25/lc/LDU1_RS_Test.cpp new file mode 100644 index 00000000..769168fa --- /dev/null +++ b/tests/p25/lc/LDU1_RS_Test.cpp @@ -0,0 +1,112 @@ +/** +* Digital Voice Modem - Host Software (Test Suite) +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software / Test Suite +* +*/ +/* +* Copyright (C) 2022 by Natalie Moore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "edac/RS634717.h" +#include "p25/P25Defines.h" +#include "Log.h" +#include "Utils.h" + +using namespace edac; +using namespace p25; + +#include +#include +#include + +TEST_CASE("LDU1", "[RS_241213_Test]") { + SECTION("RS_241213_Test") { + bool failed = false; + + INFO("P25 LDU1 RS (24,12,13) FEC Test"); + + srand((unsigned int)time(NULL)); + RS634717 m_rs = RS634717(); + + uint8_t* random = (uint8_t*)malloc(15U); + + for (size_t i = 0; i < 15U; i++) { + random[i] = rand(); + } + + // LDU1 Encode + uint8_t rs[P25_LDU_LC_LENGTH_BYTES]; + ::memset(rs, 0x00U, P25_LDU_LC_LENGTH_BYTES); + + for (uint32_t i = 0; i < 9U; i++) + rs[i] = random[i]; + rs[8U] = 0xF0U; + + Utils::dump(2U, "LC::encodeLDU1(), LDU1", rs, P25_LDU_LC_LENGTH_BYTES); + + // encode RS (24,12,13) FEC + m_rs.encode241213(rs); + + Utils::dump(2U, "LC::encodeLDU1(), LDU1 RS", rs, P25_LDU_LC_LENGTH_BYTES); + + // LDU1 Decode + rs[6U] >>= 8; + rs[7U] >>= 8; + rs[8U] >>= 8; + + Utils::dump(2U, "LC::encodeLDU1(), LDU RS (errors injected)", rs, P25_LDU_LC_LENGTH_BYTES); + + // decode RS (24,12,13) FEC + try { + bool ret = m_rs.decode241213(rs); + if (!ret) { + ::LogDebug("T", "LC::decodeLDU1(), failed to decode RS (24,12,13) FEC\n"); + failed = true; + goto cleanup; + } + } + catch (...) { + Utils::dump(2U, "P25, RS excepted with input data", rs, P25_LDU_LC_LENGTH_BYTES); + failed = true; + goto cleanup; + } + + Utils::dump(2U, "LC::decodeLDU1(), LDU1", rs, P25_LDU_LC_LENGTH_BYTES); + + for (uint32_t i = 0; i < 9U; i++) { + if (i == 8U) { + if (rs[i] != 0xF0U) { + ::LogDebug("T", "LC::decodeLDU1(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + else { + if (rs[i] != random[i]) { + ::LogDebug("T", "LC::decodeLDU1(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + } + +cleanup: + delete random; + REQUIRE(failed==false); + } +} diff --git a/tests/p25/lc/LDU2_RS_Test.cpp b/tests/p25/lc/LDU2_RS_Test.cpp new file mode 100644 index 00000000..a25df19b --- /dev/null +++ b/tests/p25/lc/LDU2_RS_Test.cpp @@ -0,0 +1,111 @@ +/** +* Digital Voice Modem - Host Software (Test Suite) +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software / Test Suite +* +*/ +/* +* Copyright (C) 2022 by Natalie Moore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "edac/RS634717.h" +#include "p25/P25Defines.h" +#include "Log.h" +#include "Utils.h" + +using namespace edac; +using namespace p25; + +#include +#include +#include + +TEST_CASE("LDU2", "[RS_24169_Test]") { + SECTION("RS_24169_Test") { + bool failed = false; + + INFO("P25 LDU2 RS (24,16,9) FEC Test"); + + srand((unsigned int)time(NULL)); + RS634717 m_rs = RS634717(); + + uint8_t* random = (uint8_t*)malloc(15U); + + for (size_t i = 0; i < 15U; i++) { + random[i] = rand(); + } + + // LDU2 Encode + uint8_t rs[P25_LDU_LC_LENGTH_BYTES]; + ::memset(rs, 0x00U, P25_LDU_LC_LENGTH_BYTES); + + for (uint32_t i = 0; i < 12U; i++) + rs[i] = random[i]; + rs[11U] = 0xF0U; + + Utils::dump(2U, "LC::encodeLDU2(), LDU2", rs, P25_LDU_LC_LENGTH_BYTES); + + // encode RS (24,16,9) FEC + m_rs.encode24169(rs); + + Utils::dump(2U, "LC::encodeLDU2(), LDU2 RS", rs, P25_LDU_LC_LENGTH_BYTES); + + // LDU2 Decode + rs[9U] >>= 4; + rs[10U] >>= 4; + + Utils::dump(2U, "LC::decodeLDU2(), LDU RS (errors injected)", rs, P25_LDU_LC_LENGTH_BYTES); + + // decode RS (24,16,9) FEC + try { + bool ret = m_rs.decode24169(rs); + if (!ret) { + ::LogDebug("T", "LC::decodeLDU2(), failed to decode RS (24,16,9) FEC\n"); + failed = true; + goto cleanup; + } + } + catch (...) { + Utils::dump(2U, "P25, RS excepted with input data", rs, P25_LDU_LC_LENGTH_BYTES); + failed = true; + goto cleanup; + } + + Utils::dump(2U, "LC::decodeLDU2(), LDU2", rs, P25_LDU_LC_LENGTH_BYTES); + + for (uint32_t i = 0; i < 12U; i++) { + if (i == 11U) { + if (rs[i] != 0xF0U) { + ::LogDebug("T", "LC::decodeLDU2(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + else { + if (rs[i] != random[i]) { + ::LogDebug("T", "LC::decodeLDU2(), UNCORRECTABLE AT IDX %d\n", i); + failed = true; + } + } + } + +cleanup: + delete random; + REQUIRE(failed==false); + } +}