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