add more tests;

pull/128/head
Bryan Biedenkapp 3 months ago
parent 794e8b71e5
commit 105e77d7bd

@ -0,0 +1,131 @@
// 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 "host/Defines.h"
#include "common/p25/P25Defines.h"
#include "common/p25/dfsi/DFSIDefines.h"
#include "common/p25/dfsi/frames/StartOfStream.h"
#include "common/p25/dfsi/frames/FullRateVoice.h"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
using namespace p25;
using namespace p25::defines;
using namespace p25::dfsi;
using namespace p25::dfsi::defines;
using namespace p25::dfsi::frames;
TEST_CASE("DFSI StartOfStream and FullRateVoice encode/decode round-trips", "[p25][dfsi][frames]")
{
SECTION("StartOfStream preserves NID and low nibble error count") {
StartOfStream tx;
tx.setNID(0xA55AU);
tx.setErrorCount(0x1DU);
uint8_t buffer[StartOfStream::LENGTH] = { 0U };
tx.encode(buffer);
StartOfStream rx;
REQUIRE(rx.decode(buffer));
REQUIRE(rx.getNID() == 0xA55AU);
REQUIRE(rx.getErrorCount() == 0x0DU);
}
SECTION("FullRateVoice LDU1 voice3 includes four additional bytes") {
FullRateVoice tx;
tx.setFrameType(DFSIFrameType::LDU1_VOICE3);
tx.setTotalErrors(5U);
tx.setMuteFrame(true);
tx.setLostFrame(false);
tx.setSuperframeCnt(2U);
tx.setBusy(DFSI_BUSY_BITS_BUSY);
for (uint8_t i = 0U; i < FullRateVoice::IMBE_BUF_LEN; i++)
tx.imbeData[i] = (uint8_t)(0x20U + i);
tx.additionalData[0U] = 0x11U;
tx.additionalData[1U] = 0x22U;
tx.additionalData[2U] = 0x33U;
tx.additionalData[3U] = 0x44U;
uint8_t buffer[FullRateVoice::LENGTH] = { 0U };
tx.encode(buffer);
FullRateVoice rx;
REQUIRE(rx.decode(buffer));
REQUIRE(rx.getFrameType() == DFSIFrameType::LDU1_VOICE3);
REQUIRE(rx.getLength() == FullRateVoice::LENGTH);
REQUIRE(rx.getTotalErrors() == 5U);
REQUIRE(rx.getMuteFrame() == true);
REQUIRE(rx.getLostFrame() == false);
REQUIRE(rx.getSuperframeCnt() == 2U);
REQUIRE(rx.getBusy() == DFSI_BUSY_BITS_BUSY);
REQUIRE(::memcmp(rx.imbeData, tx.imbeData, FullRateVoice::IMBE_BUF_LEN) == 0);
REQUIRE(::memcmp(rx.additionalData, tx.additionalData, FullRateVoice::ADDITIONAL_LENGTH) == 0);
}
SECTION("FullRateVoice LDU1 voice9 uses three-byte additional payload") {
FullRateVoice tx;
tx.setFrameType(DFSIFrameType::LDU1_VOICE9);
tx.setTotalErrors(1U);
tx.setMuteFrame(false);
tx.setLostFrame(true);
tx.setSuperframeCnt(1U);
tx.setBusy(DFSI_BUSY_BITS_INBOUND);
for (uint8_t i = 0U; i < FullRateVoice::IMBE_BUF_LEN; i++)
tx.imbeData[i] = (uint8_t)(0x40U + i);
tx.additionalData[0U] = 0xAAU;
tx.additionalData[1U] = 0xBBU;
tx.additionalData[2U] = 0xCCU;
tx.additionalData[3U] = 0xDDU;
uint8_t buffer[FullRateVoice::LENGTH_918] = { 0U };
tx.encode(buffer);
FullRateVoice rx;
REQUIRE(rx.decode(buffer));
REQUIRE(rx.getFrameType() == DFSIFrameType::LDU1_VOICE9);
REQUIRE(rx.getLength() == FullRateVoice::LENGTH_918);
REQUIRE(rx.additionalData != nullptr);
REQUIRE(rx.additionalData[0U] == 0xAAU);
REQUIRE(rx.additionalData[1U] == 0xBBU);
REQUIRE(rx.additionalData[2U] == 0xCCU);
REQUIRE(rx.additionalData[3U] == 0x00U);
}
SECTION("FullRateVoice LDU1 voice2 has no additional payload") {
FullRateVoice tx;
tx.setFrameType(DFSIFrameType::LDU1_VOICE2);
tx.setTotalErrors(7U);
tx.setMuteFrame(false);
tx.setLostFrame(false);
tx.setSuperframeCnt(3U);
tx.setBusy(DFSI_BUSY_BITS_IDLE);
for (uint8_t i = 0U; i < FullRateVoice::IMBE_BUF_LEN; i++)
tx.imbeData[i] = (uint8_t)(0x60U + i);
uint8_t buffer[FullRateVoice::LENGTH_121011] = { 0U };
tx.encode(buffer);
FullRateVoice rx;
REQUIRE(rx.decode(buffer));
REQUIRE(rx.getFrameType() == DFSIFrameType::LDU1_VOICE2);
REQUIRE(rx.getLength() == FullRateVoice::LENGTH_121011);
REQUIRE(rx.additionalData == nullptr);
}
}

