xref: /aosp_15_r20/external/openscreen/discovery/mdns/mdns_publisher_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_publisher.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <chrono>
8*3f982cf4SFabien Sanglard #include <vector>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include "discovery/common/config.h"
11*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_probe_manager.h"
12*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_sender.h"
13*3f982cf4SFabien Sanglard #include "discovery/mdns/testing/mdns_test_util.h"
14*3f982cf4SFabien Sanglard #include "platform/test/fake_task_runner.h"
15*3f982cf4SFabien Sanglard #include "platform/test/fake_udp_socket.h"
16*3f982cf4SFabien Sanglard 
17*3f982cf4SFabien Sanglard using testing::_;
18*3f982cf4SFabien Sanglard using testing::Invoke;
19*3f982cf4SFabien Sanglard using testing::Return;
20*3f982cf4SFabien Sanglard using testing::StrictMock;
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard namespace openscreen {
23*3f982cf4SFabien Sanglard namespace discovery {
24*3f982cf4SFabien Sanglard namespace {
25*3f982cf4SFabien Sanglard 
26*3f982cf4SFabien Sanglard constexpr Clock::duration kAnnounceGoodbyeDelay = std::chrono::milliseconds(25);
27*3f982cf4SFabien Sanglard 
ContainsRecord(const std::vector<MdnsRecord::ConstRef> & records,MdnsRecord record)28*3f982cf4SFabien Sanglard bool ContainsRecord(const std::vector<MdnsRecord::ConstRef>& records,
29*3f982cf4SFabien Sanglard                     MdnsRecord record) {
30*3f982cf4SFabien Sanglard   return std::find_if(records.begin(), records.end(),
31*3f982cf4SFabien Sanglard                       [&record](const MdnsRecord& ref) {
32*3f982cf4SFabien Sanglard                         return ref == record;
33*3f982cf4SFabien Sanglard                       }) != records.end();
34*3f982cf4SFabien Sanglard }
35*3f982cf4SFabien Sanglard 
36*3f982cf4SFabien Sanglard }  // namespace
37*3f982cf4SFabien Sanglard 
38*3f982cf4SFabien Sanglard class MockMdnsSender : public MdnsSender {
39*3f982cf4SFabien Sanglard  public:
MockMdnsSender(UdpSocket * socket)40*3f982cf4SFabien Sanglard   explicit MockMdnsSender(UdpSocket* socket) : MdnsSender(socket) {}
41*3f982cf4SFabien Sanglard 
42*3f982cf4SFabien Sanglard   MOCK_METHOD1(SendMulticast, Error(const MdnsMessage& message));
43*3f982cf4SFabien Sanglard   MOCK_METHOD2(SendMessage,
44*3f982cf4SFabien Sanglard                Error(const MdnsMessage& message, const IPEndpoint& endpoint));
45*3f982cf4SFabien Sanglard };
46*3f982cf4SFabien Sanglard 
47*3f982cf4SFabien Sanglard class MockProbeManager : public MdnsProbeManager {
48*3f982cf4SFabien Sanglard  public:
49*3f982cf4SFabien Sanglard   MOCK_CONST_METHOD1(IsDomainClaimed, bool(const DomainName&));
50*3f982cf4SFabien Sanglard   MOCK_METHOD2(RespondToProbeQuery,
51*3f982cf4SFabien Sanglard                void(const MdnsMessage&, const IPEndpoint&));
52*3f982cf4SFabien Sanglard };
53*3f982cf4SFabien Sanglard 
54*3f982cf4SFabien Sanglard class MdnsPublisherTesting : public MdnsPublisher {
55*3f982cf4SFabien Sanglard  public:
56*3f982cf4SFabien Sanglard   using MdnsPublisher::GetPtrRecords;
57*3f982cf4SFabien Sanglard   using MdnsPublisher::GetRecords;
58*3f982cf4SFabien Sanglard   using MdnsPublisher::MdnsPublisher;
59*3f982cf4SFabien Sanglard 
IsNonPtrRecordPresent(const DomainName & name)60*3f982cf4SFabien Sanglard   bool IsNonPtrRecordPresent(const DomainName& name) {
61*3f982cf4SFabien Sanglard     auto it = records_.find(name);
62*3f982cf4SFabien Sanglard     if (it == records_.end()) {
63*3f982cf4SFabien Sanglard       return false;
64*3f982cf4SFabien Sanglard     }
65*3f982cf4SFabien Sanglard 
66*3f982cf4SFabien Sanglard     return std::find_if(it->second.begin(), it->second.end(),
67*3f982cf4SFabien Sanglard                         [](const RecordAnnouncerPtr& announcer) {
68*3f982cf4SFabien Sanglard                           return announcer->record().dns_type() !=
69*3f982cf4SFabien Sanglard                                  DnsType::kPTR;
70*3f982cf4SFabien Sanglard                         }) != it->second.end();
71*3f982cf4SFabien Sanglard   }
72*3f982cf4SFabien Sanglard };
73*3f982cf4SFabien Sanglard 
74*3f982cf4SFabien Sanglard class MdnsPublisherTest : public testing::Test {
75*3f982cf4SFabien Sanglard  public:
MdnsPublisherTest()76*3f982cf4SFabien Sanglard   MdnsPublisherTest()
77*3f982cf4SFabien Sanglard       : clock_(Clock::now()),
78*3f982cf4SFabien Sanglard         task_runner_(&clock_),
79*3f982cf4SFabien Sanglard         socket_(&task_runner_),
80*3f982cf4SFabien Sanglard         sender_(&socket_),
81*3f982cf4SFabien Sanglard         publisher_(&sender_,
82*3f982cf4SFabien Sanglard                    &probe_manager_,
83*3f982cf4SFabien Sanglard                    &task_runner_,
84*3f982cf4SFabien Sanglard                    FakeClock::now,
85*3f982cf4SFabien Sanglard                    config_) {}
86*3f982cf4SFabien Sanglard 
~MdnsPublisherTest()87*3f982cf4SFabien Sanglard   ~MdnsPublisherTest() {
88*3f982cf4SFabien Sanglard     // Clear out any remaining calls in the task runner queue.
89*3f982cf4SFabien Sanglard     clock_.Advance(Clock::to_duration(std::chrono::seconds(1)));
90*3f982cf4SFabien Sanglard   }
91*3f982cf4SFabien Sanglard 
92*3f982cf4SFabien Sanglard  protected:
IsAnnounced(const MdnsRecord & original,const MdnsMessage & message)93*3f982cf4SFabien Sanglard   Error IsAnnounced(const MdnsRecord& original, const MdnsMessage& message) {
94*3f982cf4SFabien Sanglard     EXPECT_EQ(message.type(), MessageType::Response);
95*3f982cf4SFabien Sanglard     EXPECT_EQ(message.questions().size(), size_t{0});
96*3f982cf4SFabien Sanglard     EXPECT_EQ(message.authority_records().size(), size_t{0});
97*3f982cf4SFabien Sanglard     EXPECT_EQ(message.additional_records().size(), size_t{0});
98*3f982cf4SFabien Sanglard     EXPECT_EQ(message.answers().size(), size_t{1});
99*3f982cf4SFabien Sanglard 
100*3f982cf4SFabien Sanglard     const MdnsRecord& sent = message.answers()[0];
101*3f982cf4SFabien Sanglard     EXPECT_EQ(original.name(), sent.name());
102*3f982cf4SFabien Sanglard     EXPECT_EQ(original.dns_type(), sent.dns_type());
103*3f982cf4SFabien Sanglard     EXPECT_EQ(original.dns_class(), sent.dns_class());
104*3f982cf4SFabien Sanglard     EXPECT_EQ(original.record_type(), sent.record_type());
105*3f982cf4SFabien Sanglard     EXPECT_EQ(original.rdata(), sent.rdata());
106*3f982cf4SFabien Sanglard     EXPECT_EQ(original.ttl(), sent.ttl());
107*3f982cf4SFabien Sanglard     return Error::None();
108*3f982cf4SFabien Sanglard   }
109*3f982cf4SFabien Sanglard 
IsGoodbyeRecord(const MdnsRecord & original,const MdnsMessage & message)110*3f982cf4SFabien Sanglard   Error IsGoodbyeRecord(const MdnsRecord& original,
111*3f982cf4SFabien Sanglard                         const MdnsMessage& message) {
112*3f982cf4SFabien Sanglard     EXPECT_EQ(message.type(), MessageType::Response);
113*3f982cf4SFabien Sanglard     EXPECT_EQ(message.questions().size(), size_t{0});
114*3f982cf4SFabien Sanglard     EXPECT_EQ(message.authority_records().size(), size_t{0});
115*3f982cf4SFabien Sanglard     EXPECT_EQ(message.additional_records().size(), size_t{0});
116*3f982cf4SFabien Sanglard     EXPECT_EQ(message.answers().size(), size_t{1});
117*3f982cf4SFabien Sanglard 
118*3f982cf4SFabien Sanglard     const MdnsRecord& sent = message.answers()[0];
119*3f982cf4SFabien Sanglard     EXPECT_EQ(original.name(), sent.name());
120*3f982cf4SFabien Sanglard     EXPECT_EQ(original.dns_type(), sent.dns_type());
121*3f982cf4SFabien Sanglard     EXPECT_EQ(original.dns_class(), sent.dns_class());
122*3f982cf4SFabien Sanglard     EXPECT_EQ(original.record_type(), sent.record_type());
123*3f982cf4SFabien Sanglard     EXPECT_EQ(original.rdata(), sent.rdata());
124*3f982cf4SFabien Sanglard     EXPECT_EQ(std::chrono::seconds(0), sent.ttl());
125*3f982cf4SFabien Sanglard     return Error::None();
126*3f982cf4SFabien Sanglard   }
127*3f982cf4SFabien Sanglard 
CheckPublishedRecords(const DomainName & domain,DnsType type,std::vector<MdnsRecord> expected_records)128*3f982cf4SFabien Sanglard   void CheckPublishedRecords(const DomainName& domain,
129*3f982cf4SFabien Sanglard                              DnsType type,
130*3f982cf4SFabien Sanglard                              std::vector<MdnsRecord> expected_records) {
131*3f982cf4SFabien Sanglard     EXPECT_EQ(publisher_.GetRecordCount(), expected_records.size());
132*3f982cf4SFabien Sanglard     auto records = publisher_.GetRecords(domain, type, DnsClass::kIN);
133*3f982cf4SFabien Sanglard     for (const auto& record : expected_records) {
134*3f982cf4SFabien Sanglard       EXPECT_TRUE(ContainsRecord(records, record));
135*3f982cf4SFabien Sanglard     }
136*3f982cf4SFabien Sanglard   }
137*3f982cf4SFabien Sanglard 
TestUniqueRecordRegistrationWorkflow(MdnsRecord record,MdnsRecord record2)138*3f982cf4SFabien Sanglard   void TestUniqueRecordRegistrationWorkflow(MdnsRecord record,
139*3f982cf4SFabien Sanglard                                             MdnsRecord record2) {
140*3f982cf4SFabien Sanglard     EXPECT_CALL(probe_manager_, IsDomainClaimed(domain_))
141*3f982cf4SFabien Sanglard         .WillRepeatedly(Return(true));
142*3f982cf4SFabien Sanglard     DnsType type = record.dns_type();
143*3f982cf4SFabien Sanglard 
144*3f982cf4SFabien Sanglard     // Check preconditions.
145*3f982cf4SFabien Sanglard     ASSERT_EQ(record.dns_type(), record2.dns_type());
146*3f982cf4SFabien Sanglard     auto records = publisher_.GetRecords(domain_, type, DnsClass::kIN);
147*3f982cf4SFabien Sanglard     ASSERT_EQ(publisher_.GetRecordCount(), size_t{0});
148*3f982cf4SFabien Sanglard     ASSERT_EQ(records.size(), size_t{0});
149*3f982cf4SFabien Sanglard     ASSERT_NE(record, record2);
150*3f982cf4SFabien Sanglard     ASSERT_TRUE(records.empty());
151*3f982cf4SFabien Sanglard 
152*3f982cf4SFabien Sanglard     // Register a new record.
153*3f982cf4SFabien Sanglard     EXPECT_CALL(sender_, SendMulticast(_))
154*3f982cf4SFabien Sanglard         .WillOnce([this, &record](const MdnsMessage& message) -> Error {
155*3f982cf4SFabien Sanglard           return IsAnnounced(record, message);
156*3f982cf4SFabien Sanglard         });
157*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.RegisterRecord(record).ok());
158*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
159*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
160*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record});
161*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
162*3f982cf4SFabien Sanglard 
163*3f982cf4SFabien Sanglard     // Re-register the same record.
164*3f982cf4SFabien Sanglard     EXPECT_FALSE(publisher_.RegisterRecord(record).ok());
165*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
166*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
167*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record});
168*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
169*3f982cf4SFabien Sanglard 
170*3f982cf4SFabien Sanglard     // Update a record that doesn't exist
171*3f982cf4SFabien Sanglard     EXPECT_FALSE(publisher_.UpdateRegisteredRecord(record2, record).ok());
172*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
173*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
174*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record});
175*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
176*3f982cf4SFabien Sanglard 
177*3f982cf4SFabien Sanglard     // Update an existing record.
178*3f982cf4SFabien Sanglard     EXPECT_CALL(sender_, SendMulticast(_))
179*3f982cf4SFabien Sanglard         .WillOnce([this, &record2](const MdnsMessage& message) -> Error {
180*3f982cf4SFabien Sanglard           return IsAnnounced(record2, message);
181*3f982cf4SFabien Sanglard         });
182*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.UpdateRegisteredRecord(record, record2).ok());
183*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
184*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
185*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record2});
186*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
187*3f982cf4SFabien Sanglard 
188*3f982cf4SFabien Sanglard     // Add back the original record
189*3f982cf4SFabien Sanglard     EXPECT_CALL(sender_, SendMulticast(_))
190*3f982cf4SFabien Sanglard         .WillOnce([this, &record](const MdnsMessage& message) -> Error {
191*3f982cf4SFabien Sanglard           return IsAnnounced(record, message);
192*3f982cf4SFabien Sanglard         });
193*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.RegisterRecord(record).ok());
194*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
195*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
196*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record, record2});
197*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
198*3f982cf4SFabien Sanglard 
199*3f982cf4SFabien Sanglard     // Delete an existing record.
200*3f982cf4SFabien Sanglard     EXPECT_CALL(sender_, SendMulticast(_))
201*3f982cf4SFabien Sanglard         .WillOnce([this, &record2](const MdnsMessage& message) -> Error {
202*3f982cf4SFabien Sanglard           return IsGoodbyeRecord(record2, message);
203*3f982cf4SFabien Sanglard         });
204*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.UnregisterRecord(record2).ok());
205*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
206*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
207*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record});
208*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
209*3f982cf4SFabien Sanglard 
210*3f982cf4SFabien Sanglard     // Delete a non-existing record.
211*3f982cf4SFabien Sanglard     EXPECT_FALSE(publisher_.UnregisterRecord(record2).ok());
212*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
213*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
214*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {record});
215*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.IsNonPtrRecordPresent(domain_));
216*3f982cf4SFabien Sanglard 
217*3f982cf4SFabien Sanglard     // Delete the last record
218*3f982cf4SFabien Sanglard     EXPECT_CALL(sender_, SendMulticast(_))
219*3f982cf4SFabien Sanglard         .WillOnce([this, &record](const MdnsMessage& message) -> Error {
220*3f982cf4SFabien Sanglard           return IsGoodbyeRecord(record, message);
221*3f982cf4SFabien Sanglard         });
222*3f982cf4SFabien Sanglard     EXPECT_TRUE(publisher_.UnregisterRecord(record).ok());
223*3f982cf4SFabien Sanglard     clock_.Advance(kAnnounceGoodbyeDelay);
224*3f982cf4SFabien Sanglard     testing::Mock::VerifyAndClearExpectations(&sender_);
225*3f982cf4SFabien Sanglard     CheckPublishedRecords(domain_, type, {});
226*3f982cf4SFabien Sanglard     EXPECT_FALSE(publisher_.IsNonPtrRecordPresent(domain_));
227*3f982cf4SFabien Sanglard   }
228*3f982cf4SFabien Sanglard 
229*3f982cf4SFabien Sanglard   FakeClock clock_;
230*3f982cf4SFabien Sanglard   FakeTaskRunner task_runner_;
231*3f982cf4SFabien Sanglard   FakeUdpSocket socket_;
232*3f982cf4SFabien Sanglard   StrictMock<MockMdnsSender> sender_;
233*3f982cf4SFabien Sanglard   StrictMock<MockProbeManager> probe_manager_;
234*3f982cf4SFabien Sanglard   Config config_;
235*3f982cf4SFabien Sanglard   MdnsPublisherTesting publisher_;
236*3f982cf4SFabien Sanglard 
237*3f982cf4SFabien Sanglard   DomainName domain_{"instance", "_googlecast", "_tcp", "local"};
238*3f982cf4SFabien Sanglard   DomainName ptr_domain_{"_googlecast", "_tcp", "local"};
239*3f982cf4SFabien Sanglard };
240*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,ARecordRegistrationWorkflow)241*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, ARecordRegistrationWorkflow) {
242*3f982cf4SFabien Sanglard   const MdnsRecord record1 = GetFakeARecord(domain_);
243*3f982cf4SFabien Sanglard   const MdnsRecord record2 =
244*3f982cf4SFabien Sanglard       GetFakeARecord(domain_, std::chrono::seconds(1000));
245*3f982cf4SFabien Sanglard   TestUniqueRecordRegistrationWorkflow(record1, record2);
246*3f982cf4SFabien Sanglard }
247*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,AAAARecordRegistrationWorkflow)248*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, AAAARecordRegistrationWorkflow) {
249*3f982cf4SFabien Sanglard   const MdnsRecord record1 = GetFakeAAAARecord(domain_);
250*3f982cf4SFabien Sanglard   const MdnsRecord record2 =
251*3f982cf4SFabien Sanglard       GetFakeAAAARecord(domain_, std::chrono::seconds(1000));
252*3f982cf4SFabien Sanglard   TestUniqueRecordRegistrationWorkflow(record1, record2);
253*3f982cf4SFabien Sanglard }
254*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,TXTRecordRegistrationWorkflow)255*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, TXTRecordRegistrationWorkflow) {
256*3f982cf4SFabien Sanglard   const MdnsRecord record1 = GetFakeTxtRecord(domain_);
257*3f982cf4SFabien Sanglard   const MdnsRecord record2 =
258*3f982cf4SFabien Sanglard       GetFakeTxtRecord(domain_, std::chrono::seconds(1000));
259*3f982cf4SFabien Sanglard   TestUniqueRecordRegistrationWorkflow(record1, record2);
260*3f982cf4SFabien Sanglard }
261*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,SRVRecordRegistrationWorkflow)262*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, SRVRecordRegistrationWorkflow) {
263*3f982cf4SFabien Sanglard   const MdnsRecord record1 = GetFakeSrvRecord(domain_);
264*3f982cf4SFabien Sanglard   const MdnsRecord record2 =
265*3f982cf4SFabien Sanglard       GetFakeSrvRecord(domain_, std::chrono::seconds(1000));
266*3f982cf4SFabien Sanglard   TestUniqueRecordRegistrationWorkflow(record1, record2);
267*3f982cf4SFabien Sanglard }
268*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,PTRRecordRegistrationWorkflow)269*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, PTRRecordRegistrationWorkflow) {
270*3f982cf4SFabien Sanglard   const MdnsRecord record = GetFakePtrRecord(domain_);
271*3f982cf4SFabien Sanglard   const MdnsRecord record2 =
272*3f982cf4SFabien Sanglard       GetFakePtrRecord(domain_, std::chrono::seconds(1000));
273*3f982cf4SFabien Sanglard 
274*3f982cf4SFabien Sanglard   EXPECT_CALL(probe_manager_, IsDomainClaimed(domain_))
275*3f982cf4SFabien Sanglard       .WillRepeatedly(Return(true));
276*3f982cf4SFabien Sanglard   DnsType type = DnsType::kPTR;
277*3f982cf4SFabien Sanglard 
278*3f982cf4SFabien Sanglard   // Check preconditions.
279*3f982cf4SFabien Sanglard   ASSERT_EQ(record.dns_type(), record2.dns_type());
280*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetRecordCount(), size_t{0});
281*3f982cf4SFabien Sanglard   auto records = publisher_.GetRecords(domain_, type, DnsClass::kIN);
282*3f982cf4SFabien Sanglard   ASSERT_EQ(records.size(), size_t{0});
283*3f982cf4SFabien Sanglard   records = publisher_.GetRecords(ptr_domain_, type, DnsClass::kIN);
284*3f982cf4SFabien Sanglard   ASSERT_EQ(records.size(), size_t{0});
285*3f982cf4SFabien Sanglard   ASSERT_NE(record, record2);
286*3f982cf4SFabien Sanglard   ASSERT_TRUE(records.empty());
287*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{0});
288*3f982cf4SFabien Sanglard 
289*3f982cf4SFabien Sanglard   // Register a new record.
290*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
291*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
292*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
293*3f982cf4SFabien Sanglard       });
294*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.RegisterRecord(record).ok());
295*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
296*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
297*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {record});
298*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{1});
299*3f982cf4SFabien Sanglard 
300*3f982cf4SFabien Sanglard   // Re-register the same record.
301*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(record).ok());
302*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
303*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
304*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {record});
305*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{1});
306*3f982cf4SFabien Sanglard 
307*3f982cf4SFabien Sanglard   // Register a second record.
308*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
309*3f982cf4SFabien Sanglard       .WillOnce([this, &record2](const MdnsMessage& message) -> Error {
310*3f982cf4SFabien Sanglard         return IsAnnounced(record2, message);
311*3f982cf4SFabien Sanglard       });
312*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.RegisterRecord(record2).ok());
313*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
314*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
315*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {record, record2});
316*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{2});
317*3f982cf4SFabien Sanglard 
318*3f982cf4SFabien Sanglard   // Delete an existing record.
319*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
320*3f982cf4SFabien Sanglard       .WillOnce([this, &record2](const MdnsMessage& message) -> Error {
321*3f982cf4SFabien Sanglard         return IsGoodbyeRecord(record2, message);
322*3f982cf4SFabien Sanglard       });
323*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.UnregisterRecord(record2).ok());
324*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
325*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
326*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {record});
327*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{1});
328*3f982cf4SFabien Sanglard 
329*3f982cf4SFabien Sanglard   // Delete a non-existing record.
330*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.UnregisterRecord(record2).ok());
331*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
332*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
333*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {record});
334*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{1});
335*3f982cf4SFabien Sanglard 
336*3f982cf4SFabien Sanglard   // Delete the last record
337*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
338*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
339*3f982cf4SFabien Sanglard         return IsGoodbyeRecord(record, message);
340*3f982cf4SFabien Sanglard       });
341*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.UnregisterRecord(record).ok());
342*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
343*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
344*3f982cf4SFabien Sanglard   CheckPublishedRecords(ptr_domain_, type, {});
345*3f982cf4SFabien Sanglard   ASSERT_EQ(publisher_.GetPtrRecords(DnsClass::kANY).size(), size_t{0});
346*3f982cf4SFabien Sanglard }
347*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,RegisteringUnownedRecordsFail)348*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, RegisteringUnownedRecordsFail) {
349*3f982cf4SFabien Sanglard   EXPECT_CALL(probe_manager_, IsDomainClaimed(domain_))
350*3f982cf4SFabien Sanglard       .WillRepeatedly(Return(false));
351*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(GetFakePtrRecord(domain_)).ok());
352*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(GetFakeSrvRecord(domain_)).ok());
353*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(GetFakeTxtRecord(domain_)).ok());
354*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(GetFakeARecord(domain_)).ok());
355*3f982cf4SFabien Sanglard   EXPECT_FALSE(publisher_.RegisterRecord(GetFakeAAAARecord(domain_)).ok());
356*3f982cf4SFabien Sanglard }
357*3f982cf4SFabien Sanglard 
TEST_F(MdnsPublisherTest,RegistrationAnnouncesEightTimes)358*3f982cf4SFabien Sanglard TEST_F(MdnsPublisherTest, RegistrationAnnouncesEightTimes) {
359*3f982cf4SFabien Sanglard   EXPECT_CALL(probe_manager_, IsDomainClaimed(domain_))
360*3f982cf4SFabien Sanglard       .WillRepeatedly(Return(true));
361*3f982cf4SFabien Sanglard   constexpr Clock::duration kOneSecond =
362*3f982cf4SFabien Sanglard       Clock::to_duration(std::chrono::seconds(1));
363*3f982cf4SFabien Sanglard 
364*3f982cf4SFabien Sanglard   // First announce, at registration.
365*3f982cf4SFabien Sanglard   const MdnsRecord record = GetFakeARecord(domain_);
366*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
367*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
368*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
369*3f982cf4SFabien Sanglard       });
370*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.RegisterRecord(record).ok());
371*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
372*3f982cf4SFabien Sanglard 
373*3f982cf4SFabien Sanglard   // Second announce, at 2 seconds.
374*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
375*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
376*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
377*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
378*3f982cf4SFabien Sanglard       });
379*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
380*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
381*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
382*3f982cf4SFabien Sanglard 
383*3f982cf4SFabien Sanglard   // Third announce, at 4 seconds.
384*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
385*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
386*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
387*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
388*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
389*3f982cf4SFabien Sanglard       });
390*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
391*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
392*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
393*3f982cf4SFabien Sanglard 
394*3f982cf4SFabien Sanglard   // Fourth announce, at 8 seconds.
395*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 3);
396*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
397*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
398*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
399*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
400*3f982cf4SFabien Sanglard       });
401*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
402*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
403*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
404*3f982cf4SFabien Sanglard 
405*3f982cf4SFabien Sanglard   // Fifth announce, at 16 seconds.
406*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 7);
407*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
408*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
409*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
410*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
411*3f982cf4SFabien Sanglard       });
412*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
413*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
414*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
415*3f982cf4SFabien Sanglard 
416*3f982cf4SFabien Sanglard   // Sixth announce, at 32 seconds.
417*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 15);
418*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
419*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
420*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
421*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
422*3f982cf4SFabien Sanglard       });
423*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
424*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
425*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
426*3f982cf4SFabien Sanglard 
427*3f982cf4SFabien Sanglard   // Seventh announce, at 64 seconds.
428*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 31);
429*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
430*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
431*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
432*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
433*3f982cf4SFabien Sanglard       });
434*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
435*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
436*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
437*3f982cf4SFabien Sanglard 
438*3f982cf4SFabien Sanglard   // Eighth announce, at 128 seconds.
439*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 63);
440*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
441*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
442*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
443*3f982cf4SFabien Sanglard         return IsAnnounced(record, message);
444*3f982cf4SFabien Sanglard       });
445*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond);
446*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
447*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
448*3f982cf4SFabien Sanglard 
449*3f982cf4SFabien Sanglard   // No more announcements
450*3f982cf4SFabien Sanglard   clock_.Advance(kOneSecond * 1024);
451*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
452*3f982cf4SFabien Sanglard   testing::Mock::VerifyAndClearExpectations(&sender_);
453*3f982cf4SFabien Sanglard 
454*3f982cf4SFabien Sanglard   // Sends goodbye message when removed.
455*3f982cf4SFabien Sanglard   EXPECT_CALL(sender_, SendMulticast(_))
456*3f982cf4SFabien Sanglard       .WillOnce([this, &record](const MdnsMessage& message) -> Error {
457*3f982cf4SFabien Sanglard         return IsGoodbyeRecord(record, message);
458*3f982cf4SFabien Sanglard       });
459*3f982cf4SFabien Sanglard   EXPECT_TRUE(publisher_.UnregisterRecord(record).ok());
460*3f982cf4SFabien Sanglard   clock_.Advance(kAnnounceGoodbyeDelay);
461*3f982cf4SFabien Sanglard }
462*3f982cf4SFabien Sanglard 
463*3f982cf4SFabien Sanglard }  // namespace discovery
464*3f982cf4SFabien Sanglard }  // namespace openscreen
465