1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2023, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker * All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker *
5*4a64e381SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker *
16*4a64e381SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker */
28*4a64e381SAndroid Build Coastguard Worker
29*4a64e381SAndroid Build Coastguard Worker #include <gtest/gtest.h>
30*4a64e381SAndroid Build Coastguard Worker #include <limits.h>
31*4a64e381SAndroid Build Coastguard Worker #include <netinet/in.h>
32*4a64e381SAndroid Build Coastguard Worker #include <signal.h>
33*4a64e381SAndroid Build Coastguard Worker
34*4a64e381SAndroid Build Coastguard Worker #include <set>
35*4a64e381SAndroid Build Coastguard Worker #include <vector>
36*4a64e381SAndroid Build Coastguard Worker
37*4a64e381SAndroid Build Coastguard Worker #include "common/mainloop.hpp"
38*4a64e381SAndroid Build Coastguard Worker #include "common/mainloop_manager.hpp"
39*4a64e381SAndroid Build Coastguard Worker #include "mdns/mdns.hpp"
40*4a64e381SAndroid Build Coastguard Worker
41*4a64e381SAndroid Build Coastguard Worker using namespace otbr;
42*4a64e381SAndroid Build Coastguard Worker using namespace otbr::Mdns;
43*4a64e381SAndroid Build Coastguard Worker
44*4a64e381SAndroid Build Coastguard Worker static constexpr int kTimeoutSeconds = 3;
45*4a64e381SAndroid Build Coastguard Worker
RunMainloopUntilTimeout(int aSeconds)46*4a64e381SAndroid Build Coastguard Worker int RunMainloopUntilTimeout(int aSeconds)
47*4a64e381SAndroid Build Coastguard Worker {
48*4a64e381SAndroid Build Coastguard Worker using namespace otbr;
49*4a64e381SAndroid Build Coastguard Worker
50*4a64e381SAndroid Build Coastguard Worker int rval = 0;
51*4a64e381SAndroid Build Coastguard Worker auto beginTime = Clock::now();
52*4a64e381SAndroid Build Coastguard Worker
53*4a64e381SAndroid Build Coastguard Worker while (true)
54*4a64e381SAndroid Build Coastguard Worker {
55*4a64e381SAndroid Build Coastguard Worker MainloopContext mainloop;
56*4a64e381SAndroid Build Coastguard Worker
57*4a64e381SAndroid Build Coastguard Worker mainloop.mMaxFd = -1;
58*4a64e381SAndroid Build Coastguard Worker mainloop.mTimeout = {1, 0};
59*4a64e381SAndroid Build Coastguard Worker FD_ZERO(&mainloop.mReadFdSet);
60*4a64e381SAndroid Build Coastguard Worker FD_ZERO(&mainloop.mWriteFdSet);
61*4a64e381SAndroid Build Coastguard Worker FD_ZERO(&mainloop.mErrorFdSet);
62*4a64e381SAndroid Build Coastguard Worker
63*4a64e381SAndroid Build Coastguard Worker MainloopManager::GetInstance().Update(mainloop);
64*4a64e381SAndroid Build Coastguard Worker rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
65*4a64e381SAndroid Build Coastguard Worker (mainloop.mTimeout.tv_sec == INT_MAX ? nullptr : &mainloop.mTimeout));
66*4a64e381SAndroid Build Coastguard Worker
67*4a64e381SAndroid Build Coastguard Worker if (rval < 0)
68*4a64e381SAndroid Build Coastguard Worker {
69*4a64e381SAndroid Build Coastguard Worker perror("select");
70*4a64e381SAndroid Build Coastguard Worker break;
71*4a64e381SAndroid Build Coastguard Worker }
72*4a64e381SAndroid Build Coastguard Worker
73*4a64e381SAndroid Build Coastguard Worker MainloopManager::GetInstance().Process(mainloop);
74*4a64e381SAndroid Build Coastguard Worker
75*4a64e381SAndroid Build Coastguard Worker if (Clock::now() - beginTime >= std::chrono::seconds(aSeconds))
76*4a64e381SAndroid Build Coastguard Worker {
77*4a64e381SAndroid Build Coastguard Worker break;
78*4a64e381SAndroid Build Coastguard Worker }
79*4a64e381SAndroid Build Coastguard Worker }
80*4a64e381SAndroid Build Coastguard Worker
81*4a64e381SAndroid Build Coastguard Worker return rval;
82*4a64e381SAndroid Build Coastguard Worker }
83*4a64e381SAndroid Build Coastguard Worker
AsSet(const Container & aContainer)84*4a64e381SAndroid Build Coastguard Worker template <typename Container> std::set<typename Container::value_type> AsSet(const Container &aContainer)
85*4a64e381SAndroid Build Coastguard Worker {
86*4a64e381SAndroid Build Coastguard Worker return std::set<typename Container::value_type>(aContainer.begin(), aContainer.end());
87*4a64e381SAndroid Build Coastguard Worker }
88*4a64e381SAndroid Build Coastguard Worker
NoOpCallback(void)89*4a64e381SAndroid Build Coastguard Worker Publisher::ResultCallback NoOpCallback(void)
90*4a64e381SAndroid Build Coastguard Worker {
91*4a64e381SAndroid Build Coastguard Worker return [](otbrError aError) { OTBR_UNUSED_VARIABLE(aError); };
92*4a64e381SAndroid Build Coastguard Worker }
93*4a64e381SAndroid Build Coastguard Worker
AsTxtMap(const Publisher::TxtData & aTxtData)94*4a64e381SAndroid Build Coastguard Worker std::map<std::string, std::vector<uint8_t>> AsTxtMap(const Publisher::TxtData &aTxtData)
95*4a64e381SAndroid Build Coastguard Worker {
96*4a64e381SAndroid Build Coastguard Worker Publisher::TxtList txtList;
97*4a64e381SAndroid Build Coastguard Worker std::map<std::string, std::vector<uint8_t>> map;
98*4a64e381SAndroid Build Coastguard Worker
99*4a64e381SAndroid Build Coastguard Worker Publisher::DecodeTxtData(txtList, aTxtData.data(), aTxtData.size());
100*4a64e381SAndroid Build Coastguard Worker for (const auto &entry : txtList)
101*4a64e381SAndroid Build Coastguard Worker {
102*4a64e381SAndroid Build Coastguard Worker map[entry.mKey] = entry.mValue;
103*4a64e381SAndroid Build Coastguard Worker }
104*4a64e381SAndroid Build Coastguard Worker
105*4a64e381SAndroid Build Coastguard Worker return map;
106*4a64e381SAndroid Build Coastguard Worker }
107*4a64e381SAndroid Build Coastguard Worker
108*4a64e381SAndroid Build Coastguard Worker Publisher::TxtList sTxtList1{{"a", "1"}, {"b", "2"}};
109*4a64e381SAndroid Build Coastguard Worker Publisher::TxtData sTxtData1;
110*4a64e381SAndroid Build Coastguard Worker Ip6Address sAddr1;
111*4a64e381SAndroid Build Coastguard Worker Ip6Address sAddr2;
112*4a64e381SAndroid Build Coastguard Worker Ip6Address sAddr3;
113*4a64e381SAndroid Build Coastguard Worker Ip6Address sAddr4;
114*4a64e381SAndroid Build Coastguard Worker
115*4a64e381SAndroid Build Coastguard Worker class MdnsTest : public ::testing::Test
116*4a64e381SAndroid Build Coastguard Worker {
117*4a64e381SAndroid Build Coastguard Worker protected:
MdnsTest()118*4a64e381SAndroid Build Coastguard Worker MdnsTest()
119*4a64e381SAndroid Build Coastguard Worker {
120*4a64e381SAndroid Build Coastguard Worker SuccessOrDie(Ip6Address::FromString("2002::1", sAddr1), "");
121*4a64e381SAndroid Build Coastguard Worker SuccessOrDie(Ip6Address::FromString("2002::2", sAddr2), "");
122*4a64e381SAndroid Build Coastguard Worker SuccessOrDie(Ip6Address::FromString("2002::3", sAddr3), "");
123*4a64e381SAndroid Build Coastguard Worker SuccessOrDie(Ip6Address::FromString("2002::4", sAddr4), "");
124*4a64e381SAndroid Build Coastguard Worker SuccessOrDie(Publisher::EncodeTxtData(sTxtList1, sTxtData1), "");
125*4a64e381SAndroid Build Coastguard Worker }
126*4a64e381SAndroid Build Coastguard Worker };
127*4a64e381SAndroid Build Coastguard Worker
CreatePublisher(void)128*4a64e381SAndroid Build Coastguard Worker std::unique_ptr<Publisher> CreatePublisher(void)
129*4a64e381SAndroid Build Coastguard Worker {
130*4a64e381SAndroid Build Coastguard Worker bool ready = false;
131*4a64e381SAndroid Build Coastguard Worker std::unique_ptr<Publisher> publisher{Publisher::Create([&ready](Mdns::Publisher::State aState) {
132*4a64e381SAndroid Build Coastguard Worker if (aState == Publisher::State::kReady)
133*4a64e381SAndroid Build Coastguard Worker {
134*4a64e381SAndroid Build Coastguard Worker ready = true;
135*4a64e381SAndroid Build Coastguard Worker }
136*4a64e381SAndroid Build Coastguard Worker })};
137*4a64e381SAndroid Build Coastguard Worker
138*4a64e381SAndroid Build Coastguard Worker publisher->Start();
139*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
140*4a64e381SAndroid Build Coastguard Worker EXPECT_TRUE(ready);
141*4a64e381SAndroid Build Coastguard Worker
142*4a64e381SAndroid Build Coastguard Worker return publisher;
143*4a64e381SAndroid Build Coastguard Worker }
144*4a64e381SAndroid Build Coastguard Worker
CheckServiceInstance(const Publisher::DiscoveredInstanceInfo aInstanceInfo,bool aRemoved,const std::string & aHostName,const std::vector<Ip6Address> & aAddresses,const std::string & aServiceName,uint16_t aPort,const Publisher::TxtData aTxtData)145*4a64e381SAndroid Build Coastguard Worker void CheckServiceInstance(const Publisher::DiscoveredInstanceInfo aInstanceInfo,
146*4a64e381SAndroid Build Coastguard Worker bool aRemoved,
147*4a64e381SAndroid Build Coastguard Worker const std::string &aHostName,
148*4a64e381SAndroid Build Coastguard Worker const std::vector<Ip6Address> &aAddresses,
149*4a64e381SAndroid Build Coastguard Worker const std::string &aServiceName,
150*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
151*4a64e381SAndroid Build Coastguard Worker const Publisher::TxtData aTxtData)
152*4a64e381SAndroid Build Coastguard Worker {
153*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(aRemoved, aInstanceInfo.mRemoved);
154*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(aServiceName, aInstanceInfo.mName);
155*4a64e381SAndroid Build Coastguard Worker if (!aRemoved)
156*4a64e381SAndroid Build Coastguard Worker {
157*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(aHostName, aInstanceInfo.mHostName);
158*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(AsSet(aAddresses), AsSet(aInstanceInfo.mAddresses));
159*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(aPort, aInstanceInfo.mPort);
160*4a64e381SAndroid Build Coastguard Worker EXPECT_TRUE(AsTxtMap(aTxtData) == AsTxtMap(aInstanceInfo.mTxtData));
161*4a64e381SAndroid Build Coastguard Worker }
162*4a64e381SAndroid Build Coastguard Worker }
163*4a64e381SAndroid Build Coastguard Worker
CheckServiceInstanceAdded(const Publisher::DiscoveredInstanceInfo aInstanceInfo,const std::string & aHostName,const std::vector<Ip6Address> & aAddresses,const std::string & aServiceName,uint16_t aPort,const Publisher::TxtData aTxtData)164*4a64e381SAndroid Build Coastguard Worker void CheckServiceInstanceAdded(const Publisher::DiscoveredInstanceInfo aInstanceInfo,
165*4a64e381SAndroid Build Coastguard Worker const std::string &aHostName,
166*4a64e381SAndroid Build Coastguard Worker const std::vector<Ip6Address> &aAddresses,
167*4a64e381SAndroid Build Coastguard Worker const std::string &aServiceName,
168*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
169*4a64e381SAndroid Build Coastguard Worker const Publisher::TxtData aTxtData)
170*4a64e381SAndroid Build Coastguard Worker {
171*4a64e381SAndroid Build Coastguard Worker CheckServiceInstance(aInstanceInfo, false, aHostName, aAddresses, aServiceName, aPort, aTxtData);
172*4a64e381SAndroid Build Coastguard Worker }
173*4a64e381SAndroid Build Coastguard Worker
CheckServiceInstanceRemoved(const Publisher::DiscoveredInstanceInfo aInstanceInfo,const std::string & aServiceName)174*4a64e381SAndroid Build Coastguard Worker void CheckServiceInstanceRemoved(const Publisher::DiscoveredInstanceInfo aInstanceInfo, const std::string &aServiceName)
175*4a64e381SAndroid Build Coastguard Worker {
176*4a64e381SAndroid Build Coastguard Worker CheckServiceInstance(aInstanceInfo, true, "", {}, aServiceName, 0, {});
177*4a64e381SAndroid Build Coastguard Worker }
178*4a64e381SAndroid Build Coastguard Worker
CheckHostAdded(const Publisher::DiscoveredHostInfo & aHostInfo,const std::string & aHostName,const std::vector<Ip6Address> & aAddresses)179*4a64e381SAndroid Build Coastguard Worker void CheckHostAdded(const Publisher::DiscoveredHostInfo &aHostInfo,
180*4a64e381SAndroid Build Coastguard Worker const std::string &aHostName,
181*4a64e381SAndroid Build Coastguard Worker const std::vector<Ip6Address> &aAddresses)
182*4a64e381SAndroid Build Coastguard Worker {
183*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(aHostName, aHostInfo.mHostName);
184*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ(AsSet(aAddresses), AsSet(aHostInfo.mAddresses));
185*4a64e381SAndroid Build Coastguard Worker }
186*4a64e381SAndroid Build Coastguard Worker
TEST_F(MdnsTest,SubscribeHost)187*4a64e381SAndroid Build Coastguard Worker TEST_F(MdnsTest, SubscribeHost)
188*4a64e381SAndroid Build Coastguard Worker {
189*4a64e381SAndroid Build Coastguard Worker std::unique_ptr<Publisher> pub = CreatePublisher();
190*4a64e381SAndroid Build Coastguard Worker std::string lastHostName;
191*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredHostInfo lastHostInfo{};
192*4a64e381SAndroid Build Coastguard Worker
193*4a64e381SAndroid Build Coastguard Worker auto clearLastHost = [&lastHostName, &lastHostInfo] {
194*4a64e381SAndroid Build Coastguard Worker lastHostName = "";
195*4a64e381SAndroid Build Coastguard Worker lastHostInfo = {};
196*4a64e381SAndroid Build Coastguard Worker };
197*4a64e381SAndroid Build Coastguard Worker
198*4a64e381SAndroid Build Coastguard Worker pub->AddSubscriptionCallbacks(
199*4a64e381SAndroid Build Coastguard Worker nullptr,
200*4a64e381SAndroid Build Coastguard Worker [&lastHostName, &lastHostInfo](const std::string &aHostName, const Publisher::DiscoveredHostInfo &aHostInfo) {
201*4a64e381SAndroid Build Coastguard Worker lastHostName = aHostName;
202*4a64e381SAndroid Build Coastguard Worker lastHostInfo = aHostInfo;
203*4a64e381SAndroid Build Coastguard Worker });
204*4a64e381SAndroid Build Coastguard Worker pub->SubscribeHost("host1");
205*4a64e381SAndroid Build Coastguard Worker
206*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host1", Publisher::AddressList{sAddr1, sAddr2}, NoOpCallback());
207*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service1", "_test._tcp", Publisher::SubTypeList{"_sub1", "_sub2"}, 11111, sTxtData1,
208*4a64e381SAndroid Build Coastguard Worker NoOpCallback());
209*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
210*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("host1", lastHostName);
211*4a64e381SAndroid Build Coastguard Worker CheckHostAdded(lastHostInfo, "host1.local.", {sAddr1, sAddr2});
212*4a64e381SAndroid Build Coastguard Worker clearLastHost();
213*4a64e381SAndroid Build Coastguard Worker
214*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service2", "_test._tcp", {}, 22222, {}, NoOpCallback());
215*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
216*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("", lastHostName);
217*4a64e381SAndroid Build Coastguard Worker clearLastHost();
218*4a64e381SAndroid Build Coastguard Worker
219*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", Publisher::AddressList{sAddr3}, NoOpCallback());
220*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host2", "service3", "_test._tcp", {}, 33333, {}, NoOpCallback());
221*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
222*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("", lastHostName);
223*4a64e381SAndroid Build Coastguard Worker clearLastHost();
224*4a64e381SAndroid Build Coastguard Worker }
225*4a64e381SAndroid Build Coastguard Worker
TEST_F(MdnsTest,SubscribeServiceInstance)226*4a64e381SAndroid Build Coastguard Worker TEST_F(MdnsTest, SubscribeServiceInstance)
227*4a64e381SAndroid Build Coastguard Worker {
228*4a64e381SAndroid Build Coastguard Worker std::unique_ptr<Publisher> pub = CreatePublisher();
229*4a64e381SAndroid Build Coastguard Worker std::string lastServiceType;
230*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredInstanceInfo lastInstanceInfo{};
231*4a64e381SAndroid Build Coastguard Worker
232*4a64e381SAndroid Build Coastguard Worker auto clearLastInstance = [&lastServiceType, &lastInstanceInfo] {
233*4a64e381SAndroid Build Coastguard Worker lastServiceType = "";
234*4a64e381SAndroid Build Coastguard Worker lastInstanceInfo = {};
235*4a64e381SAndroid Build Coastguard Worker };
236*4a64e381SAndroid Build Coastguard Worker
237*4a64e381SAndroid Build Coastguard Worker pub->AddSubscriptionCallbacks(
238*4a64e381SAndroid Build Coastguard Worker [&lastServiceType, &lastInstanceInfo](const std::string &aType,
239*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredInstanceInfo aInstanceInfo) {
240*4a64e381SAndroid Build Coastguard Worker lastServiceType = aType;
241*4a64e381SAndroid Build Coastguard Worker lastInstanceInfo = aInstanceInfo;
242*4a64e381SAndroid Build Coastguard Worker },
243*4a64e381SAndroid Build Coastguard Worker nullptr);
244*4a64e381SAndroid Build Coastguard Worker pub->SubscribeService("_test._tcp", "service1");
245*4a64e381SAndroid Build Coastguard Worker
246*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host1", Publisher::AddressList{sAddr1, sAddr2}, NoOpCallback());
247*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service1", "_test._tcp", Publisher::SubTypeList{"_sub1", "_sub2"}, 11111, sTxtData1,
248*4a64e381SAndroid Build Coastguard Worker NoOpCallback());
249*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
250*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
251*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host1.local.", {sAddr1, sAddr2}, "service1", 11111, sTxtData1);
252*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
253*4a64e381SAndroid Build Coastguard Worker
254*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service2", "_test._tcp", {}, 22222, {}, NoOpCallback());
255*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
256*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("", lastServiceType);
257*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
258*4a64e381SAndroid Build Coastguard Worker
259*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", Publisher::AddressList{sAddr3}, NoOpCallback());
260*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host2", "service3", "_test._tcp", {}, 33333, {}, NoOpCallback());
261*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
262*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("", lastServiceType);
263*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
264*4a64e381SAndroid Build Coastguard Worker }
265*4a64e381SAndroid Build Coastguard Worker
TEST_F(MdnsTest,SubscribeServiceType)266*4a64e381SAndroid Build Coastguard Worker TEST_F(MdnsTest, SubscribeServiceType)
267*4a64e381SAndroid Build Coastguard Worker {
268*4a64e381SAndroid Build Coastguard Worker std::unique_ptr<Publisher> pub = CreatePublisher();
269*4a64e381SAndroid Build Coastguard Worker std::string lastServiceType;
270*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredInstanceInfo lastInstanceInfo{};
271*4a64e381SAndroid Build Coastguard Worker
272*4a64e381SAndroid Build Coastguard Worker auto clearLastInstance = [&lastServiceType, &lastInstanceInfo] {
273*4a64e381SAndroid Build Coastguard Worker lastServiceType = "";
274*4a64e381SAndroid Build Coastguard Worker lastInstanceInfo = {};
275*4a64e381SAndroid Build Coastguard Worker };
276*4a64e381SAndroid Build Coastguard Worker
277*4a64e381SAndroid Build Coastguard Worker pub->AddSubscriptionCallbacks(
278*4a64e381SAndroid Build Coastguard Worker [&lastServiceType, &lastInstanceInfo](const std::string &aType,
279*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredInstanceInfo aInstanceInfo) {
280*4a64e381SAndroid Build Coastguard Worker lastServiceType = aType;
281*4a64e381SAndroid Build Coastguard Worker lastInstanceInfo = aInstanceInfo;
282*4a64e381SAndroid Build Coastguard Worker },
283*4a64e381SAndroid Build Coastguard Worker nullptr);
284*4a64e381SAndroid Build Coastguard Worker pub->SubscribeService("_test._tcp", "");
285*4a64e381SAndroid Build Coastguard Worker
286*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host1", Publisher::AddressList{sAddr1, sAddr2}, NoOpCallback());
287*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service1", "_test._tcp", Publisher::SubTypeList{"_sub1", "_sub2"}, 11111, sTxtData1,
288*4a64e381SAndroid Build Coastguard Worker NoOpCallback());
289*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
290*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
291*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host1.local.", {sAddr1, sAddr2}, "service1", 11111, sTxtData1);
292*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
293*4a64e381SAndroid Build Coastguard Worker
294*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host1", "service2", "_test._tcp", {}, 22222, {}, NoOpCallback());
295*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
296*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
297*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host1.local.", {sAddr1, sAddr2}, "service2", 22222, {});
298*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
299*4a64e381SAndroid Build Coastguard Worker
300*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", Publisher::AddressList{sAddr3}, NoOpCallback());
301*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host2", "service3", "_test._tcp", {}, 33333, {}, NoOpCallback());
302*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
303*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
304*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host2.local.", {sAddr3}, "service3", 33333, {});
305*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
306*4a64e381SAndroid Build Coastguard Worker
307*4a64e381SAndroid Build Coastguard Worker pub->UnpublishHost("host2", NoOpCallback());
308*4a64e381SAndroid Build Coastguard Worker pub->UnpublishService("service3", "_test._tcp", NoOpCallback());
309*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
310*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
311*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceRemoved(lastInstanceInfo, "service3");
312*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
313*4a64e381SAndroid Build Coastguard Worker
314*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", {sAddr3}, NoOpCallback());
315*4a64e381SAndroid Build Coastguard Worker pub->PublishService("host2", "service3", "_test._tcp", {}, 44444, {}, NoOpCallback());
316*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", {sAddr3, sAddr4}, NoOpCallback());
317*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
318*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
319*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host2.local.", {sAddr3, sAddr4}, "service3", 44444, {});
320*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
321*4a64e381SAndroid Build Coastguard Worker
322*4a64e381SAndroid Build Coastguard Worker pub->PublishHost("host2", {sAddr4}, NoOpCallback());
323*4a64e381SAndroid Build Coastguard Worker RunMainloopUntilTimeout(kTimeoutSeconds);
324*4a64e381SAndroid Build Coastguard Worker EXPECT_EQ("_test._tcp", lastServiceType);
325*4a64e381SAndroid Build Coastguard Worker CheckServiceInstanceAdded(lastInstanceInfo, "host2.local.", {sAddr4}, "service3", 44444, {});
326*4a64e381SAndroid Build Coastguard Worker clearLastInstance();
327*4a64e381SAndroid Build Coastguard Worker }
328