add support for FNE tests via dvmtests harness;

pull/128/head
Bryan Biedenkapp 2 months ago
parent 6cbcd4240c
commit 47fff42173

@ -278,10 +278,15 @@ if (ENABLE_TESTS)
target_compile_definitions(asio::asio INTERFACE "ASIO_STANDALONE") target_compile_definitions(asio::asio INTERFACE "ASIO_STANDALONE")
target_link_libraries(asio::asio INTERFACE Threads::Threads) target_link_libraries(asio::asio INTERFACE Threads::Threads)
add_executable(dvmtests ${common_INCLUDE} ${dvmhost_SRC} ${dvmtests_SRC}) set(dvmfnetest_SRC ${dvmfne_SRC})
list(FILTER dvmfnetest_SRC EXCLUDE REGEX "/FNEMain\\.cpp$")
list(FILTER dvmfnetest_SRC EXCLUDE REGEX "/ActivityLog\\.cpp$")
list(FILTER dvmfnetest_SRC EXCLUDE REGEX "/HostFNE\\.cpp$")
list(FILTER dvmfnetest_SRC EXCLUDE REGEX "/fne/restapi/.*\\.cpp$")
add_executable(dvmtests ${common_INCLUDE} ${dvmhost_SRC} ${dvmfnetest_SRC} ${dvmtests_SRC})
target_compile_definitions(dvmtests PUBLIC -DCATCH2_TEST_COMPILATION) target_compile_definitions(dvmtests PUBLIC -DCATCH2_TEST_COMPILATION)
target_link_libraries(dvmtests PRIVATE Catch2::Catch2WithMain common ${OPENSSL_LIBRARIES} asio::asio Threads::Threads util) target_link_libraries(dvmtests PRIVATE Catch2::Catch2WithMain common ${OPENSSL_LIBRARIES} asio::asio Threads::Threads util)
target_include_directories(dvmtests PRIVATE ${OPENSSL_INCLUDE_DIR} src src/host tests) target_include_directories(dvmtests PRIVATE ${OPENSSL_INCLUDE_DIR} src src/host src/fne tests)
catch_discover_tests(dvmtests) catch_discover_tests(dvmtests)
endif (ENABLE_TESTS) endif (ENABLE_TESTS)

@ -16,7 +16,7 @@
#if !defined(__ACTIVITY_LOG_H__) #if !defined(__ACTIVITY_LOG_H__)
#define __ACTIVITY_LOG_H__ #define __ACTIVITY_LOG_H__
#include "Defines.h" #include "fne/Defines.h"
#include <string> #include <string>

@ -16,7 +16,7 @@
#if !defined(__FNE_MAIN_H__) #if !defined(__FNE_MAIN_H__)
#define __FNE_MAIN_H__ #define __FNE_MAIN_H__
#include "Defines.h" #include "fne/Defines.h"
#include <string> #include <string>

@ -7,7 +7,7 @@
* Copyright (C) 2023-2026 Bryan Biedenkapp, N2PLL * Copyright (C) 2023-2026 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "fne/Defines.h"
#include "common/network/udp/Socket.h" #include "common/network/udp/Socket.h"
#include "common/Log.h" #include "common/Log.h"
#include "common/StopWatch.h" #include "common/StopWatch.h"

