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