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_querier.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <memory>
8*3f982cf4SFabien Sanglard #include <utility>
9*3f982cf4SFabien Sanglard
10*3f982cf4SFabien Sanglard #include "discovery/common/config.h"
11*3f982cf4SFabien Sanglard #include "discovery/common/testing/mock_reporting_client.h"
12*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_random.h"
13*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_receiver.h"
14*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_record_changed_callback.h"
15*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_sender.h"
16*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_trackers.h"
17*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_writer.h"
18*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
19*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
20*3f982cf4SFabien Sanglard #include "platform/base/udp_packet.h"
21*3f982cf4SFabien Sanglard #include "platform/test/fake_clock.h"
22*3f982cf4SFabien Sanglard #include "platform/test/fake_task_runner.h"
23*3f982cf4SFabien Sanglard #include "platform/test/mock_udp_socket.h"
24*3f982cf4SFabien Sanglard
25*3f982cf4SFabien Sanglard namespace openscreen {
26*3f982cf4SFabien Sanglard namespace discovery {
27*3f982cf4SFabien Sanglard
28*3f982cf4SFabien Sanglard using testing::_;
29*3f982cf4SFabien Sanglard using testing::Args;
30*3f982cf4SFabien Sanglard using testing::Invoke;
31*3f982cf4SFabien Sanglard using testing::Return;
32*3f982cf4SFabien Sanglard using testing::StrictMock;
33*3f982cf4SFabien Sanglard using testing::WithArgs;
34*3f982cf4SFabien Sanglard
35*3f982cf4SFabien Sanglard // Only compare NAME, CLASS, TYPE and RDATA
ACTION_P(PartialCompareRecords,expected)36*3f982cf4SFabien Sanglard ACTION_P(PartialCompareRecords, expected) {
37*3f982cf4SFabien Sanglard const MdnsRecord& actual = arg0;
38*3f982cf4SFabien Sanglard EXPECT_TRUE(actual.name() == expected.name());
39*3f982cf4SFabien Sanglard EXPECT_TRUE(actual.dns_class() == expected.dns_class());
40*3f982cf4SFabien Sanglard EXPECT_TRUE(actual.dns_type() == expected.dns_type());
41*3f982cf4SFabien Sanglard EXPECT_TRUE(actual.rdata() == expected.rdata());
42*3f982cf4SFabien Sanglard return std::vector<PendingQueryChange>{};
43*3f982cf4SFabien Sanglard }
44*3f982cf4SFabien Sanglard
45*3f982cf4SFabien Sanglard class MockRecordChangedCallback : public MdnsRecordChangedCallback {
46*3f982cf4SFabien Sanglard public:
47*3f982cf4SFabien Sanglard MOCK_METHOD(std::vector<PendingQueryChange>,
48*3f982cf4SFabien Sanglard OnRecordChanged,
49*3f982cf4SFabien Sanglard (const MdnsRecord&, RecordChangedEvent event),
50*3f982cf4SFabien Sanglard (override));
51*3f982cf4SFabien Sanglard };
52*3f982cf4SFabien Sanglard
53*3f982cf4SFabien Sanglard class MdnsQuerierTest : public testing::Test {
54*3f982cf4SFabien Sanglard public:
MdnsQuerierTest()55*3f982cf4SFabien Sanglard MdnsQuerierTest()
56*3f982cf4SFabien Sanglard : clock_(Clock::now()),
57*3f982cf4SFabien Sanglard task_runner_(&clock_),
58*3f982cf4SFabien Sanglard sender_(&socket_),
59*3f982cf4SFabien Sanglard receiver_(config_),
60*3f982cf4SFabien Sanglard record0_created_(DomainName{"testing", "local"},
61*3f982cf4SFabien Sanglard DnsType::kA,
62*3f982cf4SFabien Sanglard DnsClass::kIN,
63*3f982cf4SFabien Sanglard RecordType::kUnique,
64*3f982cf4SFabien Sanglard std::chrono::seconds(120),
65*3f982cf4SFabien Sanglard ARecordRdata(IPAddress{172, 0, 0, 1})),
66*3f982cf4SFabien Sanglard record0_updated_(DomainName{"testing", "local"},
67*3f982cf4SFabien Sanglard DnsType::kA,
68*3f982cf4SFabien Sanglard DnsClass::kIN,
69*3f982cf4SFabien Sanglard RecordType::kUnique,
70*3f982cf4SFabien Sanglard std::chrono::seconds(120),
71*3f982cf4SFabien Sanglard ARecordRdata(IPAddress{172, 0, 0, 2})),
72*3f982cf4SFabien Sanglard record0_deleted_(DomainName{"testing", "local"},
73*3f982cf4SFabien Sanglard DnsType::kA,
74*3f982cf4SFabien Sanglard DnsClass::kIN,
75*3f982cf4SFabien Sanglard RecordType::kUnique,
76*3f982cf4SFabien Sanglard std::chrono::seconds(0), // a goodbye record
77*3f982cf4SFabien Sanglard ARecordRdata(IPAddress{172, 0, 0, 2})),
78*3f982cf4SFabien Sanglard record1_created_(DomainName{"poking", "local"},
79*3f982cf4SFabien Sanglard DnsType::kA,
80*3f982cf4SFabien Sanglard DnsClass::kIN,
81*3f982cf4SFabien Sanglard RecordType::kShared,
82*3f982cf4SFabien Sanglard std::chrono::seconds(120),
83*3f982cf4SFabien Sanglard ARecordRdata(IPAddress{192, 168, 0, 1})),
84*3f982cf4SFabien Sanglard record1_deleted_(DomainName{"poking", "local"},
85*3f982cf4SFabien Sanglard DnsType::kA,
86*3f982cf4SFabien Sanglard DnsClass::kIN,
87*3f982cf4SFabien Sanglard RecordType::kShared,
88*3f982cf4SFabien Sanglard std::chrono::seconds(0), // a goodbye record
89*3f982cf4SFabien Sanglard ARecordRdata(IPAddress{192, 168, 0, 1})),
90*3f982cf4SFabien Sanglard record2_created_(DomainName{"testing", "local"},
91*3f982cf4SFabien Sanglard DnsType::kAAAA,
92*3f982cf4SFabien Sanglard DnsClass::kIN,
93*3f982cf4SFabien Sanglard RecordType::kUnique,
94*3f982cf4SFabien Sanglard std::chrono::seconds(120),
95*3f982cf4SFabien Sanglard AAAARecordRdata(IPAddress{1, 2, 3, 4, 5, 6, 7, 8})),
96*3f982cf4SFabien Sanglard nsec_record_created_(
97*3f982cf4SFabien Sanglard DomainName{"testing", "local"},
98*3f982cf4SFabien Sanglard DnsType::kNSEC,
99*3f982cf4SFabien Sanglard DnsClass::kIN,
100*3f982cf4SFabien Sanglard RecordType::kUnique,
101*3f982cf4SFabien Sanglard std::chrono::seconds(120),
102*3f982cf4SFabien Sanglard NsecRecordRdata(DomainName{"testing", "local"}, DnsType::kA)) {
103*3f982cf4SFabien Sanglard receiver_.Start();
104*3f982cf4SFabien Sanglard }
105*3f982cf4SFabien Sanglard
CreateQuerier()106*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> CreateQuerier() {
107*3f982cf4SFabien Sanglard return std::make_unique<MdnsQuerier>(&sender_, &receiver_, &task_runner_,
108*3f982cf4SFabien Sanglard &FakeClock::now, &random_,
109*3f982cf4SFabien Sanglard &reporting_client_, config_);
110*3f982cf4SFabien Sanglard }
111*3f982cf4SFabien Sanglard
112*3f982cf4SFabien Sanglard protected:
113*3f982cf4SFabien Sanglard template <typename... DnsTypes>
CreateNsec(DomainName name,DnsTypes...types)114*3f982cf4SFabien Sanglard MdnsRecord CreateNsec(DomainName name, DnsTypes... types) {
115*3f982cf4SFabien Sanglard NsecRecordRdata rdata(name, types...);
116*3f982cf4SFabien Sanglard return MdnsRecord(std::move(name), nsec_record_created_.dns_type(),
117*3f982cf4SFabien Sanglard nsec_record_created_.dns_class(),
118*3f982cf4SFabien Sanglard nsec_record_created_.record_type(),
119*3f982cf4SFabien Sanglard nsec_record_created_.ttl(), std::move(rdata));
120*3f982cf4SFabien Sanglard }
121*3f982cf4SFabien Sanglard
CreatePacketWithRecords(const std::vector<MdnsRecord::ConstRef> & records,std::vector<MdnsRecord::ConstRef> additional_records)122*3f982cf4SFabien Sanglard UdpPacket CreatePacketWithRecords(
123*3f982cf4SFabien Sanglard const std::vector<MdnsRecord::ConstRef>& records,
124*3f982cf4SFabien Sanglard std::vector<MdnsRecord::ConstRef> additional_records) {
125*3f982cf4SFabien Sanglard MdnsMessage message(CreateMessageId(), MessageType::Response);
126*3f982cf4SFabien Sanglard for (const MdnsRecord& record : records) {
127*3f982cf4SFabien Sanglard message.AddAnswer(record);
128*3f982cf4SFabien Sanglard }
129*3f982cf4SFabien Sanglard for (const MdnsRecord& additional_record : additional_records) {
130*3f982cf4SFabien Sanglard message.AddAdditionalRecord(additional_record);
131*3f982cf4SFabien Sanglard }
132*3f982cf4SFabien Sanglard UdpPacket packet(message.MaxWireSize());
133*3f982cf4SFabien Sanglard MdnsWriter writer(packet.data(), packet.size());
134*3f982cf4SFabien Sanglard EXPECT_TRUE(writer.Write(message));
135*3f982cf4SFabien Sanglard packet.resize(writer.offset());
136*3f982cf4SFabien Sanglard return packet;
137*3f982cf4SFabien Sanglard }
138*3f982cf4SFabien Sanglard
CreatePacketWithRecords(const std::vector<MdnsRecord::ConstRef> & records)139*3f982cf4SFabien Sanglard UdpPacket CreatePacketWithRecords(
140*3f982cf4SFabien Sanglard const std::vector<MdnsRecord::ConstRef>& records) {
141*3f982cf4SFabien Sanglard return CreatePacketWithRecords(records, {});
142*3f982cf4SFabien Sanglard }
143*3f982cf4SFabien Sanglard
CreatePacketWithRecord(const MdnsRecord & record)144*3f982cf4SFabien Sanglard UdpPacket CreatePacketWithRecord(const MdnsRecord& record) {
145*3f982cf4SFabien Sanglard return CreatePacketWithRecords({MdnsRecord::ConstRef(record)});
146*3f982cf4SFabien Sanglard }
147*3f982cf4SFabien Sanglard
148*3f982cf4SFabien Sanglard // NSEC records are never exposed to outside callers, so the below methods are
149*3f982cf4SFabien Sanglard // necessary to validate that they are functioning as expected.
ContainsRecord(MdnsQuerier * querier,const MdnsRecord & record,DnsType type=DnsType::kANY)150*3f982cf4SFabien Sanglard bool ContainsRecord(MdnsQuerier* querier,
151*3f982cf4SFabien Sanglard const MdnsRecord& record,
152*3f982cf4SFabien Sanglard DnsType type = DnsType::kANY) {
153*3f982cf4SFabien Sanglard auto record_trackers =
154*3f982cf4SFabien Sanglard querier->records_.Find(record.name(), type, record.dns_class());
155*3f982cf4SFabien Sanglard
156*3f982cf4SFabien Sanglard return std::find_if(record_trackers.begin(), record_trackers.end(),
157*3f982cf4SFabien Sanglard [&record](const MdnsRecordTracker& tracker) {
158*3f982cf4SFabien Sanglard return tracker.rdata() == record.rdata() &&
159*3f982cf4SFabien Sanglard tracker.ttl() == record.ttl();
160*3f982cf4SFabien Sanglard }) != record_trackers.end();
161*3f982cf4SFabien Sanglard }
162*3f982cf4SFabien Sanglard
RecordCount(MdnsQuerier * querier)163*3f982cf4SFabien Sanglard size_t RecordCount(MdnsQuerier* querier) { return querier->records_.size(); }
164*3f982cf4SFabien Sanglard
165*3f982cf4SFabien Sanglard Config config_;
166*3f982cf4SFabien Sanglard FakeClock clock_;
167*3f982cf4SFabien Sanglard FakeTaskRunner task_runner_;
168*3f982cf4SFabien Sanglard testing::NiceMock<MockUdpSocket> socket_;
169*3f982cf4SFabien Sanglard MdnsSender sender_;
170*3f982cf4SFabien Sanglard MdnsReceiver receiver_;
171*3f982cf4SFabien Sanglard MdnsRandom random_;
172*3f982cf4SFabien Sanglard StrictMock<MockReportingClient> reporting_client_;
173*3f982cf4SFabien Sanglard
174*3f982cf4SFabien Sanglard MdnsRecord record0_created_;
175*3f982cf4SFabien Sanglard MdnsRecord record0_updated_;
176*3f982cf4SFabien Sanglard MdnsRecord record0_deleted_;
177*3f982cf4SFabien Sanglard MdnsRecord record1_created_;
178*3f982cf4SFabien Sanglard MdnsRecord record1_deleted_;
179*3f982cf4SFabien Sanglard MdnsRecord record2_created_;
180*3f982cf4SFabien Sanglard MdnsRecord nsec_record_created_;
181*3f982cf4SFabien Sanglard };
182*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,UniqueRecordCreatedUpdatedDeleted)183*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, UniqueRecordCreatedUpdatedDeleted) {
184*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
185*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
186*3f982cf4SFabien Sanglard
187*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
188*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
189*3f982cf4SFabien Sanglard
190*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
191*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)));
192*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kUpdated))
193*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_updated_)));
194*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kExpired))
195*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_deleted_)));
196*3f982cf4SFabien Sanglard
197*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
198*3f982cf4SFabien Sanglard // Receiving the same record should only reset TTL, no callback
199*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
200*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
201*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_deleted_));
202*3f982cf4SFabien Sanglard
203*3f982cf4SFabien Sanglard // Advance clock for expiration to happen, since it's delayed by 1 second as
204*3f982cf4SFabien Sanglard // per RFC 6762.
205*3f982cf4SFabien Sanglard clock_.Advance(std::chrono::seconds(1));
206*3f982cf4SFabien Sanglard }
207*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,WildcardQuery)208*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, WildcardQuery) {
209*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
210*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
211*3f982cf4SFabien Sanglard
212*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kANY,
213*3f982cf4SFabien Sanglard DnsClass::kANY, &callback);
214*3f982cf4SFabien Sanglard
215*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
216*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record1_created_)));
217*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kExpired))
218*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record1_deleted_)));
219*3f982cf4SFabien Sanglard
220*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
221*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_deleted_));
222*3f982cf4SFabien Sanglard
223*3f982cf4SFabien Sanglard // Advance clock for expiration to happen, since it's delayed by 1 second as
224*3f982cf4SFabien Sanglard // per RFC 6762.
225*3f982cf4SFabien Sanglard clock_.Advance(std::chrono::seconds(1));
226*3f982cf4SFabien Sanglard }
227*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,SharedRecordCreatedDeleted)228*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, SharedRecordCreatedDeleted) {
229*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
230*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
231*3f982cf4SFabien Sanglard
232*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
233*3f982cf4SFabien Sanglard &callback);
234*3f982cf4SFabien Sanglard
235*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
236*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record1_created_)));
237*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kExpired))
238*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record1_deleted_)));
239*3f982cf4SFabien Sanglard
240*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
241*3f982cf4SFabien Sanglard // Receiving the same record should only reset TTL, no callback
242*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
243*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_deleted_));
244*3f982cf4SFabien Sanglard
245*3f982cf4SFabien Sanglard // Advance clock for expiration to happen, since it's delayed by 1 second as
246*3f982cf4SFabien Sanglard // per RFC 6762.
247*3f982cf4SFabien Sanglard clock_.Advance(std::chrono::seconds(1));
248*3f982cf4SFabien Sanglard }
249*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,StartQueryTwice)250*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, StartQueryTwice) {
251*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
252*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
253*3f982cf4SFabien Sanglard
254*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
255*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
256*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
257*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
258*3f982cf4SFabien Sanglard
259*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _)).Times(1);
260*3f982cf4SFabien Sanglard
261*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
262*3f982cf4SFabien Sanglard }
263*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,MultipleCallbacks)264*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, MultipleCallbacks) {
265*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
266*3f982cf4SFabien Sanglard MockRecordChangedCallback callback_1;
267*3f982cf4SFabien Sanglard MockRecordChangedCallback callback_2;
268*3f982cf4SFabien Sanglard
269*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
270*3f982cf4SFabien Sanglard DnsClass::kIN, &callback_1);
271*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
272*3f982cf4SFabien Sanglard DnsClass::kIN, &callback_2);
273*3f982cf4SFabien Sanglard
274*3f982cf4SFabien Sanglard EXPECT_CALL(callback_1, OnRecordChanged(_, _)).Times(1);
275*3f982cf4SFabien Sanglard EXPECT_CALL(callback_2, OnRecordChanged(_, _)).Times(2);
276*3f982cf4SFabien Sanglard
277*3f982cf4SFabien Sanglard // Both callbacks will be invoked.
278*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
279*3f982cf4SFabien Sanglard
280*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
281*3f982cf4SFabien Sanglard &callback_1);
282*3f982cf4SFabien Sanglard
283*3f982cf4SFabien Sanglard // Only callback_2 will be invoked.
284*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
285*3f982cf4SFabien Sanglard
286*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
287*3f982cf4SFabien Sanglard &callback_2);
288*3f982cf4SFabien Sanglard // No callbacks will be invoked as all have been stopped.
289*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
290*3f982cf4SFabien Sanglard }
291*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NoRecordChangesAfterStop)292*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NoRecordChangesAfterStop) {
293*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
294*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
295*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
296*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
297*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _)).Times(1);
298*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
299*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
300*3f982cf4SFabien Sanglard &callback);
301*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
302*3f982cf4SFabien Sanglard }
303*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,OnRecordChangeCallbacksGetRun)304*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, OnRecordChangeCallbacksGetRun) {
305*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
306*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
307*3f982cf4SFabien Sanglard DomainName name = DomainName{"testing", "local"};
308*3f982cf4SFabien Sanglard querier->StartQuery(name, DnsType::kA, DnsClass::kIN, &callback);
309*3f982cf4SFabien Sanglard PendingQueryChange result{name, DnsType::kA, DnsClass::kIN, &callback,
310*3f982cf4SFabien Sanglard PendingQueryChange::kStopQuery};
311*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _))
312*3f982cf4SFabien Sanglard .WillOnce(Return(std::vector<PendingQueryChange>{result}));
313*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
314*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
315*3f982cf4SFabien Sanglard }
316*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,StopQueryTwice)317*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, StopQueryTwice) {
318*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
319*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
320*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
321*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
322*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _)).Times(0);
323*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
324*3f982cf4SFabien Sanglard &callback);
325*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
326*3f982cf4SFabien Sanglard &callback);
327*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
328*3f982cf4SFabien Sanglard }
329*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,StopNonExistingQuery)330*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, StopNonExistingQuery) {
331*3f982cf4SFabien Sanglard // Just making sure nothing crashes.
332*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
333*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
334*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
335*3f982cf4SFabien Sanglard &callback);
336*3f982cf4SFabien Sanglard }
337*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,IrrelevantRecordReceived)338*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, IrrelevantRecordReceived) {
339*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
340*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
341*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
342*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
343*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _)).Times(1);
344*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
345*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
346*3f982cf4SFabien Sanglard }
347*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,DifferentCallersSameQuestion)348*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, DifferentCallersSameQuestion) {
349*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
350*3f982cf4SFabien Sanglard MockRecordChangedCallback callback1;
351*3f982cf4SFabien Sanglard MockRecordChangedCallback callback2;
352*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
353*3f982cf4SFabien Sanglard DnsClass::kIN, &callback1);
354*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
355*3f982cf4SFabien Sanglard DnsClass::kIN, &callback2);
356*3f982cf4SFabien Sanglard EXPECT_CALL(callback1, OnRecordChanged(_, _)).Times(1);
357*3f982cf4SFabien Sanglard EXPECT_CALL(callback2, OnRecordChanged(_, _)).Times(1);
358*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
359*3f982cf4SFabien Sanglard }
360*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,DifferentCallersDifferentQuestions)361*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, DifferentCallersDifferentQuestions) {
362*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
363*3f982cf4SFabien Sanglard MockRecordChangedCallback callback1;
364*3f982cf4SFabien Sanglard MockRecordChangedCallback callback2;
365*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
366*3f982cf4SFabien Sanglard DnsClass::kIN, &callback1);
367*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
368*3f982cf4SFabien Sanglard &callback2);
369*3f982cf4SFabien Sanglard EXPECT_CALL(callback1, OnRecordChanged(_, _)).Times(1);
370*3f982cf4SFabien Sanglard EXPECT_CALL(callback2, OnRecordChanged(_, _)).Times(1);
371*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
372*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
373*3f982cf4SFabien Sanglard }
374*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,SameCallerDifferentQuestions)375*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, SameCallerDifferentQuestions) {
376*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
377*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
378*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
379*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
380*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
381*3f982cf4SFabien Sanglard &callback);
382*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, _)).Times(2);
383*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
384*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
385*3f982cf4SFabien Sanglard }
386*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,ReinitializeQueries)387*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, ReinitializeQueries) {
388*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
389*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
390*3f982cf4SFabien Sanglard
391*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
392*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
393*3f982cf4SFabien Sanglard
394*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
395*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)));
396*3f982cf4SFabien Sanglard
397*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
398*3f982cf4SFabien Sanglard // Receiving the same record should only reset TTL, no callback
399*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
400*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&receiver_);
401*3f982cf4SFabien Sanglard
402*3f982cf4SFabien Sanglard // Queries should still be ongoing but all received records should have been
403*3f982cf4SFabien Sanglard // deleted.
404*3f982cf4SFabien Sanglard querier->ReinitializeQueries(DomainName{"testing", "local"});
405*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
406*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)));
407*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
408*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&receiver_);
409*3f982cf4SFabien Sanglard
410*3f982cf4SFabien Sanglard // Reinitializing a different domain should not affect other queries.
411*3f982cf4SFabien Sanglard querier->ReinitializeQueries(DomainName{"testing2", "local"});
412*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
413*3f982cf4SFabien Sanglard }
414*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,MessagesForUnknownQueriesDropped)415*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, MessagesForUnknownQueriesDropped) {
416*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
417*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
418*3f982cf4SFabien Sanglard
419*3f982cf4SFabien Sanglard // Message for unknown query does not get processed.
420*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
421*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
422*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record1_created_));
423*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
424*3f982cf4SFabien Sanglard &callback);
425*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
426*3f982cf4SFabien Sanglard
427*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
428*3f982cf4SFabien Sanglard &callback);
429*3f982cf4SFabien Sanglard
430*3f982cf4SFabien Sanglard // Only known records from the message are processed.
431*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
432*3f982cf4SFabien Sanglard .Times(1);
433*3f982cf4SFabien Sanglard receiver_.OnRead(
434*3f982cf4SFabien Sanglard &socket_, CreatePacketWithRecords({record0_created_, record1_created_}));
435*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
436*3f982cf4SFabien Sanglard &callback);
437*3f982cf4SFabien Sanglard }
438*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,MessagesForKnownRecordsAllowed)439*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, MessagesForKnownRecordsAllowed) {
440*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
441*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
442*3f982cf4SFabien Sanglard
443*3f982cf4SFabien Sanglard // Store a message for a known query.
444*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
445*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
446*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_created_));
447*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
448*3f982cf4SFabien Sanglard
449*3f982cf4SFabien Sanglard // Stop the query and validate that record updates are still received.
450*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
451*3f982cf4SFabien Sanglard &callback);
452*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecord(record0_updated_));
453*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
454*3f982cf4SFabien Sanglard
455*3f982cf4SFabien Sanglard querier->StopQuery(DomainName{"poking", "local"}, DnsType::kA, DnsClass::kIN,
456*3f982cf4SFabien Sanglard &callback);
457*3f982cf4SFabien Sanglard
458*3f982cf4SFabien Sanglard // Only known records from the message are processed.
459*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
460*3f982cf4SFabien Sanglard OnRecordChanged(record0_updated_, RecordChangedEvent::kCreated))
461*3f982cf4SFabien Sanglard .Times(1);
462*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
463*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
464*3f982cf4SFabien Sanglard }
465*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,MessagesForUnknownKnownRecordsAllowsAdditionalRecords)466*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, MessagesForUnknownKnownRecordsAllowsAdditionalRecords) {
467*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
468*3f982cf4SFabien Sanglard MockRecordChangedCallback callback;
469*3f982cf4SFabien Sanglard
470*3f982cf4SFabien Sanglard // Store a message for a known query.
471*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
472*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
473*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
474*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kCreated))
475*3f982cf4SFabien Sanglard .Times(1);
476*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, CreatePacketWithRecords({record1_created_},
477*3f982cf4SFabien Sanglard {record0_created_}));
478*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
479*3f982cf4SFabien Sanglard }
480*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecDroppedWhenCorrespondsToNonNsec)481*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecDroppedWhenCorrespondsToNonNsec) {
482*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
483*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
484*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
485*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
486*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecords(
487*3f982cf4SFabien Sanglard {record0_created_, nsec_record_created_, record2_created_});
488*3f982cf4SFabien Sanglard
489*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
490*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)))
491*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record2_created_)));
492*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
493*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{2});
494*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
495*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record2_created_, DnsType::kAAAA));
496*3f982cf4SFabien Sanglard
497*3f982cf4SFabien Sanglard // Do it again in the another record order.
498*3f982cf4SFabien Sanglard querier = CreateQuerier();
499*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
500*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
501*3f982cf4SFabien Sanglard packet = CreatePacketWithRecords(
502*3f982cf4SFabien Sanglard {nsec_record_created_, record2_created_, record0_created_});
503*3f982cf4SFabien Sanglard
504*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
505*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)))
506*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record2_created_)));
507*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
508*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{2});
509*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
510*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record2_created_, DnsType::kAAAA));
511*3f982cf4SFabien Sanglard }
512*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,MultipleNsecCombinedWhenSameName)513*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, MultipleNsecCombinedWhenSameName) {
514*3f982cf4SFabien Sanglard DomainName alternate_name{"poking", "local"};
515*3f982cf4SFabien Sanglard MdnsRecord multi_type_nsec =
516*3f982cf4SFabien Sanglard CreateNsec(nsec_record_created_.name(), DnsType::kA, DnsType::kAAAA);
517*3f982cf4SFabien Sanglard MdnsRecord aaaa_nsec =
518*3f982cf4SFabien Sanglard CreateNsec(nsec_record_created_.name(), DnsType::kAAAA);
519*3f982cf4SFabien Sanglard MdnsRecord srv_nsec = CreateNsec(alternate_name, DnsType::kSRV);
520*3f982cf4SFabien Sanglard
521*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
522*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
523*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
524*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
525*3f982cf4SFabien Sanglard querier->StartQuery(alternate_name, DnsType::kANY, DnsClass::kIN, &callback);
526*3f982cf4SFabien Sanglard auto packet =
527*3f982cf4SFabien Sanglard CreatePacketWithRecords({nsec_record_created_, srv_nsec, aaaa_nsec});
528*3f982cf4SFabien Sanglard
529*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
530*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{3});
531*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kA));
532*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kAAAA));
533*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), srv_nsec, DnsType::kSRV));
534*3f982cf4SFabien Sanglard }
535*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecBitsUnSetWhenCorrespondsToExistingRecord)536*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecBitsUnSetWhenCorrespondsToExistingRecord) {
537*3f982cf4SFabien Sanglard MdnsRecord multi_type_nsec =
538*3f982cf4SFabien Sanglard CreateNsec(nsec_record_created_.name(), DnsType::kA, DnsType::kAAAA);
539*3f982cf4SFabien Sanglard MdnsRecord aaaa_nsec =
540*3f982cf4SFabien Sanglard CreateNsec(nsec_record_created_.name(), DnsType::kAAAA);
541*3f982cf4SFabien Sanglard
542*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
543*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
544*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
545*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
546*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecords({multi_type_nsec, record0_created_});
547*3f982cf4SFabien Sanglard
548*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
549*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)));
550*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
551*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{2});
552*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
553*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa_nsec, DnsType::kAAAA));
554*3f982cf4SFabien Sanglard
555*3f982cf4SFabien Sanglard // Do it again in the another record order.
556*3f982cf4SFabien Sanglard querier = CreateQuerier();
557*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
558*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
559*3f982cf4SFabien Sanglard packet = CreatePacketWithRecords({record0_created_, multi_type_nsec});
560*3f982cf4SFabien Sanglard
561*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
562*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)));
563*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
564*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{2});
565*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
566*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa_nsec, DnsType::kAAAA));
567*3f982cf4SFabien Sanglard }
568*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecDroppedWhenAllBitsUnset)569*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecDroppedWhenAllBitsUnset) {
570*3f982cf4SFabien Sanglard MdnsRecord multi_type_nsec =
571*3f982cf4SFabien Sanglard CreateNsec(nsec_record_created_.name(), DnsType::kA, DnsType::kAAAA);
572*3f982cf4SFabien Sanglard MdnsRecord aaaa(record0_created_.name(), DnsType::kAAAA,
573*3f982cf4SFabien Sanglard record0_created_.dns_class(), record0_created_.record_type(),
574*3f982cf4SFabien Sanglard record0_created_.ttl(),
575*3f982cf4SFabien Sanglard AAAARecordRdata(IPAddress{172, 0, 0, 0, 0, 0, 0, 1}));
576*3f982cf4SFabien Sanglard
577*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
578*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
579*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
580*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
581*3f982cf4SFabien Sanglard auto packet =
582*3f982cf4SFabien Sanglard CreatePacketWithRecords({multi_type_nsec, record0_created_, aaaa});
583*3f982cf4SFabien Sanglard
584*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
585*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(record0_created_)))
586*3f982cf4SFabien Sanglard .WillOnce(WithArgs<0>(PartialCompareRecords(aaaa)));
587*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
588*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{2});
589*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
590*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa, DnsType::kAAAA));
591*3f982cf4SFabien Sanglard }
592*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecUpdatesMultipleRecords)593*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecUpdatesMultipleRecords) {
594*3f982cf4SFabien Sanglard const DomainName& first_name = record0_created_.name();
595*3f982cf4SFabien Sanglard const DomainName alternate_name{"poking", "local"};
596*3f982cf4SFabien Sanglard const DomainName third_name{"third", "local"};
597*3f982cf4SFabien Sanglard MdnsRecord nsec_first_name =
598*3f982cf4SFabien Sanglard CreateNsec(first_name, DnsType::kA, DnsType::kAAAA, DnsType::kSRV);
599*3f982cf4SFabien Sanglard MdnsRecord aaaa(alternate_name, DnsType::kAAAA, record0_created_.dns_class(),
600*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
601*3f982cf4SFabien Sanglard AAAARecordRdata(IPAddress{172, 0, 0, 0, 0, 0, 0, 1}));
602*3f982cf4SFabien Sanglard MdnsRecord nsec_second_name =
603*3f982cf4SFabien Sanglard CreateNsec(alternate_name, DnsType::kA, DnsType::kAAAA, DnsType::kSRV);
604*3f982cf4SFabien Sanglard
605*3f982cf4SFabien Sanglard MdnsRecord srv(third_name, DnsType::kSRV, record0_created_.dns_class(),
606*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
607*3f982cf4SFabien Sanglard SrvRecordRdata(1, 2, 3, third_name));
608*3f982cf4SFabien Sanglard MdnsRecord nsec_third_name =
609*3f982cf4SFabien Sanglard CreateNsec(third_name, DnsType::kA, DnsType::kAAAA, DnsType::kSRV);
610*3f982cf4SFabien Sanglard
611*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
612*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
613*3f982cf4SFabien Sanglard querier->StartQuery(first_name, DnsType::kANY, DnsClass::kIN, &callback);
614*3f982cf4SFabien Sanglard querier->StartQuery(alternate_name, DnsType::kANY, DnsClass::kIN, &callback);
615*3f982cf4SFabien Sanglard querier->StartQuery(third_name, DnsType::kANY, DnsClass::kIN, &callback);
616*3f982cf4SFabien Sanglard auto packet =
617*3f982cf4SFabien Sanglard CreatePacketWithRecords({nsec_first_name, nsec_second_name,
618*3f982cf4SFabien Sanglard nsec_third_name, record0_created_, aaaa, srv});
619*3f982cf4SFabien Sanglard
620*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
621*3f982cf4SFabien Sanglard .Times(3);
622*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
623*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{9});
624*3f982cf4SFabien Sanglard
625*3f982cf4SFabien Sanglard MdnsRecord new_first_nsec =
626*3f982cf4SFabien Sanglard CreateNsec(first_name, DnsType::kAAAA, DnsType::kSRV);
627*3f982cf4SFabien Sanglard MdnsRecord new_second_nsec =
628*3f982cf4SFabien Sanglard CreateNsec(alternate_name, DnsType::kA, DnsType::kSRV);
629*3f982cf4SFabien Sanglard MdnsRecord new_third_nsec =
630*3f982cf4SFabien Sanglard CreateNsec(third_name, DnsType::kA, DnsType::kAAAA);
631*3f982cf4SFabien Sanglard
632*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
633*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_first_nsec, DnsType::kAAAA));
634*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_first_nsec, DnsType::kSRV));
635*3f982cf4SFabien Sanglard
636*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_second_nsec, DnsType::kA));
637*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa, DnsType::kAAAA));
638*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_second_nsec, DnsType::kSRV));
639*3f982cf4SFabien Sanglard
640*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_third_nsec, DnsType::kA));
641*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), new_third_nsec, DnsType::kAAAA));
642*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), srv, DnsType::kSRV));
643*3f982cf4SFabien Sanglard }
644*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecDeletesMultipleRecords)645*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecDeletesMultipleRecords) {
646*3f982cf4SFabien Sanglard const DomainName& first_name = record0_created_.name();
647*3f982cf4SFabien Sanglard const DomainName alternate_name{"poking", "local"};
648*3f982cf4SFabien Sanglard MdnsRecord nsec_first = CreateNsec(first_name, DnsType::kA);
649*3f982cf4SFabien Sanglard
650*3f982cf4SFabien Sanglard MdnsRecord aaaa(alternate_name, DnsType::kAAAA, record0_created_.dns_class(),
651*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
652*3f982cf4SFabien Sanglard AAAARecordRdata(IPAddress{172, 0, 0, 0, 0, 0, 0, 1}));
653*3f982cf4SFabien Sanglard MdnsRecord srv(alternate_name, DnsType::kSRV, record0_created_.dns_class(),
654*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
655*3f982cf4SFabien Sanglard SrvRecordRdata(1, 2, 3, first_name));
656*3f982cf4SFabien Sanglard MdnsRecord nsec_second =
657*3f982cf4SFabien Sanglard CreateNsec(alternate_name, DnsType::kAAAA, DnsType::kSRV);
658*3f982cf4SFabien Sanglard MdnsRecord nsec_third = CreateNsec(alternate_name, DnsType::kAAAA);
659*3f982cf4SFabien Sanglard
660*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
661*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
662*3f982cf4SFabien Sanglard querier->StartQuery(first_name, DnsType::kANY, DnsClass::kIN, &callback);
663*3f982cf4SFabien Sanglard querier->StartQuery(alternate_name, DnsType::kANY, DnsClass::kIN, &callback);
664*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecords(
665*3f982cf4SFabien Sanglard {record0_created_, aaaa, srv, nsec_first, nsec_second, nsec_third});
666*3f982cf4SFabien Sanglard
667*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
668*3f982cf4SFabien Sanglard .Times(3);
669*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
670*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{3});
671*3f982cf4SFabien Sanglard
672*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
673*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa, DnsType::kAAAA));
674*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), srv, DnsType::kSRV));
675*3f982cf4SFabien Sanglard }
676*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NsecCreatesUpdatesAndDeletesMultipleRecords)677*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NsecCreatesUpdatesAndDeletesMultipleRecords) {
678*3f982cf4SFabien Sanglard const DomainName& first_name = record0_created_.name();
679*3f982cf4SFabien Sanglard const DomainName alternate_name{"poking", "local"};
680*3f982cf4SFabien Sanglard const DomainName third_name{"third", "local"};
681*3f982cf4SFabien Sanglard MdnsRecord nsec_first_name = CreateNsec(first_name, DnsType::kA);
682*3f982cf4SFabien Sanglard
683*3f982cf4SFabien Sanglard MdnsRecord aaaa(alternate_name, DnsType::kAAAA, record0_created_.dns_class(),
684*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
685*3f982cf4SFabien Sanglard AAAARecordRdata(IPAddress{172, 0, 0, 0, 0, 0, 0, 1}));
686*3f982cf4SFabien Sanglard MdnsRecord nsec_second_name =
687*3f982cf4SFabien Sanglard CreateNsec(alternate_name, DnsType::kAAAA, DnsType::kSRV);
688*3f982cf4SFabien Sanglard MdnsRecord srv(alternate_name, DnsType::kSRV, record0_created_.dns_class(),
689*3f982cf4SFabien Sanglard record0_created_.record_type(), record0_created_.ttl(),
690*3f982cf4SFabien Sanglard SrvRecordRdata(1, 2, 3, third_name));
691*3f982cf4SFabien Sanglard
692*3f982cf4SFabien Sanglard MdnsRecord nsec_third_name = CreateNsec(third_name, DnsType::kA);
693*3f982cf4SFabien Sanglard
694*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
695*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
696*3f982cf4SFabien Sanglard querier->StartQuery(first_name, DnsType::kANY, DnsClass::kIN, &callback);
697*3f982cf4SFabien Sanglard querier->StartQuery(alternate_name, DnsType::kANY, DnsClass::kIN, &callback);
698*3f982cf4SFabien Sanglard querier->StartQuery(third_name, DnsType::kANY, DnsClass::kIN, &callback);
699*3f982cf4SFabien Sanglard auto packet =
700*3f982cf4SFabien Sanglard CreatePacketWithRecords({nsec_first_name, nsec_second_name,
701*3f982cf4SFabien Sanglard nsec_third_name, record0_created_, aaaa, srv});
702*3f982cf4SFabien Sanglard
703*3f982cf4SFabien Sanglard EXPECT_CALL(callback, OnRecordChanged(_, RecordChangedEvent::kCreated))
704*3f982cf4SFabien Sanglard .Times(3);
705*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
706*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{4});
707*3f982cf4SFabien Sanglard
708*3f982cf4SFabien Sanglard MdnsRecord new_second_nsec = CreateNsec(alternate_name, DnsType::kSRV);
709*3f982cf4SFabien Sanglard
710*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
711*3f982cf4SFabien Sanglard
712*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), aaaa, DnsType::kAAAA));
713*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), srv, DnsType::kSRV));
714*3f982cf4SFabien Sanglard
715*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), nsec_third_name, DnsType::kA));
716*3f982cf4SFabien Sanglard }
717*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,CallbackNotCalledOnStartQueryForNsecRecords)718*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, CallbackNotCalledOnStartQueryForNsecRecords) {
719*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
720*3f982cf4SFabien Sanglard
721*3f982cf4SFabien Sanglard // Set up so an NSEC record has been received
722*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
723*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
724*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
725*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(nsec_record_created_);
726*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
727*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{1});
728*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
729*3f982cf4SFabien Sanglard
730*3f982cf4SFabien Sanglard // Start new query
731*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
732*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
733*3f982cf4SFabien Sanglard }
734*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,ReceiveNsecRecordFansOutToEachType)735*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, ReceiveNsecRecordFansOutToEachType) {
736*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
737*3f982cf4SFabien Sanglard
738*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
739*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
740*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
741*3f982cf4SFabien Sanglard MdnsRecord multi_type_nsec =
742*3f982cf4SFabien Sanglard MdnsRecord(nsec_record_created_.name(), nsec_record_created_.dns_type(),
743*3f982cf4SFabien Sanglard nsec_record_created_.dns_class(),
744*3f982cf4SFabien Sanglard nsec_record_created_.record_type(), nsec_record_created_.ttl(),
745*3f982cf4SFabien Sanglard NsecRecordRdata(nsec_record_created_.name(), DnsType::kA,
746*3f982cf4SFabien Sanglard DnsType::kSRV, DnsType::kAAAA));
747*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(multi_type_nsec);
748*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
749*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{3});
750*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kA));
751*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kAAAA));
752*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kSRV));
753*3f982cf4SFabien Sanglard }
754*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,ReceiveNsecKAnyRecordFansOutToAllTypes)755*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, ReceiveNsecKAnyRecordFansOutToAllTypes) {
756*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
757*3f982cf4SFabien Sanglard
758*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
759*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
760*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
761*3f982cf4SFabien Sanglard MdnsRecord any_type_nsec =
762*3f982cf4SFabien Sanglard MdnsRecord(nsec_record_created_.name(), nsec_record_created_.dns_type(),
763*3f982cf4SFabien Sanglard nsec_record_created_.dns_class(),
764*3f982cf4SFabien Sanglard nsec_record_created_.record_type(), nsec_record_created_.ttl(),
765*3f982cf4SFabien Sanglard NsecRecordRdata(nsec_record_created_.name(), DnsType::kANY));
766*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(any_type_nsec);
767*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
768*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{5});
769*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), any_type_nsec, DnsType::kA));
770*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), any_type_nsec, DnsType::kAAAA));
771*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), any_type_nsec, DnsType::kSRV));
772*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), any_type_nsec, DnsType::kTXT));
773*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), any_type_nsec, DnsType::kPTR));
774*3f982cf4SFabien Sanglard }
775*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,CorrectCallbackCalledWhenNsecRecordReplacesNonNsec)776*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, CorrectCallbackCalledWhenNsecRecordReplacesNonNsec) {
777*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
778*3f982cf4SFabien Sanglard
779*3f982cf4SFabien Sanglard // Set up so an A record has been received
780*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
781*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
782*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
783*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
784*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kCreated));
785*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(record0_created_);
786*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
787*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
788*3f982cf4SFabien Sanglard ASSERT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
789*3f982cf4SFabien Sanglard EXPECT_FALSE(
790*3f982cf4SFabien Sanglard ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
791*3f982cf4SFabien Sanglard
792*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
793*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kExpired));
794*3f982cf4SFabien Sanglard packet = CreatePacketWithRecord(nsec_record_created_);
795*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
796*3f982cf4SFabien Sanglard EXPECT_FALSE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
797*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
798*3f982cf4SFabien Sanglard }
799*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NoCallbackCalledWhenNsecRecordWouldReplaceNonNsecButNsecDisabled)800*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest,
801*3f982cf4SFabien Sanglard NoCallbackCalledWhenNsecRecordWouldReplaceNonNsecButNsecDisabled) {
802*3f982cf4SFabien Sanglard config_.ignore_nsec_responses = true;
803*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
804*3f982cf4SFabien Sanglard
805*3f982cf4SFabien Sanglard // Set up so an A record has been received
806*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
807*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
808*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
809*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
810*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kCreated));
811*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(record0_created_);
812*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
813*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
814*3f982cf4SFabien Sanglard ASSERT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
815*3f982cf4SFabien Sanglard EXPECT_FALSE(
816*3f982cf4SFabien Sanglard ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
817*3f982cf4SFabien Sanglard
818*3f982cf4SFabien Sanglard packet = CreatePacketWithRecord(nsec_record_created_);
819*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
820*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
821*3f982cf4SFabien Sanglard EXPECT_FALSE(
822*3f982cf4SFabien Sanglard ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
823*3f982cf4SFabien Sanglard }
824*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,CorrectCallbackCalledWhenNonNsecRecordReplacesNsec)825*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, CorrectCallbackCalledWhenNonNsecRecordReplacesNsec) {
826*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
827*3f982cf4SFabien Sanglard
828*3f982cf4SFabien Sanglard // Set up so an A record has been received
829*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
830*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
831*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
832*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(nsec_record_created_);
833*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
834*3f982cf4SFabien Sanglard ASSERT_TRUE(ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
835*3f982cf4SFabien Sanglard EXPECT_FALSE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
836*3f982cf4SFabien Sanglard
837*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
838*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kCreated));
839*3f982cf4SFabien Sanglard packet = CreatePacketWithRecord(record0_created_);
840*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
841*3f982cf4SFabien Sanglard EXPECT_FALSE(
842*3f982cf4SFabien Sanglard ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
843*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
844*3f982cf4SFabien Sanglard }
845*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,NoCallbackCalledWhenSecondNsecRecordReceived)846*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, NoCallbackCalledWhenSecondNsecRecordReceived) {
847*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
848*3f982cf4SFabien Sanglard MdnsRecord multi_type_nsec =
849*3f982cf4SFabien Sanglard MdnsRecord(nsec_record_created_.name(), nsec_record_created_.dns_type(),
850*3f982cf4SFabien Sanglard nsec_record_created_.dns_class(),
851*3f982cf4SFabien Sanglard nsec_record_created_.record_type(), nsec_record_created_.ttl(),
852*3f982cf4SFabien Sanglard NsecRecordRdata(nsec_record_created_.name(), DnsType::kA,
853*3f982cf4SFabien Sanglard DnsType::kSRV, DnsType::kAAAA));
854*3f982cf4SFabien Sanglard
855*3f982cf4SFabien Sanglard // Set up so an A record has been received
856*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
857*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kA,
858*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
859*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(nsec_record_created_);
860*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
861*3f982cf4SFabien Sanglard ASSERT_TRUE(ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
862*3f982cf4SFabien Sanglard EXPECT_FALSE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kA));
863*3f982cf4SFabien Sanglard
864*3f982cf4SFabien Sanglard packet = CreatePacketWithRecord(multi_type_nsec);
865*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
866*3f982cf4SFabien Sanglard EXPECT_FALSE(
867*3f982cf4SFabien Sanglard ContainsRecord(querier.get(), nsec_record_created_, DnsType::kA));
868*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), multi_type_nsec, DnsType::kA));
869*3f982cf4SFabien Sanglard }
870*3f982cf4SFabien Sanglard
TEST_F(MdnsQuerierTest,TestMaxRecordsRespected)871*3f982cf4SFabien Sanglard TEST_F(MdnsQuerierTest, TestMaxRecordsRespected) {
872*3f982cf4SFabien Sanglard config_.querier_max_records_cached = 1;
873*3f982cf4SFabien Sanglard std::unique_ptr<MdnsQuerier> querier = CreateQuerier();
874*3f982cf4SFabien Sanglard
875*3f982cf4SFabien Sanglard // Set up so an A record has been received
876*3f982cf4SFabien Sanglard StrictMock<MockRecordChangedCallback> callback;
877*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"testing", "local"}, DnsType::kANY,
878*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
879*3f982cf4SFabien Sanglard querier->StartQuery(DomainName{"poking", "local"}, DnsType::kANY,
880*3f982cf4SFabien Sanglard DnsClass::kIN, &callback);
881*3f982cf4SFabien Sanglard auto packet = CreatePacketWithRecord(record0_created_);
882*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
883*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kCreated));
884*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
885*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{1});
886*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
887*3f982cf4SFabien Sanglard EXPECT_FALSE(ContainsRecord(querier.get(), record1_created_, DnsType::kA));
888*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&callback);
889*3f982cf4SFabien Sanglard
890*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
891*3f982cf4SFabien Sanglard OnRecordChanged(record0_created_, RecordChangedEvent::kExpired));
892*3f982cf4SFabien Sanglard EXPECT_CALL(callback,
893*3f982cf4SFabien Sanglard OnRecordChanged(record1_created_, RecordChangedEvent::kCreated));
894*3f982cf4SFabien Sanglard packet = CreatePacketWithRecord(record1_created_);
895*3f982cf4SFabien Sanglard receiver_.OnRead(&socket_, std::move(packet));
896*3f982cf4SFabien Sanglard ASSERT_EQ(RecordCount(querier.get()), size_t{1});
897*3f982cf4SFabien Sanglard EXPECT_FALSE(ContainsRecord(querier.get(), record0_created_, DnsType::kA));
898*3f982cf4SFabien Sanglard EXPECT_TRUE(ContainsRecord(querier.get(), record1_created_, DnsType::kA));
899*3f982cf4SFabien Sanglard }
900*3f982cf4SFabien Sanglard
901*3f982cf4SFabien Sanglard } // namespace discovery
902*3f982cf4SFabien Sanglard } // namespace openscreen
903