@ -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 "host/Defines.h"
#include "common/p25/P25Defines.h"
#include "common/p25/kmm/KMMFactory.h"
#include "common/p25/kmm/KMMHello.h"
#include "common/p25/kmm/KMMNoService.h"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
using namespace p25;
using namespace p25::defines;
using namespace p25::kmm;
TEST_CASE("KMM factory decodes encoded HELLO and NO_SERVICE frames", "[p25][kmm][factory]")
{
SECTION("HELLO frame round-trips with message number") {
KMMHello tx;
tx.setDstLLId(0x123456U);
tx.setSrcLLId(0x654321U);
tx.setMessageNumber(0x1122U);
tx.setFlag(KMM_HelloFlag::REKEY_REQUEST_NO_UKEK);
UInt8Array buffer = std::make_unique<uint8_t[]>(tx.fullLength());
::memset(buffer.get(), 0x00U, tx.fullLength());
tx.encode(buffer.get());
std::unique_ptr<KMMFrame> base = KMMFactory::create(buffer.get());
REQUIRE(base != nullptr);
KMMHello* rx = dynamic_cast<KMMHello*>(base.get());
REQUIRE(rx != nullptr);
REQUIRE(rx->getMessageId() == KMM_MessageType::HELLO);
REQUIRE(rx->getFlag() == KMM_HelloFlag::REKEY_REQUEST_NO_UKEK);
REQUIRE(rx->getDstLLId() == 0x123456U);
REQUIRE(rx->getSrcLLId() == 0x654321U);
REQUIRE(rx->getHasMessageNumber() == true);
REQUIRE(rx->getMessageNumber() == 0x1122U);
}
SECTION("NO_SERVICE frame round-trips") {
KMMNoService tx;
tx.setDstLLId(0x010203U);
tx.setSrcLLId(0xA0B0C0U);
UInt8Array buffer = std::make_unique<uint8_t[]>(tx.fullLength());
::memset(buffer.get(), 0x00U, tx.fullLength());
tx.encode(buffer.get());
std::unique_ptr<KMMFrame> base = KMMFactory::create(buffer.get());
REQUIRE(base != nullptr);
KMMNoService* rx = dynamic_cast<KMMNoService*>(base.get());
REQUIRE(rx != nullptr);
REQUIRE(rx->getMessageId() == KMM_MessageType::NO_SERVICE);
REQUIRE(rx->getDstLLId() == 0x010203U);
REQUIRE(rx->getSrcLLId() == 0xA0B0C0U);
}
SECTION("Factory returns nullptr for unknown message ID") {
uint8_t buffer[16U] = { 0U };
buffer[0U] = 0xFFU;
std::unique_ptr<KMMFrame> frame = KMMFactory::create(buffer);
REQUIRE(frame == nullptr);
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.