@ -16,7 +16,7 @@
#if !defined(__HOST_FNE_H__) #if !defined(__HOST_FNE_H__)
#define __HOST_FNE_H__ #define __HOST_FNE_H__
#include "Defines.h" #include "fne/Defines.h"
#include "common/lookups/RadioIdLookup.h" #include "common/lookups/RadioIdLookup.h"
#include "common/lookups/TalkgroupRulesLookup.h" #include "common/lookups/TalkgroupRulesLookup.h"
#include "common/lookups/PeerListLookup.h" #include "common/lookups/PeerListLookup.h"
@ -27,7 +27,7 @@
#include "network/TrafficNetwork.h" #include "network/TrafficNetwork.h"
#include "network/MetadataNetwork.h" #include "network/MetadataNetwork.h"
#include "network/PeerNetwork.h" #include "network/PeerNetwork.h"
#include "restapi/RESTAPI.h" #include "fne/restapi/RESTAPI.h"
#include "CryptoContainer.h" #include "CryptoContainer.h"
#include <string> #include <string>
@ -38,6 +38,10 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class FNETestHooks;
#endif
namespace network { namespace callhandler { class HOST_SW_API TagDMRData; } } namespace network { namespace callhandler { class HOST_SW_API TagDMRData; } }
namespace network { namespace callhandler { namespace packetdata { class HOST_SW_API DMRPacketData; } } } namespace network { namespace callhandler { namespace packetdata { class HOST_SW_API DMRPacketData; } } }
namespace network { namespace callhandler { class HOST_SW_API TagP25Data; } } namespace network { namespace callhandler { class HOST_SW_API TagP25Data; } }
@ -81,6 +85,9 @@ public:
int run(); int run();
private: private:
#if defined(CATCH2_TEST_COMPILATION)
friend class FNETestHooks;
#endif
const std::string& m_confFile; const std::string& m_confFile;
yaml::Node m_conf; yaml::Node m_conf;

@ -20,7 +20,7 @@
#if !defined(__FNE_AFFILIATION_LOOKUP_H__) #if !defined(__FNE_AFFILIATION_LOOKUP_H__)
#define __FNE_AFFILIATION_LOOKUP_H__ #define __FNE_AFFILIATION_LOOKUP_H__
#include "Defines.h" #include "fne/Defines.h"
#include "common/lookups/AffiliationLookup.h" #include "common/lookups/AffiliationLookup.h"
#include "common/lookups/ChannelLookup.h" #include "common/lookups/ChannelLookup.h"

