blob: 3bb6ebc3f3e901d5cd796b6e8886274207aebd06 [file]
/*
*
* Copyright (c) 2026 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <pw_unit_test/framework.h>
#include <lib/core/StringBuilderAdapters.h>
#include <lib/dnssd/uld/DeleteRecord.h>
#include <lib/dnssd/uld/KeyRecord.h>
#include <lib/dnssd/uld/OptRecord.h>
#include <lib/dnssd/uld/Sig0Record.h>
#include <lib/dnssd/uld/UpdateBuilder.h>
#include <lib/dnssd/wire/records/Ptr.h>
#include <lib/dnssd/wire/records/Srv.h>
#include <cstring>
namespace {
using namespace chip;
using namespace chip::Dnssd;
using namespace chip::Dnssd::Uld;
const QNamePart kZone[] = { "default", "service", "arpa" };
const QNamePart kService[] = { "foo", "_matterc", "_udp", "local" };
const QNamePart kInstance[] = { "inst", "_matterc", "_udp", "local" };
const QNamePart kHost[] = { "host", "local" };
TEST(TestUpdateBuilder, BeginSetsOpcodeUpdate)
{
uint8_t buffer[256];
UpdateBuilder builder(buffer, sizeof(buffer));
builder.Begin(0x1234);
EXPECT_EQ(builder.Header().GetMessageId(), 0x1234);
EXPECT_TRUE(builder.Header().GetFlags().IsQuery());
EXPECT_EQ(builder.Header().GetFlags().GetOpcode(), Opcode::kUpdate);
ByteSpan packet;
EXPECT_EQ(builder.GetPacket(packet), CHIP_NO_ERROR);
EXPECT_EQ(packet.size(), HeaderRef::kSizeBytes);
}
TEST(TestUpdateBuilder, MinimalUpdateWithZoneDeleteAddOptAndSig)
{
uint8_t buffer[512];
uint8_t signature[kP256RawSignatureSize] = {};
Crypto::P256Keypair keypair;
ASSERT_EQ(keypair.Initialize(Crypto::ECPKeyTarget::ECDSA), CHIP_NO_ERROR);
UpdateBuilder builder(buffer, sizeof(buffer));
builder.Begin(0xABCD);
DeleteRrsetRecord delAny(kHost, QType::ANY);
PtrResourceRecord ptr(kService, kInstance);
SrvResourceRecord srv(kInstance, kHost, 5540);
KeyResourceRecord key(kHost, keypair.Pubkey());
OptLeaseRecord opt(/*udpPayloadSize=*/1232, /*leaseSeconds=*/7200, /*keyLeaseSeconds=*/86400);
Sig0ResourceRecord sig(kHost, ByteSpan(signature));
builder.AddZone(kZone);
builder.AddUpdate(delAny);
builder.AddUpdate(ptr);
builder.AddUpdate(srv);
builder.AddUpdate(key);
builder.AddAdditional(opt);
builder.AddAdditional(sig);
EXPECT_EQ(builder.Header().GetQueryCount(), 1); // ZONE
EXPECT_EQ(builder.Header().GetAnswerCount(), 0); // Prerequisite
EXPECT_EQ(builder.Header().GetAuthorityCount(), 4); // Update
EXPECT_EQ(builder.Header().GetAdditionalCount(), 2); // OPT + SIG
// Header flags: opcode UPDATE at offset 2.
EXPECT_EQ(buffer[2], 0x28); // QR=0, OPCODE=5
EXPECT_EQ(buffer[3], 0x00);
ByteSpan packet;
EXPECT_EQ(builder.GetPacket(packet), CHIP_NO_ERROR);
EXPECT_GT(packet.size(), HeaderRef::kSizeBytes);
ByteSpan samePacket;
EXPECT_EQ(builder.GetPacket(samePacket), CHIP_NO_ERROR);
EXPECT_EQ(samePacket.data(), packet.data());
EXPECT_EQ(samePacket.size(), packet.size());
}
TEST(TestUpdateBuilder, ReportsBufferTooSmall)
{
uint8_t buffer[HeaderRef::kSizeBytes];
UpdateBuilder builder(buffer, sizeof(buffer));
builder.Begin(1);
builder.AddZone(kZone);
ByteSpan packet;
EXPECT_EQ(builder.GetPacket(packet), CHIP_ERROR_BUFFER_TOO_SMALL);
}
TEST(TestUpdateBuilder, BeginClearsBufferOverflow)
{
uint8_t buffer[64];
UpdateBuilder builder(buffer, sizeof(buffer));
builder.Begin(1);
builder.AddZone(kZone);
DeleteRrsetRecord record(kHost, QType::TXT);
builder.AddUpdate(record);
builder.AddUpdate(record);
ByteSpan packet;
EXPECT_EQ(builder.GetPacket(packet), CHIP_ERROR_BUFFER_TOO_SMALL);
builder.Begin(2);
EXPECT_EQ(builder.GetPacket(packet), CHIP_NO_ERROR);
EXPECT_EQ(packet.size(), HeaderRef::kSizeBytes);
EXPECT_EQ(builder.Header().GetMessageId(), 2);
}
} // namespace