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_records.h"
6
7 #include <limits>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "discovery/mdns/mdns_reader.h"
13 #include "discovery/mdns/mdns_writer.h"
14 #include "discovery/mdns/testing/hash_test_util.h"
15 #include "discovery/mdns/testing/mdns_test_util.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 #include "platform/api/network_interface.h"
19
20 namespace openscreen {
21 namespace discovery {
22
23 using testing::ElementsAreArray;
24
25 namespace {
26
27 constexpr std::chrono::seconds kTtl{120};
28
29 template <class T>
TestCopyAndMove(const T & value)30 void TestCopyAndMove(const T& value) {
31 T value_copy_constuct(value);
32 EXPECT_EQ(value_copy_constuct, value);
33 T value_copy_assign = value;
34 EXPECT_EQ(value_copy_assign, value);
35 T value_move_constuct(std::move(value_copy_constuct));
36 EXPECT_EQ(value_move_constuct, value);
37 T value_move_assign = std::move(value_copy_assign);
38 EXPECT_EQ(value_move_assign, value);
39 }
40
41 } // namespace
42
TEST(MdnsDomainNameTest,Construct)43 TEST(MdnsDomainNameTest, Construct) {
44 DomainName name1;
45 EXPECT_TRUE(name1.empty());
46 EXPECT_EQ(name1.MaxWireSize(), UINT64_C(1));
47 EXPECT_EQ(name1.labels().size(), UINT64_C(0));
48
49 DomainName name2{"MyDevice", "_mYSERvice", "local"};
50 EXPECT_FALSE(name2.empty());
51 EXPECT_EQ(name2.MaxWireSize(), UINT64_C(27));
52 ASSERT_EQ(name2.labels().size(), UINT64_C(3));
53 EXPECT_EQ(name2.labels()[0], "MyDevice");
54 EXPECT_EQ(name2.labels()[1], "_mYSERvice");
55 EXPECT_EQ(name2.labels()[2], "local");
56 EXPECT_EQ(name2.ToString(), "MyDevice._mYSERvice.local");
57
58 std::vector<absl::string_view> labels{"OtherDevice", "_MYservice", "LOcal"};
59 DomainName name3(labels);
60 EXPECT_FALSE(name3.empty());
61 EXPECT_EQ(name3.MaxWireSize(), UINT64_C(30));
62 ASSERT_EQ(name3.labels().size(), UINT64_C(3));
63 EXPECT_EQ(name3.labels()[0], "OtherDevice");
64 EXPECT_EQ(name3.labels()[1], "_MYservice");
65 EXPECT_EQ(name3.labels()[2], "LOcal");
66 EXPECT_EQ(name3.ToString(), "OtherDevice._MYservice.LOcal");
67 }
68
TEST(MdnsDomainNameTest,Compare)69 TEST(MdnsDomainNameTest, Compare) {
70 DomainName first{"testing", "local"};
71 DomainName second{"TeStInG", "LOCAL"};
72 DomainName third{"testing"};
73 DomainName fourth{"testing.local"};
74 DomainName fifth{"Testing.Local"};
75
76 EXPECT_EQ(first, second);
77 EXPECT_TRUE(first >= second);
78 EXPECT_TRUE(second >= first);
79 EXPECT_TRUE(first <= second);
80 EXPECT_TRUE(second <= first);
81 EXPECT_EQ(fourth, fifth);
82 EXPECT_NE(first, third);
83 EXPECT_NE(first, fourth);
84
85 EXPECT_FALSE(first < second);
86 EXPECT_FALSE(second < first);
87 EXPECT_FALSE(first < third);
88 EXPECT_TRUE(third < first);
89 EXPECT_TRUE(third <= first);
90 EXPECT_FALSE(third > first);
91 EXPECT_TRUE(first < fourth);
92 EXPECT_TRUE(fourth > first);
93 EXPECT_TRUE(fourth >= first);
94 EXPECT_TRUE(first < fifth);
95 EXPECT_FALSE(fifth < first);
96
97 EXPECT_FALSE(second < third);
98 EXPECT_TRUE(third < second);
99 EXPECT_TRUE(second < fourth);
100 EXPECT_FALSE(fourth < second);
101 EXPECT_TRUE(second < fifth);
102 EXPECT_FALSE(fifth < second);
103
104 EXPECT_TRUE(third < fourth);
105 EXPECT_FALSE(fourth < third);
106 EXPECT_TRUE(third < fifth);
107 EXPECT_FALSE(fifth < third);
108
109 EXPECT_FALSE(fourth < fifth);
110 EXPECT_FALSE(fifth < fourth);
111
112 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly(
113 {first, second, third, fourth, fifth}));
114 }
115
TEST(MdnsDomainNameTest,CopyAndMove)116 TEST(MdnsDomainNameTest, CopyAndMove) {
117 TestCopyAndMove(DomainName{"testing", "local"});
118 }
119
TEST(MdnsRawRecordRdataTest,Construct)120 TEST(MdnsRawRecordRdataTest, Construct) {
121 constexpr uint8_t kRawRdata[] = {
122 0x05, 'c', 'n', 'a', 'm', 'e', 0xc0, 0x00,
123 };
124
125 RawRecordRdata rdata1;
126 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(2));
127 EXPECT_EQ(rdata1.size(), UINT16_C(0));
128
129 RawRecordRdata rdata2(kRawRdata, sizeof(kRawRdata));
130 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(10));
131 EXPECT_EQ(rdata2.size(), UINT16_C(8));
132 EXPECT_THAT(
133 std::vector<uint8_t>(rdata2.data(), rdata2.data() + rdata2.size()),
134 ElementsAreArray(kRawRdata));
135
136 RawRecordRdata rdata3(
137 std::vector<uint8_t>(kRawRdata, kRawRdata + sizeof(kRawRdata)));
138 EXPECT_EQ(rdata3.MaxWireSize(), UINT64_C(10));
139 EXPECT_EQ(rdata3.size(), UINT16_C(8));
140 EXPECT_THAT(
141 std::vector<uint8_t>(rdata3.data(), rdata3.data() + rdata3.size()),
142 ElementsAreArray(kRawRdata));
143 }
144
TEST(MdnsRawRecordRdataTest,Compare)145 TEST(MdnsRawRecordRdataTest, Compare) {
146 constexpr uint8_t kRawRdata1[] = {
147 0x05, 'c', 'n', 'a', 'm', 'e', 0xc0, 0x00,
148 };
149 constexpr uint8_t kRawRdata2[] = {
150 0x05, 'r', 'd', 'a', 't', 'a',
151 };
152
153 RawRecordRdata rdata1(kRawRdata1, sizeof(kRawRdata1));
154 RawRecordRdata rdata2(kRawRdata1, sizeof(kRawRdata1));
155 RawRecordRdata rdata3(kRawRdata2, sizeof(kRawRdata2));
156
157 EXPECT_EQ(rdata1, rdata2);
158 EXPECT_NE(rdata1, rdata3);
159
160 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3}));
161 }
162
TEST(MdnsRawRecordRdataTest,CopyAndMove)163 TEST(MdnsRawRecordRdataTest, CopyAndMove) {
164 constexpr uint8_t kRawRdata[] = {
165 0x05, 'c', 'n', 'a', 'm', 'e', 0xc0, 0x00,
166 };
167 TestCopyAndMove(RawRecordRdata(kRawRdata, sizeof(kRawRdata)));
168 }
169
TEST(MdnsSrvRecordRdataTest,Construct)170 TEST(MdnsSrvRecordRdataTest, Construct) {
171 SrvRecordRdata rdata1;
172 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(9));
173 EXPECT_EQ(rdata1.priority(), UINT16_C(0));
174 EXPECT_EQ(rdata1.weight(), UINT16_C(0));
175 EXPECT_EQ(rdata1.port(), UINT16_C(0));
176 EXPECT_EQ(rdata1.target(), DomainName());
177
178 SrvRecordRdata rdata2(1, 2, 3, DomainName{"testing", "local"});
179 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(23));
180 EXPECT_EQ(rdata2.priority(), UINT16_C(1));
181 EXPECT_EQ(rdata2.weight(), UINT16_C(2));
182 EXPECT_EQ(rdata2.port(), UINT16_C(3));
183 EXPECT_EQ(rdata2.target(), (DomainName{"testing", "local"}));
184 }
185
TEST(MdnsSrvRecordRdataTest,Compare)186 TEST(MdnsSrvRecordRdataTest, Compare) {
187 SrvRecordRdata rdata1(1, 2, 3, DomainName{"testing", "local"});
188 SrvRecordRdata rdata2(1, 2, 3, DomainName{"testing", "local"});
189 SrvRecordRdata rdata3(4, 2, 3, DomainName{"testing", "local"});
190 SrvRecordRdata rdata4(1, 5, 3, DomainName{"testing", "local"});
191 SrvRecordRdata rdata5(1, 2, 6, DomainName{"testing", "local"});
192 SrvRecordRdata rdata6(1, 2, 3, DomainName{"device", "local"});
193
194 EXPECT_EQ(rdata1, rdata2);
195 EXPECT_NE(rdata1, rdata3);
196 EXPECT_NE(rdata1, rdata4);
197 EXPECT_NE(rdata1, rdata5);
198 EXPECT_NE(rdata1, rdata6);
199
200 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly(
201 {rdata1, rdata2, rdata3, rdata4, rdata5, rdata6}));
202 }
203
TEST(MdnsSrvRecordRdataTest,CopyAndMove)204 TEST(MdnsSrvRecordRdataTest, CopyAndMove) {
205 TestCopyAndMove(SrvRecordRdata(1, 2, 3, DomainName{"testing", "local"}));
206 }
207
TEST(MdnsARecordRdataTest,Construct)208 TEST(MdnsARecordRdataTest, Construct) {
209 ARecordRdata rdata1;
210 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(6));
211 EXPECT_EQ(rdata1.ipv4_address(), (IPAddress{0, 0, 0, 0}));
212
213 ARecordRdata rdata2(IPAddress{8, 8, 8, 8});
214 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(6));
215 EXPECT_EQ(rdata2.ipv4_address(), (IPAddress{8, 8, 8, 8}));
216 }
217
TEST(MdnsARecordRdataTest,Compare)218 TEST(MdnsARecordRdataTest, Compare) {
219 ARecordRdata rdata1(IPAddress{8, 8, 8, 8});
220 ARecordRdata rdata2(IPAddress{8, 8, 8, 8});
221 ARecordRdata rdata3(IPAddress{1, 2, 3, 4});
222
223 EXPECT_EQ(rdata1, rdata2);
224 EXPECT_NE(rdata1, rdata3);
225
226 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3}));
227 }
228
TEST(MdnsARecordRdataTest,CopyAndMove)229 TEST(MdnsARecordRdataTest, CopyAndMove) {
230 TestCopyAndMove(ARecordRdata(IPAddress{8, 8, 8, 8}));
231 }
232
TEST(MdnsAAAARecordRdataTest,Construct)233 TEST(MdnsAAAARecordRdataTest, Construct) {
234 constexpr uint16_t kIPv6AddressHextets1[] = {
235 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
236 };
237 constexpr uint16_t kIPv6AddressHextets2[] = {
238 0xfe80, 0x0000, 0x0000, 0x0000, 0x0202, 0xb3ff, 0xfe1e, 0x8329,
239 };
240
241 IPAddress address1(kIPv6AddressHextets1);
242 AAAARecordRdata rdata1;
243 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(18));
244 EXPECT_EQ(rdata1.ipv6_address(), address1);
245
246 IPAddress address2(kIPv6AddressHextets2);
247 AAAARecordRdata rdata2(address2);
248 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(18));
249 EXPECT_EQ(rdata2.ipv6_address(), address2);
250 }
251
TEST(MdnsAAAARecordRdataTest,Compare)252 TEST(MdnsAAAARecordRdataTest, Compare) {
253 constexpr uint16_t kIPv6AddressHextets1[] = {
254 0x0001, 0x0203, 0x0405, 0x0607, 0x0809, 0x0A0B, 0x0C0D, 0x0E0F,
255 };
256 constexpr uint16_t kIPv6AddressHextets2[] = {
257 0xfe80, 0x0000, 0x0000, 0x0000, 0x0202, 0xb3ff, 0xfe1e, 0x8329,
258 };
259
260 IPAddress address1(kIPv6AddressHextets1);
261 IPAddress address2(kIPv6AddressHextets2);
262 AAAARecordRdata rdata1(address1);
263 AAAARecordRdata rdata2(address1);
264 AAAARecordRdata rdata3(address2);
265
266 EXPECT_EQ(rdata1, rdata2);
267 EXPECT_NE(rdata1, rdata3);
268
269 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3}));
270 }
271
TEST(MdnsAAAARecordRdataTest,CopyAndMove)272 TEST(MdnsAAAARecordRdataTest, CopyAndMove) {
273 constexpr uint16_t kIPv6AddressHextets[] = {
274 0xfe80, 0x0000, 0x0000, 0x0000, 0x0202, 0xb3ff, 0xfe1e, 0x8329,
275 };
276 TestCopyAndMove(AAAARecordRdata(IPAddress(kIPv6AddressHextets)));
277 }
278
TEST(MdnsPtrRecordRdataTest,Construct)279 TEST(MdnsPtrRecordRdataTest, Construct) {
280 PtrRecordRdata rdata1;
281 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(3));
282 EXPECT_EQ(rdata1.ptr_domain(), DomainName());
283
284 PtrRecordRdata rdata2(DomainName{"testing", "local"});
285 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(17));
286 EXPECT_EQ(rdata2.ptr_domain(), (DomainName{"testing", "local"}));
287 }
288
TEST(MdnsPtrRecordRdataTest,Compare)289 TEST(MdnsPtrRecordRdataTest, Compare) {
290 PtrRecordRdata rdata1(DomainName{"testing", "local"});
291 PtrRecordRdata rdata2(DomainName{"testing", "local"});
292 PtrRecordRdata rdata3(DomainName{"device", "local"});
293
294 EXPECT_EQ(rdata1, rdata2);
295 EXPECT_NE(rdata1, rdata3);
296
297 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3}));
298 }
299
TEST(MdnsPtrRecordRdataTest,CopyAndMove)300 TEST(MdnsPtrRecordRdataTest, CopyAndMove) {
301 TestCopyAndMove(PtrRecordRdata(DomainName{"testing", "local"}));
302 }
303
TEST(MdnsTxtRecordRdataTest,Construct)304 TEST(MdnsTxtRecordRdataTest, Construct) {
305 TxtRecordRdata rdata1;
306 EXPECT_EQ(rdata1.MaxWireSize(), UINT64_C(3));
307 EXPECT_EQ(rdata1.texts(), std::vector<std::string>());
308
309 TxtRecordRdata rdata2 = MakeTxtRecord({"foo=1", "bar=2"});
310 EXPECT_EQ(rdata2.MaxWireSize(), UINT64_C(14));
311 EXPECT_EQ(rdata2.texts(), (std::vector<std::string>{"foo=1", "bar=2"}));
312 }
313
TEST(MdnsTxtRecordRdataTest,Compare)314 TEST(MdnsTxtRecordRdataTest, Compare) {
315 TxtRecordRdata rdata1 = MakeTxtRecord({"foo=1", "bar=2"});
316 TxtRecordRdata rdata2 = MakeTxtRecord({"foo=1", "bar=2"});
317 TxtRecordRdata rdata3 = MakeTxtRecord({"foo=1"});
318 TxtRecordRdata rdata4 = MakeTxtRecord({"E=mc^2", "F=ma"});
319
320 EXPECT_EQ(rdata1, rdata2);
321 EXPECT_NE(rdata1, rdata3);
322 EXPECT_NE(rdata1, rdata4);
323
324 EXPECT_TRUE(
325 VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3, rdata4}));
326 }
327
TEST(MdnsTxtRecordRdataTest,CopyAndMove)328 TEST(MdnsTxtRecordRdataTest, CopyAndMove) {
329 TestCopyAndMove(MakeTxtRecord({"foo=1", "bar=2"}));
330 }
331
TEST(MdnsNsecRecordRdataTest,Construct)332 TEST(MdnsNsecRecordRdataTest, Construct) {
333 const DomainName domain{"testing", "local"};
334 NsecRecordRdata rdata(domain);
335 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize());
336 EXPECT_EQ(rdata.next_domain_name(), domain);
337
338 rdata = NsecRecordRdata(domain, DnsType::kA);
339 // It takes 3 bytes to encode the kA and kSRV records because:
340 // - Both record types have value less than 256, so they are both in window
341 // block 1.
342 // - The bitmap length for this block is always a single byte
343 // - DnsType kA = 1 (encoded in byte 1)
344 // So the full encoded version is:
345 // 00000000 00000001 01000000
346 // |window| | size | | 0-7 |
347 // For a total of 3 bytes.
348 EXPECT_EQ(rdata.encoded_types(), (std::vector<uint8_t>{0x00, 0x01, 0x40}));
349 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 3);
350 EXPECT_EQ(rdata.next_domain_name(), domain);
351
352 // It takes 8 bytes to encode the kA and kSRV records because:
353 // - Both record types have value less than 256, so they are both in window
354 // block 1.
355 // - The bitmap length for this block is always a single byte
356 // - DnsTypes kTXT = 16 (encoded in byte 3)
357 // So the full encoded version is:
358 // 00000000 00000011 00000000 00000000 10000000
359 // |window| | size | | 0-7 | | 8-15 | |16-23 |
360 // For a total of 5 bytes.
361 rdata = NsecRecordRdata(domain, DnsType::kTXT);
362 EXPECT_EQ(rdata.encoded_types(),
363 (std::vector<uint8_t>{0x00, 0x03, 0x00, 0x00, 0x80}));
364 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 5);
365 EXPECT_EQ(rdata.next_domain_name(), domain);
366
367 // It takes 8 bytes to encode the kA and kSRV records because:
368 // - Both record types have value less than 256, so they are both in window
369 // block 1.
370 // - The bitmap length for this block is always a single byte
371 // - DnsTypes kSRV = 33 (encoded in byte 5)
372 // So the full encoded version is:
373 // 00000000 00000101 00000000 00000000 00000000 00000000 01000000
374 // |window| | size | | 0-7 | | 8-15 | |16-23 | |24-31 | |32-39 |
375 // For a total of 7 bytes.
376 rdata = NsecRecordRdata(domain, DnsType::kSRV);
377 EXPECT_EQ(rdata.encoded_types(),
378 (std::vector<uint8_t>{0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x40}));
379 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 7);
380 EXPECT_EQ(rdata.next_domain_name(), domain);
381
382 // It takes 8 bytes to encode the kA and kSRV records because:
383 // - Both record types have value less than 256, so they are both in window
384 // block 1.
385 // - The bitmap length for this block is always a single byte
386 // - DnsTypes kNSEC = 47
387 // So the full encoded version is:
388 // 00000000 00000110 00000000 00000000 00000000 00000000 0000000 00000001
389 // |window| | size | | 0-7 | | 8-15 | |16-23 | |24-31 | |32-39 | |40-47 |
390 // For a total of 8 bytes.
391 rdata = NsecRecordRdata(domain, DnsType::kNSEC);
392 EXPECT_EQ(
393 rdata.encoded_types(),
394 (std::vector<uint8_t>{0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}));
395 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 8);
396 EXPECT_EQ(rdata.next_domain_name(), domain);
397
398 // It takes 8 bytes to encode the kA and kSRV records because:
399 // - Both record types have value less than 256, so they are both in window
400 // block 1.
401 // - The bitmap length for this block is always a single byte
402 // - DnsTypes kNSEC = 255
403 // So 32 bits are required for the bitfield, for a total of 34 bits.
404 rdata = NsecRecordRdata(domain, DnsType::kANY);
405 std::vector<uint8_t> results{0x00, 32};
406 for (int i = 1; i < 32; i++) {
407 results.push_back(0x00);
408 }
409 results.push_back(0x01);
410 EXPECT_EQ(rdata.encoded_types(), results);
411 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 34);
412 EXPECT_EQ(rdata.next_domain_name(), domain);
413
414 // It takes 8 bytes to encode the kA and kSRV records because:
415 // - Both record types have value less than 256, so they are both in window
416 // block 1.
417 // - The bitmap length for this block is always a single byte
418 // - DnsTypes have the following values:
419 // - kA = 1 (encoded in byte 1)
420 // kTXT = 16 (encoded in byte 3)
421 // - kSRV = 33 (encoded in byte 5)
422 // - kNSEC = 47 (encoded in 6 bytes)
423 // - The largest of these is 47, so 6 bytes are needed to encode this data.
424 // So the full encoded version is:
425 // 00000000 00000110 01000000 00000000 10000000 00000000 0100000 00000001
426 // |window| | size | | 0-7 | | 8-15 | |16-23 | |24-31 | |32-39 | |40-47 |
427 // For a total of 8 bytes.
428 rdata = NsecRecordRdata(domain, DnsType::kA, DnsType::kTXT, DnsType::kSRV,
429 DnsType::kNSEC);
430 EXPECT_EQ(
431 rdata.encoded_types(),
432 (std::vector<uint8_t>{0x00, 0x06, 0x40, 0x00, 0x80, 0x00, 0x40, 0x01}));
433 EXPECT_EQ(rdata.MaxWireSize(), domain.MaxWireSize() + 8);
434 EXPECT_EQ(rdata.next_domain_name(), domain);
435 }
436
TEST(MdnsNsecRecordRdataTest,Compare)437 TEST(MdnsNsecRecordRdataTest, Compare) {
438 const DomainName domain{"testing", "local"};
439 const NsecRecordRdata rdata1(domain, DnsType::kA, DnsType::kSRV);
440 const NsecRecordRdata rdata2(domain, DnsType::kSRV, DnsType::kA);
441 const NsecRecordRdata rdata3(domain, DnsType::kSRV, DnsType::kA,
442 DnsType::kAAAA);
443 const NsecRecordRdata rdata4(domain, DnsType::kSRV, DnsType::kAAAA);
444
445 // Ensure equal Rdata values are evaluated as equal.
446 EXPECT_EQ(rdata1, rdata1);
447 EXPECT_EQ(rdata1, rdata2);
448 EXPECT_EQ(rdata2, rdata1);
449
450 // Ensure different Rdata values are not.
451 EXPECT_NE(rdata1, rdata3);
452 EXPECT_NE(rdata1, rdata4);
453 EXPECT_NE(rdata3, rdata4);
454
455 EXPECT_TRUE(
456 VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3, rdata4}));
457 }
458
TEST(MdnsNsecRecordRdataTest,CopyAndMove)459 TEST(MdnsNsecRecordRdataTest, CopyAndMove) {
460 TestCopyAndMove(NsecRecordRdata(DomainName{"testing", "local"}, DnsType::kA,
461 DnsType::kSRV));
462 }
463
TEST(MdnsOptRecordRdataTest,Construct)464 TEST(MdnsOptRecordRdataTest, Construct) {
465 OptRecordRdata rdata1;
466 EXPECT_EQ(rdata1.MaxWireSize(), size_t{0});
467 EXPECT_EQ(rdata1.options().size(), size_t{0});
468
469 OptRecordRdata::Option opt1{12, 34, {0x12, 0x34}};
470 OptRecordRdata::Option opt2{12, 34, {0x12, 0x34}};
471 OptRecordRdata::Option opt3{12, 34, {0x12, 0x34, 0x56}};
472 OptRecordRdata::Option opt4{34, 12, {0x00}};
473 OptRecordRdata::Option opt5{12, 12, {0x12, 0x34}};
474 rdata1 = OptRecordRdata(opt1, opt2, opt3, opt4, opt5);
475 EXPECT_EQ(rdata1.MaxWireSize(), size_t{30});
476
477 ASSERT_EQ(rdata1.options().size(), size_t{5});
478 EXPECT_EQ(rdata1.options()[0], opt5);
479 EXPECT_EQ(rdata1.options()[1], opt1);
480 EXPECT_EQ(rdata1.options()[2], opt2);
481 EXPECT_EQ(rdata1.options()[3], opt3);
482 EXPECT_EQ(rdata1.options()[4], opt4);
483 }
484
TEST(MdnsOptRecordRdataTest,Compare)485 TEST(MdnsOptRecordRdataTest, Compare) {
486 OptRecordRdata::Option opt1{12, 34, {0x12, 0x34}};
487 OptRecordRdata::Option opt2{12, 34, {0x12, 0x34}};
488 OptRecordRdata::Option opt3{12, 34, {0x12, 0x56}};
489 OptRecordRdata rdata1(opt1);
490 OptRecordRdata rdata2(opt2);
491 OptRecordRdata rdata3(opt3);
492 OptRecordRdata rdata4;
493
494 EXPECT_EQ(rdata1, rdata1);
495 EXPECT_EQ(rdata2, rdata2);
496 EXPECT_EQ(rdata3, rdata3);
497 EXPECT_EQ(rdata4, rdata4);
498
499 EXPECT_EQ(rdata1, rdata2);
500 EXPECT_NE(rdata1, rdata3);
501 EXPECT_NE(rdata1, rdata4);
502 EXPECT_NE(rdata2, rdata3);
503 EXPECT_NE(rdata2, rdata4);
504 EXPECT_NE(rdata3, rdata4);
505
506 EXPECT_TRUE(
507 VerifyTypeImplementsAbslHashCorrectly({rdata1, rdata2, rdata3, rdata4}));
508 }
509
TEST(MdnsOptRecordRdataTest,CopyAndMove)510 TEST(MdnsOptRecordRdataTest, CopyAndMove) {
511 OptRecordRdata::Option opt1{12, 34, {0x12, 0x34}};
512 TestCopyAndMove(OptRecordRdata(opt1));
513 }
514
TEST(MdnsRecordTest,Construct)515 TEST(MdnsRecordTest, Construct) {
516 MdnsRecord record1;
517 EXPECT_EQ(record1.MaxWireSize(), UINT64_C(11));
518 EXPECT_EQ(record1.name(), DomainName());
519 EXPECT_EQ(record1.dns_type(), static_cast<DnsType>(0));
520 EXPECT_EQ(record1.dns_class(), static_cast<DnsClass>(0));
521 EXPECT_EQ(record1.record_type(), RecordType::kShared);
522 EXPECT_EQ(record1.ttl(),
523 std::chrono::seconds(255)); // 255 is kDefaultRecordTTLSeconds
524 EXPECT_EQ(record1.rdata(), Rdata(RawRecordRdata()));
525
526 MdnsRecord record2(DomainName{"hostname", "local"}, DnsType::kPTR,
527 DnsClass::kIN, RecordType::kUnique, kTtl,
528 PtrRecordRdata(DomainName{"testing", "local"}));
529 EXPECT_EQ(record2.MaxWireSize(), UINT64_C(41));
530 EXPECT_EQ(record2.name(), (DomainName{"hostname", "local"}));
531 EXPECT_EQ(record2.dns_type(), DnsType::kPTR);
532 EXPECT_EQ(record2.dns_class(), DnsClass::kIN);
533 EXPECT_EQ(record2.record_type(), RecordType::kUnique);
534 EXPECT_EQ(record2.ttl(), kTtl);
535 EXPECT_EQ(record2.rdata(),
536 Rdata(PtrRecordRdata(DomainName{"testing", "local"})));
537 }
538
TEST(MdnsRecordTest,Compare)539 TEST(MdnsRecordTest, Compare) {
540 const MdnsRecord record1(DomainName{"hostname", "local"}, DnsType::kPTR,
541 DnsClass::kIN, RecordType::kShared, kTtl,
542 PtrRecordRdata(DomainName{"testing", "local"}));
543 const MdnsRecord record2(DomainName{"hostname", "local"}, DnsType::kPTR,
544 DnsClass::kIN, RecordType::kShared, kTtl,
545 PtrRecordRdata(DomainName{"testing", "local"}));
546 const MdnsRecord record3(DomainName{"othername", "local"}, DnsType::kPTR,
547 DnsClass::kIN, RecordType::kShared, kTtl,
548 PtrRecordRdata(DomainName{"testing", "local"}));
549 const MdnsRecord record4(DomainName{"hostname", "local"}, DnsType::kA,
550 DnsClass::kIN, RecordType::kShared, kTtl,
551 ARecordRdata(IPAddress{8, 8, 8, 8}));
552 const MdnsRecord record5(DomainName{"hostname", "local"}, DnsType::kPTR,
553 DnsClass::kIN, RecordType::kUnique, kTtl,
554 PtrRecordRdata(DomainName{"testing", "local"}));
555 const MdnsRecord record6(DomainName{"hostname", "local"}, DnsType::kPTR,
556 DnsClass::kIN, RecordType::kShared,
557 std::chrono::seconds(200),
558 PtrRecordRdata(DomainName{"testing", "local"}));
559 const MdnsRecord record7(DomainName{"hostname", "local"}, DnsType::kPTR,
560 DnsClass::kIN, RecordType::kShared, kTtl,
561 PtrRecordRdata(DomainName{"device", "local"}));
562 const MdnsRecord record8(
563 DomainName{"testing", "local"}, DnsType::kNSEC, DnsClass::kIN,
564 RecordType::kUnique, std::chrono::seconds(120),
565 NsecRecordRdata(DomainName{"testing", "local"}, DnsType::kA));
566 const MdnsRecord record9(
567 DomainName{"testing", "local"}, DnsType::kNSEC, DnsClass::kIN,
568 RecordType::kUnique, std::chrono::seconds(120),
569 NsecRecordRdata(DomainName{"testing", "local"}, DnsType::kAAAA));
570
571 EXPECT_EQ(record1, record2);
572
573 // Account for intentional differences between > / < and = / !=. This is
574 // unfortunate but required difference for > / < per RFC.
575 EXPECT_NE(record1, record6);
576 ASSERT_FALSE(record1 > record6);
577 ASSERT_FALSE(record6 > record1);
578
579 std::vector<const MdnsRecord*> records_sorted{
580 &record4, &record7, &record1, &record5, &record3, &record8, &record9};
581 for (size_t i = 0; i < records_sorted.size(); i++) {
582 for (size_t j = i + 1; j < records_sorted.size(); j++) {
583 EXPECT_NE(*records_sorted[i], *records_sorted[j])
584 << "failure for i=" << i << " , j=" << j;
585 EXPECT_GT(*records_sorted[j], *records_sorted[i])
586 << "failure for i=" << i << " , j=" << j;
587 EXPECT_LT(*records_sorted[i], *records_sorted[j])
588 << "failure for i=" << i << " , j=" << j;
589 }
590 }
591
592 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly(
593 {record1, record2, record3, record4, record5, record6, record7, record8,
594 record9}));
595 }
596
TEST(MdnsRecordTest,CopyAndMove)597 TEST(MdnsRecordTest, CopyAndMove) {
598 MdnsRecord record(DomainName{"hostname", "local"}, DnsType::kPTR,
599 DnsClass::kIN, RecordType::kUnique, kTtl,
600 PtrRecordRdata(DomainName{"testing", "local"}));
601 TestCopyAndMove(record);
602 }
603
TEST(MdnsQuestionTest,Construct)604 TEST(MdnsQuestionTest, Construct) {
605 MdnsQuestion question1;
606 EXPECT_EQ(question1.MaxWireSize(), UINT64_C(5));
607 EXPECT_EQ(question1.name(), DomainName());
608 EXPECT_EQ(question1.dns_type(), static_cast<DnsType>(0));
609 EXPECT_EQ(question1.dns_class(), static_cast<DnsClass>(0));
610 EXPECT_EQ(question1.response_type(), ResponseType::kMulticast);
611
612 MdnsQuestion question2(DomainName{"testing", "local"}, DnsType::kPTR,
613 DnsClass::kIN, ResponseType::kUnicast);
614 EXPECT_EQ(question2.MaxWireSize(), UINT64_C(19));
615 EXPECT_EQ(question2.name(), (DomainName{"testing", "local"}));
616 EXPECT_EQ(question2.dns_type(), DnsType::kPTR);
617 EXPECT_EQ(question2.dns_class(), DnsClass::kIN);
618 EXPECT_EQ(question2.response_type(), ResponseType::kUnicast);
619 }
620
TEST(MdnsQuestionTest,Compare)621 TEST(MdnsQuestionTest, Compare) {
622 MdnsQuestion question1(DomainName{"testing", "local"}, DnsType::kPTR,
623 DnsClass::kIN, ResponseType::kMulticast);
624 MdnsQuestion question2(DomainName{"testing", "local"}, DnsType::kPTR,
625 DnsClass::kIN, ResponseType::kMulticast);
626 MdnsQuestion question3(DomainName{"hostname", "local"}, DnsType::kPTR,
627 DnsClass::kIN, ResponseType::kMulticast);
628 MdnsQuestion question4(DomainName{"testing", "local"}, DnsType::kA,
629 DnsClass::kIN, ResponseType::kMulticast);
630 MdnsQuestion question5(DomainName{"hostname", "local"}, DnsType::kPTR,
631 DnsClass::kIN, ResponseType::kUnicast);
632
633 EXPECT_EQ(question1, question2);
634 EXPECT_NE(question1, question3);
635 EXPECT_NE(question1, question4);
636 EXPECT_NE(question1, question5);
637
638 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly(
639 {question1, question2, question3, question4, question5}));
640 }
641
TEST(MdnsQuestionTest,CopyAndMove)642 TEST(MdnsQuestionTest, CopyAndMove) {
643 MdnsQuestion question(DomainName{"testing", "local"}, DnsType::kPTR,
644 DnsClass::kIN, ResponseType::kUnicast);
645 TestCopyAndMove(question);
646 }
647
TEST(MdnsMessageTest,Construct)648 TEST(MdnsMessageTest, Construct) {
649 MdnsMessage message1;
650 EXPECT_EQ(message1.MaxWireSize(), UINT64_C(12));
651 EXPECT_EQ(message1.id(), UINT16_C(0));
652 EXPECT_EQ(message1.type(), MessageType::Query);
653 EXPECT_EQ(message1.questions().size(), UINT64_C(0));
654 EXPECT_EQ(message1.answers().size(), UINT64_C(0));
655 EXPECT_EQ(message1.authority_records().size(), UINT64_C(0));
656 EXPECT_EQ(message1.additional_records().size(), UINT64_C(0));
657
658 MdnsQuestion question(DomainName{"testing", "local"}, DnsType::kPTR,
659 DnsClass::kIN, ResponseType::kUnicast);
660 MdnsRecord record1(DomainName{"record1"}, DnsType::kA, DnsClass::kIN,
661 RecordType::kShared, kTtl,
662 ARecordRdata(IPAddress{172, 0, 0, 1}));
663 MdnsRecord record2(DomainName{"record2"}, DnsType::kTXT, DnsClass::kIN,
664 RecordType::kShared, kTtl,
665 MakeTxtRecord({"foo=1", "bar=2"}));
666 MdnsRecord record3(DomainName{"record3"}, DnsType::kPTR, DnsClass::kIN,
667 RecordType::kShared, kTtl,
668 PtrRecordRdata(DomainName{"device", "local"}));
669
670 MdnsMessage message2(123, MessageType::Response);
671 EXPECT_EQ(message2.MaxWireSize(), UINT64_C(12));
672 EXPECT_EQ(message2.id(), UINT16_C(123));
673 EXPECT_EQ(message2.type(), MessageType::Response);
674 EXPECT_EQ(message2.questions().size(), UINT64_C(0));
675 EXPECT_EQ(message2.answers().size(), UINT64_C(0));
676 EXPECT_EQ(message2.authority_records().size(), UINT64_C(0));
677 EXPECT_EQ(message2.additional_records().size(), UINT64_C(0));
678
679 message2.AddQuestion(question);
680 message2.AddAnswer(record1);
681 message2.AddAuthorityRecord(record2);
682 message2.AddAdditionalRecord(record3);
683
684 EXPECT_EQ(message2.MaxWireSize(), UINT64_C(118));
685 ASSERT_EQ(message2.questions().size(), UINT64_C(1));
686 ASSERT_EQ(message2.answers().size(), UINT64_C(1));
687 ASSERT_EQ(message2.authority_records().size(), UINT64_C(1));
688 ASSERT_EQ(message2.additional_records().size(), UINT64_C(1));
689
690 EXPECT_EQ(message2.questions()[0], question);
691 EXPECT_EQ(message2.answers()[0], record1);
692 EXPECT_EQ(message2.authority_records()[0], record2);
693 EXPECT_EQ(message2.additional_records()[0], record3);
694
695 MdnsMessage message3(
696 123, MessageType::Response, std::vector<MdnsQuestion>{question},
697 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
698 std::vector<MdnsRecord>{record3});
699
700 EXPECT_EQ(message3.MaxWireSize(), UINT64_C(118));
701 ASSERT_EQ(message3.questions().size(), UINT64_C(1));
702 ASSERT_EQ(message3.answers().size(), UINT64_C(1));
703 ASSERT_EQ(message3.authority_records().size(), UINT64_C(1));
704 ASSERT_EQ(message3.additional_records().size(), UINT64_C(1));
705
706 EXPECT_EQ(message3.questions()[0], question);
707 EXPECT_EQ(message3.answers()[0], record1);
708 EXPECT_EQ(message3.authority_records()[0], record2);
709 EXPECT_EQ(message3.additional_records()[0], record3);
710 }
711
TEST(MdnsMessageTest,Compare)712 TEST(MdnsMessageTest, Compare) {
713 MdnsQuestion question(DomainName{"testing", "local"}, DnsType::kPTR,
714 DnsClass::kIN, ResponseType::kUnicast);
715 MdnsRecord record1(DomainName{"record1"}, DnsType::kA, DnsClass::kIN,
716 RecordType::kShared, kTtl,
717 ARecordRdata(IPAddress{172, 0, 0, 1}));
718 MdnsRecord record2(DomainName{"record2"}, DnsType::kTXT, DnsClass::kIN,
719 RecordType::kShared, kTtl,
720 MakeTxtRecord({"foo=1", "bar=2"}));
721 MdnsRecord record3(DomainName{"record3"}, DnsType::kPTR, DnsClass::kIN,
722 RecordType::kShared, kTtl,
723 PtrRecordRdata(DomainName{"device", "local"}));
724
725 MdnsMessage message1(
726 123, MessageType::Response, std::vector<MdnsQuestion>{question},
727 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
728 std::vector<MdnsRecord>{record3});
729 MdnsMessage message2(
730 123, MessageType::Response, std::vector<MdnsQuestion>{question},
731 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
732 std::vector<MdnsRecord>{record3});
733 MdnsMessage message3(
734 456, MessageType::Response, std::vector<MdnsQuestion>{question},
735 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
736 std::vector<MdnsRecord>{record3});
737 MdnsMessage message4(
738 123, MessageType::Query, std::vector<MdnsQuestion>{question},
739 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
740 std::vector<MdnsRecord>{record3});
741 MdnsMessage message5(123, MessageType::Response, std::vector<MdnsQuestion>{},
742 std::vector<MdnsRecord>{record1},
743 std::vector<MdnsRecord>{record2},
744 std::vector<MdnsRecord>{record3});
745 MdnsMessage message6(
746 123, MessageType::Response, std::vector<MdnsQuestion>{question},
747 std::vector<MdnsRecord>{}, std::vector<MdnsRecord>{record2},
748 std::vector<MdnsRecord>{record3});
749 MdnsMessage message7(
750 123, MessageType::Response, std::vector<MdnsQuestion>{question},
751 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{},
752 std::vector<MdnsRecord>{record3});
753 MdnsMessage message8(
754 123, MessageType::Response, std::vector<MdnsQuestion>{question},
755 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
756 std::vector<MdnsRecord>{});
757
758 EXPECT_EQ(message1, message2);
759 EXPECT_NE(message1, message3);
760 EXPECT_NE(message1, message4);
761 EXPECT_NE(message1, message5);
762 EXPECT_NE(message1, message6);
763 EXPECT_NE(message1, message7);
764 EXPECT_NE(message1, message8);
765
766 EXPECT_TRUE(VerifyTypeImplementsAbslHashCorrectly(
767 {message1, message2, message3, message4, message5, message6, message7,
768 message8}));
769 }
770
TEST(MdnsMessageTest,CopyAndMove)771 TEST(MdnsMessageTest, CopyAndMove) {
772 MdnsQuestion question(DomainName{"testing", "local"}, DnsType::kPTR,
773 DnsClass::kIN, ResponseType::kUnicast);
774 MdnsRecord record1(DomainName{"record1"}, DnsType::kA, DnsClass::kIN,
775 RecordType::kShared, kTtl,
776 ARecordRdata(IPAddress{172, 0, 0, 1}));
777 MdnsRecord record2(DomainName{"record2"}, DnsType::kTXT, DnsClass::kIN,
778 RecordType::kShared, kTtl,
779 MakeTxtRecord({"foo=1", "bar=2"}));
780 MdnsRecord record3(DomainName{"record3"}, DnsType::kPTR, DnsClass::kIN,
781 RecordType::kShared, kTtl,
782 PtrRecordRdata(DomainName{"device", "local"}));
783 MdnsMessage message(
784 123, MessageType::Response, std::vector<MdnsQuestion>{question},
785 std::vector<MdnsRecord>{record1}, std::vector<MdnsRecord>{record2},
786 std::vector<MdnsRecord>{record3});
787 TestCopyAndMove(message);
788 }
789
TEST(MdnsRecordOperations,CanBeProcessed)790 TEST(MdnsRecordOperations, CanBeProcessed) {
791 EXPECT_FALSE(CanBeProcessed(static_cast<DnsType>(1234)));
792 EXPECT_FALSE(CanBeProcessed(static_cast<DnsType>(222)));
793 EXPECT_FALSE(CanBeProcessed(static_cast<DnsType>(8973)));
794 }
795
796 } // namespace discovery
797 } // namespace openscreen
798