@ -24,6 +24,14 @@
#include <map> #include <map>
#include <shared_mutex> #include <shared_mutex>
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class FNETestHooks;
#endif
namespace network namespace network
{ {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -275,6 +283,9 @@ namespace network
DECLARE_PROPERTY_PLAIN(json::object, config); DECLARE_PROPERTY_PLAIN(json::object, config);
private: private:
#if defined(CATCH2_TEST_COMPILATION)
friend class ::FNETestHooks;
#endif
mutable std::mutex m_peerLockMtx; mutable std::mutex m_peerLockMtx;
std::map<uint64_t, AdaptiveJitterBuffer*> m_jitterBuffers; std::map<uint64_t, AdaptiveJitterBuffer*> m_jitterBuffers;

@ -30,6 +30,10 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class FNETestHooks;
#endif
class HOST_SW_API HostFNE; class HOST_SW_API HostFNE;
namespace network namespace network
@ -99,6 +103,9 @@ namespace network
void close() override; void close() override;
private: private:
#if defined(CATCH2_TEST_COMPILATION)
friend class ::FNETestHooks;
#endif
friend class TrafficNetwork; friend class TrafficNetwork;
TrafficNetwork* m_trafficNetwork; TrafficNetwork* m_trafficNetwork;
HostFNE* m_host; HostFNE* m_host;

@ -16,7 +16,7 @@
#if !defined(__PEER_NETWORK_H__) #if !defined(__PEER_NETWORK_H__)
#define __PEER_NETWORK_H__ #define __PEER_NETWORK_H__
#include "Defines.h" #include "fne/Defines.h"
#include "common/lookups/PeerListLookup.h" #include "common/lookups/PeerListLookup.h"
#include "common/network/Network.h" #include "common/network/Network.h"
#include "common/network/PacketBuffer.h" #include "common/network/PacketBuffer.h"

@ -195,7 +195,9 @@ TrafficNetwork::TrafficNetwork(HostFNE* host, const std::string& address, uint16
** Initialize Threads ** Initialize Threads
*/ */
#if !defined(CATCH2_TEST_COMPILATION)
Thread::runAsThread(this, threadParrotHandler); Thread::runAsThread(this, threadParrotHandler);
#endif
} }
/* Finalizes a instance of the TrafficNetwork class. */ /* Finalizes a instance of the TrafficNetwork class. */

@ -57,6 +57,10 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class FNETestHooks;
#endif
class HOST_SW_API HostFNE; class HOST_SW_API HostFNE;
class HOST_SW_API RESTAPI; class HOST_SW_API RESTAPI;
namespace network { namespace callhandler { class HOST_SW_API TagDMRData; } } namespace network { namespace callhandler { class HOST_SW_API TagDMRData; } }
@ -310,6 +314,9 @@ namespace network
void setPeerReplica(bool replica); void setPeerReplica(bool replica);
private: private:
#if defined(CATCH2_TEST_COMPILATION)
friend class ::FNETestHooks;
#endif
friend class MetadataNetwork; friend class MetadataNetwork;
friend class callhandler::TagDMRData; friend class callhandler::TagDMRData;
friend class callhandler::packetdata::DMRPacketData; friend class callhandler::packetdata::DMRPacketData;

@ -14,6 +14,8 @@
#include "fne/ActivityLog.h" #include "fne/ActivityLog.h"
#include "HostFNE.h" #include "HostFNE.h"
#include <fstream>
using namespace network; using namespace network;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -43,7 +43,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace dmr namespace dmr
{ {
@ -305,7 +307,9 @@ namespace dmr
private: private:
friend class Slot; friend class Slot;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
bool m_authoritative; bool m_authoritative;
bool m_supervisor; bool m_supervisor;

@ -41,7 +41,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace dmr namespace dmr
{ {
@ -345,7 +347,9 @@ namespace dmr
private: private:
friend class Control; friend class Control;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
friend class packet::Voice; friend class packet::Voice;
packet::Voice* m_voice; packet::Voice* m_voice;
friend class packet::Data; friend class packet::Data;

@ -51,7 +51,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace nxdn namespace nxdn
{ {
@ -266,7 +268,9 @@ namespace nxdn
private: private:
friend class packet::Voice; friend class packet::Voice;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
packet::Voice* m_voice; packet::Voice* m_voice;
friend class packet::Data; friend class packet::Data;
packet::Data* m_data; packet::Data* m_data;

@ -56,7 +56,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace p25 namespace p25
{ {
@ -284,7 +286,9 @@ namespace p25
private: private:
friend class packet::Voice; friend class packet::Voice;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
packet::Voice* m_voice; packet::Voice* m_voice;
friend class packet::Data; friend class packet::Data;
packet::Data* m_data; packet::Data* m_data;

@ -31,7 +31,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace p25 namespace p25
{ {
@ -87,7 +89,9 @@ namespace p25
protected: protected:
friend class packet::ControlSignaling; friend class packet::ControlSignaling;
friend class p25::Control; friend class p25::Control;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
Control* m_p25; Control* m_p25;
uint32_t m_rfFrames; uint32_t m_rfFrames;

@ -28,7 +28,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace p25 namespace p25
{ {
@ -102,7 +104,9 @@ namespace p25
private: private:
friend class p25::phase2::Slot; friend class p25::phase2::Slot;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
p25::phase2::Slot* m_slot; p25::phase2::Slot* m_slot;

@ -26,7 +26,13 @@
#include <cstdint> #include <cstdint>
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace p25 namespace p25
{ {
@ -172,7 +178,9 @@ namespace p25
private: private:
friend class Slot; friend class Slot;
friend class packet::phase2::Voice; friend class packet::phase2::Voice;
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
/* Interfaces */ /* Interfaces */
modem::Modem* m_modem; modem::Modem* m_modem;

@ -34,7 +34,9 @@
// Class Prototypes // Class Prototypes
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if defined(CATCH2_TEST_COMPILATION)
class HostTestHooks; class HostTestHooks;
#endif
namespace p25 namespace p25
{ {
@ -178,7 +180,9 @@ namespace p25
lookups::P25AffiliationLookup* affiliations, ::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup); lookups::P25AffiliationLookup* affiliations, ::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup);
private: private:
#if defined(CATCH2_TEST_COMPILATION)
friend class ::HostTestHooks; friend class ::HostTestHooks;
#endif
friend class phase2::Control; friend class phase2::Control;
friend class packet::phase2::Voice; friend class packet::phase2::Voice;
packet::phase2::Voice m_voice; packet::phase2::Voice m_voice;

@ -18,4 +18,6 @@ file(GLOB dvmtests_SRC
"tests/p25/*.cpp" "tests/p25/*.cpp"
"tests/nxdn/*.cpp" "tests/nxdn/*.cpp"
"tests/network/*.cpp" "tests/network/*.cpp"
"tests/fne/*.h"
"tests/fne/*.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 <catch2/catch_test_macros.hpp>
#include "fne/FNETestHooks.h"
#include "fne/HostFNE.h"
#include <string>
#include <vector>
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief Test harness for FNE network tests.
*/
class FNEHarness {
public:
/**
* @brief Initializes a new instance of the FNEHarness class.
*/
FNEHarness() :
configFile("fne-test.yml"),
host(configFile),
traffic(&host, "127.0.0.1", 62031U, 999999U, "test-password", "test-fne",
false, false, false, false, true, true, true, true, true,
0U, false, true, true, 5U, 10U, 2U),
metadata(&host, &traffic, "127.0.0.1", 62032U, 2U)
{
/* stub */
}
/**
* @brief Finalizes a instance of the FNEHarness class.
*/
~FNEHarness()
{
FNETestHooks::clearPeers(traffic);
}
std::string configFile;
HostFNE host;
network::TrafficNetwork traffic;
network::MetadataNetwork metadata;
};
TEST_CASE("FNE test hooks expose peer connection state", "[fne][hooks]")
{
FNEHarness harness;
FNETestHooks::addPeer(harness.traffic, 1001U, network::NET_STAT_WAITING_AUTHORISATION);
REQUIRE(FNETestHooks::hasPeer(harness.traffic, 1001U));
REQUIRE(FNETestHooks::peerCount(harness.traffic) == 1U);
REQUIRE(FNETestHooks::peerState(harness.traffic, 1001U) == network::NET_STAT_WAITING_AUTHORISATION);
}
TEST_CASE("FNE traffic dispatcher rejects truncated pre-authentication packets", "[fne][hooks][security]")
{
FNEHarness harness;
FNETestHooks::addPeer(harness.traffic, 1001U, network::NET_STAT_WAITING_AUTHORISATION);
REQUIRE_NOTHROW(FNETestHooks::dispatchTraffic(harness.traffic, network::NET_FUNC::RPTK,
network::NET_SUBFUNC::NOP, 1001U, std::vector<uint8_t>(8U)));
REQUIRE(FNETestHooks::peerState(harness.traffic, 1001U) == network::NET_STAT_WAITING_AUTHORISATION);
REQUIRE_NOTHROW(FNETestHooks::dispatchTraffic(harness.traffic, network::NET_FUNC::RPTC,
network::NET_SUBFUNC::NOP, 1001U, std::vector<uint8_t>(8U)));
REQUIRE(FNETestHooks::peerState(harness.traffic, 1001U) == network::NET_STAT_WAITING_AUTHORISATION);
}
TEST_CASE("FNE metadata dispatcher rejects truncated log transfers", "[fne][hooks][security]")
{
FNEHarness harness;
FNETestHooks::addPeer(harness.traffic, 1001U, network::NET_STAT_RUNNING, true);
REQUIRE_NOTHROW(FNETestHooks::dispatchMetadata(harness.traffic, harness.metadata,
network::NET_FUNC::TRANSFER, network::NET_SUBFUNC::TRANSFER_SUBFUNC_ACTIVITY,
1001U, std::vector<uint8_t>(11U)));
REQUIRE_NOTHROW(FNETestHooks::dispatchMetadata(harness.traffic, harness.metadata,
network::NET_FUNC::TRANSFER, network::NET_SUBFUNC::TRANSFER_SUBFUNC_DIAG,
1001U, std::vector<uint8_t>(10U)));
REQUIRE(FNETestHooks::peerState(harness.traffic, 1001U) == network::NET_STAT_RUNNING);
}

@ -0,0 +1,183 @@
// 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 "fne/FNETestHooks.h"
#include "fne/HostFNE.h"
#include <cstring>
#include <chrono>
#include <stdexcept>
using namespace network;
// ---------------------------------------------------------------------------
// Global Variables
// ---------------------------------------------------------------------------
bool g_promiscuousHub = false;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/**
* @brief Initializes an instance of the HostFNE class.
*/
HostFNE::HostFNE(const std::string& confFile) :
m_confFile(confFile), m_conf(), m_network(nullptr), m_mdNetwork(nullptr),
m_vtunEnabled(false), m_packetDataMode(PacketDataMode::PROJECT25),
#if !defined(_WIN32)
m_tun(nullptr),
#endif
m_dmrEnabled(false), m_p25Enabled(false), m_p25P2Enabled(false),
m_nxdnEnabled(false), m_analogEnabled(false), m_ridLookup(nullptr),
m_tidLookup(nullptr), m_peerListLookup(nullptr), m_adjSiteMapLookup(nullptr),
m_cryptoLookup(nullptr), m_peerNetworks(), m_pingTime(5U), m_maxMissedPings(5U),
m_updateLookupTime(10U), m_peerReplicaSavesACL(false),
m_allowActivityTransfer(false), m_allowDiagnosticTransfer(false), m_RESTAPI(nullptr)
{
/* stub */
}
/**
* @brief Finalizes an instance of the HostFNE class.
*/
HostFNE::~HostFNE() = default;
/**
* @brief Adds a peer to the specified TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer to add.
* @param state The connection state of the peer.
* @param connected Whether the peer is connected.
* @return Reference to the added FNEPeerConnection.
*/
FNEPeerConnection& FNETestHooks::addPeer(TrafficNetwork& network, uint32_t peerId,
NET_CONN_STATUS state, bool connected)
{
FNEPeerConnection* connection = new FNEPeerConnection();
connection->m_id = peerId;
connection->m_connectionState = state;
connection->m_connected = connected;
network.m_peers[peerId] = connection;
return *connection;
}
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
/**
* @brief Checks if the specified peer exists in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer to check.
* @return True if the peer exists, false otherwise.
*/
bool FNETestHooks::hasPeer(const TrafficNetwork& network, uint32_t peerId)
{
return network.m_peers.find(peerId) != network.m_peers.end();
}
/**
* @brief Retrieves the number of peers in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @return The number of peers.
*/
size_t FNETestHooks::peerCount(const TrafficNetwork& network)
{
return network.m_peers.size();
}
/**
* @brief Retrieves the connection state of the specified peer.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer.
* @return The connection state of the peer.
*/
NET_CONN_STATUS FNETestHooks::peerState(const TrafficNetwork& network, uint32_t peerId)
{
auto it = network.m_peers.find(peerId);
if (it == network.m_peers.end() || it->second == nullptr)
throw std::out_of_range("peer does not exist");
return it->second->connectionState();
}
/**
* @brief Clears all peers from the specified TrafficNetwork.
* @param network The TrafficNetwork instance.
*/
void FNETestHooks::clearPeers(TrafficNetwork& network)
{
for (auto peer : network.m_peers)
delete peer.second;
network.m_peers.clear();
}
/**
* @brief Creates a NetPacketRequest for the specified network, metadata, function, subFunction, peerId, and packet.
* @param network The TrafficNetwork instance.
* @param metadata The MetadataNetwork instance (can be nullptr).
* @param function The network function.
* @param subFunction The network sub-function.
* @param peerId The ID of the peer.
* @param packet The packet data.
* @return Pointer to the created NetPacketRequest.
*/
static NetPacketRequest* makeRequest(TrafficNetwork& network, MetadataNetwork* metadata,
NET_FUNC::ENUM function, NET_SUBFUNC::ENUM subFunction, uint32_t peerId,
const std::vector<uint8_t>& packet)
{
NetPacketRequest* request = new NetPacketRequest();
request->obj = &network;
request->metadataObj = metadata;
request->peerId = peerId;
request->fneHeader.setFunction(function);
request->fneHeader.setSubFunction(subFunction);
request->fneHeader.setPeerId(peerId);
request->fneHeader.setStreamId(1U);
request->rtpHeader.setSSRC(peerId);
request->pktRxTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
request->length = static_cast<int>(packet.size());
if (!packet.empty()) {
request->buffer = new uint8_t[packet.size()];
::memcpy(request->buffer, packet.data(), packet.size());
}
return request;
}
/**
* @brief Dispatches a traffic packet to the specified TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param function The network function.
* @param subFunction The network sub-function.
* @param peerId The ID of the peer.
* @param packet The packet data.
*/
void FNETestHooks::dispatchTraffic(TrafficNetwork& network, NET_FUNC::ENUM function,
NET_SUBFUNC::ENUM subFunction, uint32_t peerId, const std::vector<uint8_t>& packet)
{
TrafficNetwork::taskNetworkRx(makeRequest(network, nullptr, function, subFunction, peerId, packet));
}
/**
* @brief Dispatches a metadata packet to the specified TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param metadata The MetadataNetwork instance.
* @param function The network function.
* @param subFunction The network sub-function.
* @param peerId The ID of the peer.
* @param packet The packet data.
*/
void FNETestHooks::dispatchMetadata(TrafficNetwork& network, MetadataNetwork& metadata,
NET_FUNC::ENUM function, NET_SUBFUNC::ENUM subFunction, uint32_t peerId,
const std::vector<uint8_t>& packet)
{
MetadataNetwork::taskNetworkRx(makeRequest(network, &metadata, function, subFunction, peerId, packet));
}

@ -0,0 +1,88 @@
// 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
*
*/
#if !defined(__FNE_TEST_HOOKS_H__)
#define __FNE_TEST_HOOKS_H__
#include "fne/network/MetadataNetwork.h"
#include "fne/network/TrafficNetwork.h"
#include <cstdint>
#include <vector>
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief Test hooks for the FNE network components.
*/
class FNETestHooks {
public:
/**
* @brief Adds a peer to the specified TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer to add.
* @param state The connection state of the peer.
* @param connected Whether the peer is connected.
* @return Reference to the added FNEPeerConnection.
*/
static network::FNEPeerConnection& addPeer(network::TrafficNetwork& network, uint32_t peerId,
network::NET_CONN_STATUS state, bool connected = false);
/**
* @brief Checks if the specified peer exists in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer to check.
* @return True if the peer exists, false otherwise.
*/
static bool hasPeer(const network::TrafficNetwork& network, uint32_t peerId);
/**
* @brief Retrieves the number of peers in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @return The number of peers.
*/
static size_t peerCount(const network::TrafficNetwork& network);
/**
* @brief Retrieves the connection state of the specified peer.
* @param network The TrafficNetwork instance.
* @param peerId The ID of the peer.
* @return The connection state of the peer.
*/
static network::NET_CONN_STATUS peerState(const network::TrafficNetwork& network, uint32_t peerId);
/**
* @brief Clears all peers from the TrafficNetwork.
* @param network The TrafficNetwork instance.
*/
static void clearPeers(network::TrafficNetwork& network);
/**
* @brief Dispatches a traffic packet to the specified peer in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param function The network function.
* @param subFunction The network sub-function.
* @param peerId The ID of the peer.
* @param packet The packet data.
*/
static void dispatchTraffic(network::TrafficNetwork& network, network::NET_FUNC::ENUM function,
network::NET_SUBFUNC::ENUM subFunction, uint32_t peerId, const std::vector<uint8_t>& packet);
/**
* @brief Dispatches a metadata packet to the specified peer in the TrafficNetwork.
* @param network The TrafficNetwork instance.
* @param metadata The MetadataNetwork instance.
* @param function The network function.
* @param subFunction The network sub-function.
* @param peerId The ID of the peer.
* @param packet The packet data.
*/
static void dispatchMetadata(network::TrafficNetwork& network, network::MetadataNetwork& metadata,
network::NET_FUNC::ENUM function, network::NET_SUBFUNC::ENUM subFunction, uint32_t peerId,
const std::vector<uint8_t>& packet);
};
#endif // __FNE_TEST_HOOKS_H__
Loading…
Cancel
Save

Powered by TurnKey Linux.