blob: 1bd59cc62727f213ce84d125b589e46e34390185 [file] [log] [blame]
/*
*
* Copyright (c) 2021 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 <lib/dnssd/Advertiser.h>
#include <string>
#include <utility>
#include <lib/dnssd/Advertiser.h>
#include <lib/dnssd/MinimalMdnsServer.h>
#include <lib/dnssd/minimal_mdns/Query.h>
#include <lib/dnssd/minimal_mdns/QueryBuilder.h>
#include <lib/dnssd/minimal_mdns/core/QName.h>
#include <lib/dnssd/minimal_mdns/records/Ptr.h>
#include <lib/dnssd/minimal_mdns/records/Srv.h>
#include <lib/dnssd/minimal_mdns/records/Txt.h>
#include <lib/dnssd/minimal_mdns/tests/CheckOnlyServer.h>
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestRegistration.h>
#include <system/SystemPacketBuffer.h>
#include <transport/raw/tests/NetworkTestHelpers.h>
#include <nlunit-test.h>
namespace {
using namespace std;
using namespace chip;
using namespace chip::Dnssd;
using namespace mdns::Minimal;
using namespace mdns::Minimal::test;
// Used for everything.
const QNamePart kDnsSdQueryParts[] = { "_services", "_dns-sd", "_udp", "local" };
const FullQName kDnsSdQueryName = FullQName(kDnsSdQueryParts);
constexpr size_t kMdnsMaxPacketSize = 512;
const uint8_t kMac[kMaxMacSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const QNamePart kHostnameParts[] = { "0102030405060708", "local" };
const FullQName kHostnameName = FullQName(kHostnameParts);
// Operational records and queries.
const QNamePart kMatterOperationalQueryParts[3] = { "_matter", "_tcp", "local" };
const FullQName kMatterOperationalQueryName = FullQName(kMatterOperationalQueryParts);
const PeerId kPeerId1 = PeerId().SetCompressedFabricId(0xBEEFBEEFF00DF00D).SetNodeId(0x1111222233334444);
const PeerId kPeerId2 = PeerId().SetCompressedFabricId(0x5555666677778888).SetNodeId(0x1212343456567878);
const PeerId kPeerId3 = PeerId().SetCompressedFabricId(0x3333333333333333).SetNodeId(0x3333333333333333);
const PeerId kPeerId4 = PeerId().SetCompressedFabricId(0x4444444444444444).SetNodeId(0x4444444444444444);
const PeerId kPeerId5 = PeerId().SetCompressedFabricId(0x5555555555555555).SetNodeId(0x5555555555555555);
const PeerId kPeerId6 = PeerId().SetCompressedFabricId(0x6666666666666666).SetNodeId(0x6666666666666666);
const QNamePart kInstanceNameParts1[] = { "BEEFBEEFF00DF00D-1111222233334444", "_matter", "_tcp", "local" };
const FullQName kInstanceName1 = FullQName(kInstanceNameParts1);
const QNamePart kInstanceNameParts2[] = { "5555666677778888-1212343456567878", "_matter", "_tcp", "local" };
const FullQName kInstanceName2 = FullQName(kInstanceNameParts2);
const QNamePart kTxtRecordEmptyParts[] = { "=" };
const FullQName kTxtRecordEmptyName = FullQName(kTxtRecordEmptyParts);
const QNamePart kCompressedIdSubParts1[] = { "_IBEEFBEEFF00DF00D", "_sub", "_matter", "_tcp", "local" };
FullQName kCompressedIdSubName1 = FullQName(kCompressedIdSubParts1);
const QNamePart kCompressedIdSubParts2[] = { "_I5555666677778888", "_sub", "_matter", "_tcp", "local" };
FullQName kCompressedIdSubName2 = FullQName(kCompressedIdSubParts2);
PtrResourceRecord ptrServiceSubCompressedId1 = PtrResourceRecord(kDnsSdQueryName, kCompressedIdSubName1);
PtrResourceRecord ptrServiceSubCompressedId2 = PtrResourceRecord(kDnsSdQueryName, kCompressedIdSubName2);
OperationalAdvertisingParameters operationalParams1 =
OperationalAdvertisingParameters()
.SetPeerId(kPeerId1)
.SetMac(ByteSpan(kMac))
.SetPort(CHIP_PORT)
.EnableIpV4(true)
.SetTcpSupported(chip::Optional<bool>(false))
.SetLocalMRPConfig(Optional<ReliableMessageProtocolConfig>::Value(32_ms32, 30_ms32)); // Match SII, SAI below
OperationalAdvertisingParameters operationalParams2 =
OperationalAdvertisingParameters().SetPeerId(kPeerId2).SetMac(ByteSpan(kMac)).SetPort(CHIP_PORT).EnableIpV4(true);
OperationalAdvertisingParameters operationalParams3 =
OperationalAdvertisingParameters().SetPeerId(kPeerId3).SetMac(ByteSpan(kMac)).SetPort(CHIP_PORT).EnableIpV4(true);
OperationalAdvertisingParameters operationalParams4 =
OperationalAdvertisingParameters().SetPeerId(kPeerId4).SetMac(ByteSpan(kMac)).SetPort(CHIP_PORT).EnableIpV4(true);
OperationalAdvertisingParameters operationalParams5 =
OperationalAdvertisingParameters().SetPeerId(kPeerId5).SetMac(ByteSpan(kMac)).SetPort(CHIP_PORT).EnableIpV4(true);
OperationalAdvertisingParameters operationalParams6 =
OperationalAdvertisingParameters().SetPeerId(kPeerId6).SetMac(ByteSpan(kMac)).SetPort(CHIP_PORT).EnableIpV4(true);
const QNamePart txtOperational1Parts[] = { "SII=32", "SAI=30", "T=0" };
PtrResourceRecord ptrOperationalService = PtrResourceRecord(kDnsSdQueryName, kMatterOperationalQueryName);
PtrResourceRecord ptrOperational1 = PtrResourceRecord(kMatterOperationalQueryName, kInstanceName1);
SrvResourceRecord srvOperational1 = SrvResourceRecord(kInstanceName1, kHostnameName, CHIP_PORT);
TxtResourceRecord txtOperational1 = TxtResourceRecord(kInstanceName1, txtOperational1Parts);
PtrResourceRecord ptrOperational2 = PtrResourceRecord(kMatterOperationalQueryName, kInstanceName2);
SrvResourceRecord srvOperational2 = SrvResourceRecord(kInstanceName2, kHostnameName, CHIP_PORT);
TxtResourceRecord txtOperational2 = TxtResourceRecord(kInstanceName2, kTxtRecordEmptyName);
// Commissionable node records and queries.
const QNamePart kMatterCommissionableNodeQueryParts[3] = { "_matterc", "_udp", "local" };
const QNamePart kLongSubPartsFullLen[] = { "_L4094", "_sub", "_matterc", "_udp", "local" };
const QNamePart kShortSubPartsFullLen[] = { "_S15", "_sub", "_matterc", "_udp", "local" };
const QNamePart kCmSubParts[] = { "_CM", "_sub", "_matterc", "_udp", "local" };
const QNamePart kLongSubParts[] = { "_L22", "_sub", "_matterc", "_udp", "local" };
const QNamePart kShortSubParts[] = { "_S2", "_sub", "_matterc", "_udp", "local" };
const QNamePart kVendorSubParts[] = { "_V555", "_sub", "_matterc", "_udp", "local" };
const QNamePart kDeviceTypeSubParts[] = { "_T70000", "_sub", "_matterc", "_udp", "local" };
const FullQName kMatterCommissionableNodeQueryName = FullQName(kMatterCommissionableNodeQueryParts);
FullQName kLongSubFullLenName = FullQName(kLongSubPartsFullLen);
FullQName kShortSubFullLenName = FullQName(kShortSubPartsFullLen);
FullQName kCmSubName = FullQName(kCmSubParts);
FullQName kLongSubName = FullQName(kLongSubParts);
FullQName kShortSubName = FullQName(kShortSubParts);
FullQName kVendorSubName = FullQName(kVendorSubParts);
FullQName kDeviceTypeSubName = FullQName(kDeviceTypeSubParts);
PtrResourceRecord ptrCommissionableNodeService = PtrResourceRecord(kDnsSdQueryName, kMatterCommissionableNodeQueryName);
PtrResourceRecord ptrServiceSubLFullLen = PtrResourceRecord(kDnsSdQueryName, kLongSubFullLenName);
PtrResourceRecord ptrServiceSubSFullLen = PtrResourceRecord(kDnsSdQueryName, kShortSubFullLenName);
PtrResourceRecord ptrServiceSubCM = PtrResourceRecord(kDnsSdQueryName, kCmSubName);
PtrResourceRecord ptrServiceSubLong = PtrResourceRecord(kDnsSdQueryName, kLongSubName);
PtrResourceRecord ptrServiceSubShort = PtrResourceRecord(kDnsSdQueryName, kShortSubName);
PtrResourceRecord ptrServiceSubVendor = PtrResourceRecord(kDnsSdQueryName, kVendorSubName);
PtrResourceRecord ptrServiceSubDeviceType = PtrResourceRecord(kDnsSdQueryName, kDeviceTypeSubName);
// For commissioning, the instance name is chosen randomly by the advertiser, so we have to get this value from it. We can, however,
// pre-populate the records with the ptr.
char instanceNamePrefix[17];
QNamePart instanceNameParts[] = { instanceNamePrefix, "_matterc", "_udp", "local" };
FullQName instanceName = FullQName(instanceNameParts);
PtrResourceRecord ptrCommissionableNode = PtrResourceRecord(kMatterCommissionableNodeQueryName, instanceName);
SrvResourceRecord srvCommissionableNode = SrvResourceRecord(instanceName, kHostnameName, CHIP_PORT);
CommissionAdvertisingParameters commissionableNodeParamsSmall =
CommissionAdvertisingParameters()
.SetCommissionAdvertiseMode(CommssionAdvertiseMode::kCommissionableNode)
.SetMac(ByteSpan(kMac))
.SetLongDiscriminator(0xFFE)
.SetShortDiscriminator(0xF)
.SetCommissioningMode(CommissioningMode::kDisabled);
const QNamePart txtCommissionableNodeParamsSmallParts[] = { "CM=0", "D=4094" };
FullQName txtCommissionableNodeParamsSmallName = FullQName(txtCommissionableNodeParamsSmallParts);
TxtResourceRecord txtCommissionableNodeParamsSmall = TxtResourceRecord(instanceName, txtCommissionableNodeParamsSmallName);
CommissionAdvertisingParameters commissionableNodeParamsLargeBasic =
CommissionAdvertisingParameters()
.SetCommissionAdvertiseMode(CommssionAdvertiseMode::kCommissionableNode)
.SetMac(ByteSpan(kMac, sizeof(kMac)))
.SetLongDiscriminator(22)
.SetShortDiscriminator(2)
.SetVendorId(chip::Optional<uint16_t>(555))
.SetDeviceType(chip::Optional<uint32_t>(70000))
.SetCommissioningMode(CommissioningMode::kEnabledBasic)
.SetDeviceName(chip::Optional<const char *>("testy-test"))
.SetPairingHint(chip::Optional<uint16_t>(3))
.SetPairingInstruction(chip::Optional<const char *>("Pair me"))
.SetProductId(chip::Optional<uint16_t>(897))
.SetRotatingDeviceId(chip::Optional<const char *>("id_that_spins"));
QNamePart txtCommissionableNodeParamsLargeBasicParts[] = { "D=22", "VP=555+897", "CM=1", "DT=70000",
"DN=testy-test", "RI=id_that_spins", "PI=Pair me", "PH=3" };
FullQName txtCommissionableNodeParamsLargeBasicName = FullQName(txtCommissionableNodeParamsLargeBasicParts);
TxtResourceRecord txtCommissionableNodeParamsLargeBasic =
TxtResourceRecord(instanceName, txtCommissionableNodeParamsLargeBasicName);
CommissionAdvertisingParameters commissionableNodeParamsLargeEnhanced =
CommissionAdvertisingParameters()
.SetCommissionAdvertiseMode(CommssionAdvertiseMode::kCommissionableNode)
.SetMac(ByteSpan(kMac, sizeof(kMac)))
.SetLongDiscriminator(22)
.SetShortDiscriminator(2)
.SetVendorId(chip::Optional<uint16_t>(555))
.SetDeviceType(chip::Optional<uint32_t>(70000))
.SetCommissioningMode(CommissioningMode::kEnabledEnhanced)
.SetDeviceName(chip::Optional<const char *>("testy-test"))
.SetPairingHint(chip::Optional<uint16_t>(3))
.SetPairingInstruction(chip::Optional<const char *>("Pair me"))
.SetProductId(chip::Optional<uint16_t>(897))
.SetRotatingDeviceId(chip::Optional<const char *>("id_that_spins"))
.SetTcpSupported(chip::Optional<bool>(true))
// 3600005 is more than the max so should be adjusted down
.SetLocalMRPConfig(Optional<ReliableMessageProtocolConfig>::Value(3600000_ms32, 3600005_ms32));
QNamePart txtCommissionableNodeParamsLargeEnhancedParts[] = { "D=22", "VP=555+897", "CM=2", "DT=70000",
"DN=testy-test", "RI=id_that_spins", "PI=Pair me", "PH=3",
"SAI=3600000", "SII=3600000", "T=1" };
FullQName txtCommissionableNodeParamsLargeEnhancedName = FullQName(txtCommissionableNodeParamsLargeEnhancedParts);
TxtResourceRecord txtCommissionableNodeParamsLargeEnhanced =
TxtResourceRecord(instanceName, txtCommissionableNodeParamsLargeEnhancedName);
// Our server doesn't do anything with this, blank is fine.
Inet::IPPacketInfo packetInfo;
CHIP_ERROR SendQuery(FullQName qname)
{
System::PacketBufferHandle queryBuffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
if (queryBuffer.IsNull())
{
return CHIP_ERROR_NO_MEMORY;
}
QueryBuilder queryBuilder(std::move(queryBuffer));
queryBuilder.Header().SetMessageId(0);
Query query = Query(qname).SetClass(QClass::IN).SetType(QType::ANY);
queryBuilder.AddQuery(query);
queryBuffer = queryBuilder.ReleasePacket();
// Send the query to the advertiser directly.
BytesRange range = BytesRange(queryBuffer->Start(), queryBuffer->Start() + queryBuffer->DataLength());
GlobalMinimalMdnsServer::Instance().OnQuery(range, &packetInfo);
return CHIP_NO_ERROR;
}
void OperationalAdverts(nlTestSuite * inSuite, void * inContext)
{
auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.RemoveServices() == CHIP_NO_ERROR);
auto & server = static_cast<CheckOnlyServer &>(GlobalMinimalMdnsServer::Server());
server.SetTestSuite(inSuite);
server.Reset();
// Start a single operational advertiser
ChipLogProgress(Discovery, "Testing single operational advertiser");
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
// Test for PTR response to _services request.
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
// These check that the requested records added are sent out correctly.
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Want PTR response to _matter.tcp. We will also get the SRV and TXT as additionals.
// We won't get any A/AAAA because this is a test and we don't have addresses.
ChipLogProgress(Discovery, "Testing response to _matter._tcp.local");
server.Reset();
// For now, we don't check TXT records content, just that they exist. Operational currently
// sends a TXT record regardless of content being present or not.
server.AddExpectedRecord(&ptrOperational1);
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterOperationalQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to instance name");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
NL_TEST_ASSERT(inSuite, SendQuery(kInstanceName1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// If we try to re-advertise with the same operational parameters, we should not get duplicates
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
ChipLogProgress(Discovery, "Testing single operational advertiser with Advertise called twice");
// We should get a single PTR back for _services
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Same records should come back for _matter._tcp.local queries.
ChipLogProgress(Discovery, "Testing response to _matter._tcp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperational1);
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterOperationalQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Adding a second operational advertiser.
ChipLogProgress(Discovery, "Adding a second operational Advertiser");
server.Reset();
// Mac is the same, peer id is different
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams2) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
// For now, we'll get back two copies of the PTR. Not sure if that's totally correct, but for now, that's expected.
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
server.AddExpectedRecord(&ptrServiceSubCompressedId2);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Requests for _matter._tcp.local will respond with all records from both parameter sets
ChipLogProgress(Discovery, "Testing response to _matter._tcp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperational1);
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
server.AddExpectedRecord(&ptrOperational2);
server.AddExpectedRecord(&srvOperational2);
server.AddExpectedRecord(&txtOperational2);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterOperationalQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Requests for each SRV record should give only records specific to that fabric.
ChipLogProgress(Discovery, "Testing response to instance name for fabric 1");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
NL_TEST_ASSERT(inSuite, SendQuery(kInstanceName1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to instance name for fabric 2");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvOperational2);
server.AddExpectedRecord(&txtOperational2);
NL_TEST_ASSERT(inSuite, SendQuery(kInstanceName2) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// All devices should support at least 5 operational network additions (spec min)
// however larger devices may support more.
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams3) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams4) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams5) == CHIP_NO_ERROR);
}
void CommissionableAdverts(nlTestSuite * inSuite, void * inContext)
{
auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.RemoveServices() == CHIP_NO_ERROR);
auto & server = static_cast<CheckOnlyServer &>(GlobalMinimalMdnsServer::Server());
server.SetTestSuite(inSuite);
server.Reset();
// Start a single operational advertiser
ChipLogProgress(Discovery, "Testing commissionable advertiser");
// Start very basic - only the mandatory values (short and long discriminator and commissioning modes)
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(commissionableNodeParamsSmall) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
// Test for PTR response to _services request.
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local for small parameters");
server.AddExpectedRecord(&ptrCommissionableNodeService);
server.AddExpectedRecord(&ptrServiceSubLFullLen);
server.AddExpectedRecord(&ptrServiceSubSFullLen);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
// These check that the requested records added are sent out correctly.
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Want PTR response to _matterc._udp. We will also get the SRV and TXT as additionals.
// We won't get any A/AAAA because this is a test and we don't have addresses.
// First fill in the instance name - FullQNames already have this space included.
NL_TEST_ASSERT(inSuite,
mdnsAdvertiser.GetCommissionableInstanceName(instanceNamePrefix, sizeof(instanceNamePrefix)) == CHIP_NO_ERROR);
ChipLogProgress(Discovery, "Testing response to _matterc._udp.local for small parameters");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNode);
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsSmall);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterCommissionableNodeQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to instance name for small parameters");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsSmall);
NL_TEST_ASSERT(inSuite, SendQuery(instanceName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Add more parameters, check that the subtypes and TXT values get set correctly.
// Also check that we get proper values when the discriminators are small (no leading 0's)
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(commissionableNodeParamsLargeBasic) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local for large basic parameters");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNodeService);
server.AddExpectedRecord(&ptrServiceSubLong);
server.AddExpectedRecord(&ptrServiceSubShort);
server.AddExpectedRecord(&ptrServiceSubCM);
server.AddExpectedRecord(&ptrServiceSubVendor);
server.AddExpectedRecord(&ptrServiceSubDeviceType);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to _matterc._udp.local for large basic parameters");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNode);
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeBasic);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterCommissionableNodeQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to instance name for large basic parameters");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeBasic);
NL_TEST_ASSERT(inSuite, SendQuery(instanceName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(commissionableNodeParamsLargeEnhanced) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local for large enhanced parameters");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNodeService);
server.AddExpectedRecord(&ptrServiceSubLong);
server.AddExpectedRecord(&ptrServiceSubShort);
server.AddExpectedRecord(&ptrServiceSubCM);
server.AddExpectedRecord(&ptrServiceSubVendor);
server.AddExpectedRecord(&ptrServiceSubDeviceType);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to _matterc._udp.local for large enhanced parameters");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNode);
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeEnhanced);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterCommissionableNodeQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to instance name for large enhanced parameters");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeEnhanced);
NL_TEST_ASSERT(inSuite, SendQuery(instanceName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
}
void CommissionableAndOperationalAdverts(nlTestSuite * inSuite, void * inContext)
{
auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.RemoveServices() == CHIP_NO_ERROR);
auto & server = static_cast<CheckOnlyServer &>(GlobalMinimalMdnsServer::Server());
server.SetTestSuite(inSuite);
server.Reset();
// Add two operational and a commissionable and test that we get the correct values back.
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(operationalParams2) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.Advertise(commissionableNodeParamsLargeEnhanced) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, mdnsAdvertiser.FinalizeServiceUpdate() == CHIP_NO_ERROR);
// Services listing should have two operational ptrs, the base commissionable node ptr and the various _sub ptrs
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrCommissionableNodeService);
server.AddExpectedRecord(&ptrServiceSubLong);
server.AddExpectedRecord(&ptrServiceSubShort);
server.AddExpectedRecord(&ptrServiceSubCM);
server.AddExpectedRecord(&ptrServiceSubVendor);
server.AddExpectedRecord(&ptrServiceSubDeviceType);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
server.AddExpectedRecord(&ptrServiceSubCompressedId2);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Requests for _matter._tcp.local will respond with all records from both operational records, but no commissionable.
ChipLogProgress(Discovery, "Testing response to _matter._tcp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperational1);
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
server.AddExpectedRecord(&ptrOperational2);
server.AddExpectedRecord(&srvOperational2);
server.AddExpectedRecord(&txtOperational2);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterOperationalQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Responses to _matterc query should return commissionable node, but no operational.
ChipLogProgress(Discovery, "Testing response to _matterc._udp.local");
server.Reset();
server.AddExpectedRecord(&ptrCommissionableNode);
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeEnhanced);
NL_TEST_ASSERT(inSuite, SendQuery(kMatterCommissionableNodeQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
// Requests for each SRV record should give only records specific to that fabric.
ChipLogProgress(Discovery, "Testing response to operational instance name for fabric 1");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvOperational1);
server.AddExpectedRecord(&txtOperational1);
NL_TEST_ASSERT(inSuite, SendQuery(kInstanceName1) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to operational instance name for fabric 2");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvOperational2);
server.AddExpectedRecord(&txtOperational2);
NL_TEST_ASSERT(inSuite, SendQuery(kInstanceName2) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
ChipLogProgress(Discovery, "Testing response to commissionable instance name");
server.Reset();
// Just the SRV and TXT should return
server.AddExpectedRecord(&srvCommissionableNode);
server.AddExpectedRecord(&txtCommissionableNodeParamsLargeEnhanced);
NL_TEST_ASSERT(inSuite, SendQuery(instanceName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
}
const nlTest sTests[] = {
NL_TEST_DEF("OperationalAdverts", OperationalAdverts), //
NL_TEST_DEF("CommissionableNodeAdverts", CommissionableAdverts), //
NL_TEST_DEF("CommissionableAndOperationalAdverts", CommissionableAndOperationalAdverts), //
NL_TEST_SENTINEL() //
};
} // namespace
int TestAdvertiser(void)
{
chip::Platform::MemoryInit();
chip::Test::IOContext context;
context.Init();
nlTestSuite theSuite = { "AdvertiserImplMinimal", sTests, nullptr, nullptr };
CheckOnlyServer server(&theSuite);
test::ServerSwapper swapper(&server);
auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
mdnsAdvertiser.Init(context.GetUDPEndPointManager());
nlTestRunner(&theSuite, &server);
server.Shutdown();
context.Shutdown();
mdnsAdvertiser.RemoveServices();
mdnsAdvertiser.Shutdown();
chip::Platform::MemoryShutdown();
return nlTestRunnerStats(&theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestAdvertiser)