3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 #include <mdns/minimal/responders/QueryResponder.h>
21 #include <mdns/minimal/records/Ptr.h>
23 #include <support/UnitTestRegistration.h>
25 #include <nlunit-test.h>
30 using namespace mdns::Minimal;
32 const QNamePart kDnsSdname[] = { "_services", "_dns-sd", "_udp", "local" };
34 const QNamePart kName1[] = { "some", "test" };
35 const QNamePart kName2[] = { "some", "other", "test" };
37 class EmptyResponder : public Responder
40 EmptyResponder(const FullQName & qName) : Responder(QType::NULLVALUE, qName) {}
41 void AddAllResponses(const chip::Inet::IPPacketInfo *, ResponderDelegate *) override {}
44 class DnssdReplyAccumulator : public ResponderDelegate
47 DnssdReplyAccumulator(nlTestSuite * suite) : mSuite(suite) {}
48 void AddResponse(const ResourceRecord & record) override
51 NL_TEST_ASSERT(mSuite, record.GetType() == QType::PTR);
52 NL_TEST_ASSERT(mSuite, record.GetClass() == QClass::IN);
53 NL_TEST_ASSERT(mSuite, record.GetName() == kDnsSdname);
55 mCaptures.push_back(reinterpret_cast<const PtrResourceRecord &>(record).GetPtr());
58 std::vector<FullQName> & Captures() { return mCaptures; }
62 std::vector<FullQName> mCaptures;
65 void CanIterateOverResponders(nlTestSuite * inSuite, void * inContext)
67 QueryResponder<10> responder;
69 EmptyResponder empty1(kName1);
70 EmptyResponder empty2(kName2);
71 EmptyResponder empty3(kName2);
73 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty1).SetReportInServiceListing(true).IsValid());
74 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty2).SetReportInServiceListing(true).IsValid());
75 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty3).SetReportInServiceListing(true).IsValid());
78 QueryResponderRecordFilter noFilter;
79 for (auto it = responder.begin(&noFilter); it != responder.end(); it++, idx++)
81 FullQName qName = it->responder->GetQName();
82 NL_TEST_ASSERT(inSuite, (idx != 0) || (qName == kDnsSdname));
83 NL_TEST_ASSERT(inSuite, (idx != 1) || (qName == kName1));
84 NL_TEST_ASSERT(inSuite, (idx != 2) || (qName == kName2));
85 NL_TEST_ASSERT(inSuite, (idx != 3) || (qName == kName2));
87 NL_TEST_ASSERT(inSuite, idx == 4);
90 void RespondsToDnsSdQueries(nlTestSuite * inSuite, void * inContext)
92 QueryResponder<10> responder;
93 QueryResponderRecordFilter noFilter;
95 EmptyResponder empty1(kName1);
96 EmptyResponder empty2(kName2);
97 EmptyResponder empty3(kName1);
98 EmptyResponder empty4(kName1);
100 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty1).IsValid());
101 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty2).SetReportInServiceListing(true).IsValid());
102 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty3).SetReportInServiceListing(true).IsValid());
103 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty4).IsValid());
105 // It reports itself inside the iterator
106 NL_TEST_ASSERT(inSuite, &(*responder.begin(&noFilter)->responder) == &responder);
108 // It reponds dnssd PTR answers
109 NL_TEST_ASSERT(inSuite, responder.GetQClass() == QClass::IN);
110 NL_TEST_ASSERT(inSuite, responder.GetQType() == QType::PTR);
111 NL_TEST_ASSERT(inSuite, responder.GetQName() == kDnsSdname);
113 DnssdReplyAccumulator accumulator(inSuite);
114 responder.AddAllResponses(nullptr, &accumulator);
116 NL_TEST_ASSERT(inSuite, accumulator.Captures().size() == 2);
117 if (accumulator.Captures().size() == 2)
119 NL_TEST_ASSERT(inSuite, accumulator.Captures()[0] == kName2);
120 NL_TEST_ASSERT(inSuite, accumulator.Captures()[1] == kName1);
124 void LimitedStorage(nlTestSuite * inSuite, void * inContext)
126 QueryResponder<3> responder;
128 EmptyResponder empty1(kName1);
129 EmptyResponder empty2(kName2);
131 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty1).SetReportInServiceListing(true).IsValid());
132 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty2).SetReportInServiceListing(true).IsValid());
134 for (int i = 0; i < 100; i++)
136 EmptyResponder emptyX(kName1);
137 NL_TEST_ASSERT(inSuite, !responder.AddResponder(&emptyX).SetReportInServiceListing(true).IsValid());
141 QueryResponderRecordFilter noFilter;
142 for (auto it = responder.begin(&noFilter); it != responder.end(); it++, idx++)
144 FullQName qName = it->responder->GetQName();
145 NL_TEST_ASSERT(inSuite, (idx != 0) || (qName == kDnsSdname));
146 NL_TEST_ASSERT(inSuite, (idx != 1) || (qName == kName1));
147 NL_TEST_ASSERT(inSuite, (idx != 2) || (qName == kName2));
149 NL_TEST_ASSERT(inSuite, idx == 3);
152 void NonDiscoverableService(nlTestSuite * inSuite, void * inContext)
154 QueryResponder<3> responder;
156 EmptyResponder empty1(kName1);
157 EmptyResponder empty2(kName2);
159 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty1).IsValid());
160 NL_TEST_ASSERT(inSuite, responder.AddResponder(&empty2).SetReportInServiceListing(true).IsValid());
162 DnssdReplyAccumulator accumulator(inSuite);
163 responder.AddAllResponses(nullptr, &accumulator);
165 NL_TEST_ASSERT(inSuite, accumulator.Captures().size() == 1);
166 if (accumulator.Captures().size() == 1)
168 NL_TEST_ASSERT(inSuite, accumulator.Captures()[0] == kName2);
172 const nlTest sTests[] = {
173 NL_TEST_DEF("CanIterateOverResponders", CanIterateOverResponders), //
174 NL_TEST_DEF("RespondsToDnsSdQueries", RespondsToDnsSdQueries), //
175 NL_TEST_DEF("LimitedStorage", LimitedStorage), //
176 NL_TEST_DEF("NonDiscoverableService", NonDiscoverableService), //
177 NL_TEST_SENTINEL() //
182 int TestQueryResponder(void)
184 nlTestSuite theSuite = { "QueryResponder", sTests, nullptr, nullptr };
185 nlTestRunner(&theSuite, nullptr);
186 return nlTestRunnerStats(&theSuite);
189 CHIP_REGISTER_TEST_SUITE(TestQueryResponder)