1 // Copyright 2020 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/dnssd/impl/dns_data_graph.h"
6
7 #include <utility>
8
9 #include "discovery/mdns/testing/mdns_test_util.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 #include "platform/base/ip_address.h"
13
14 namespace openscreen {
15 namespace discovery {
16 namespace {
17
GetAddressV4(const DnsSdInstanceEndpoint endpoint)18 IPAddress GetAddressV4(const DnsSdInstanceEndpoint endpoint) {
19 for (const IPAddress& address : endpoint.addresses()) {
20 if (address.IsV4()) {
21 return address;
22 }
23 }
24 return IPAddress{};
25 }
26
GetAddressV6(const DnsSdInstanceEndpoint endpoint)27 IPAddress GetAddressV6(const DnsSdInstanceEndpoint endpoint) {
28 for (const IPAddress& address : endpoint.addresses()) {
29 if (address.IsV6()) {
30 return address;
31 }
32 }
33 return IPAddress{};
34 }
35
36 } // namespace
37
38 using testing::_;
39 using testing::Invoke;
40 using testing::Return;
41 using testing::StrictMock;
42
43 class DomainChangeImpl {
44 public:
45 MOCK_METHOD1(OnStartTracking, void(const DomainName&));
46 MOCK_METHOD1(OnStopTracking, void(const DomainName&));
47 };
48
49 class DnsDataGraphTests : public testing::Test {
50 public:
DnsDataGraphTests()51 DnsDataGraphTests() : graph_(DnsDataGraph::Create(network_interface_)) {
52 EXPECT_CALL(callbacks_, OnStartTracking(ptr_domain_));
53 StartTracking(ptr_domain_);
54 testing::Mock::VerifyAndClearExpectations(&callbacks_);
55 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{1});
56 }
57
58 protected:
TriggerRecordCreation(MdnsRecord record,Error::Code result_code=Error::Code::kNone)59 void TriggerRecordCreation(MdnsRecord record,
60 Error::Code result_code = Error::Code::kNone) {
61 size_t size = graph_->GetTrackedDomainCount();
62 Error result =
63 ApplyDataRecordChange(std::move(record), RecordChangedEvent::kCreated);
64 EXPECT_EQ(result.code(), result_code)
65 << "Failed with error code " << result.code();
66 size_t new_size = graph_->GetTrackedDomainCount();
67 EXPECT_EQ(size, new_size);
68 }
69
TriggerRecordCreationWithCallback(MdnsRecord record,const DomainName & target_domain)70 void TriggerRecordCreationWithCallback(MdnsRecord record,
71 const DomainName& target_domain) {
72 EXPECT_CALL(callbacks_, OnStartTracking(target_domain));
73 size_t size = graph_->GetTrackedDomainCount();
74 Error result =
75 ApplyDataRecordChange(std::move(record), RecordChangedEvent::kCreated);
76 EXPECT_TRUE(result.ok()) << "Failed with error code " << result.code();
77 size_t new_size = graph_->GetTrackedDomainCount();
78 EXPECT_EQ(size + 1, new_size);
79 }
80
ExpectDomainEqual(const DnsSdInstance & instance,const DomainName & name)81 void ExpectDomainEqual(const DnsSdInstance& instance,
82 const DomainName& name) {
83 EXPECT_EQ(name.labels().size(), size_t{4});
84 EXPECT_EQ(instance.instance_id(), name.labels()[0]);
85 EXPECT_EQ(instance.service_id(), name.labels()[1] + "." + name.labels()[2]);
86 EXPECT_EQ(instance.domain_id(), name.labels()[3]);
87 }
88
ApplyDataRecordChange(MdnsRecord record,RecordChangedEvent event)89 Error ApplyDataRecordChange(MdnsRecord record, RecordChangedEvent event) {
90 return graph_->ApplyDataRecordChange(
91 std::move(record), event,
92 [this](const DomainName& domain) {
93 callbacks_.OnStartTracking(domain);
94 },
95 [this](const DomainName& domain) {
96 callbacks_.OnStopTracking(domain);
97 });
98 }
99
StartTracking(const DomainName & domain)100 void StartTracking(const DomainName& domain) {
101 graph_->StartTracking(domain, [this](const DomainName& domain) {
102 callbacks_.OnStartTracking(domain);
103 });
104 }
105
StopTracking(const DomainName & domain)106 void StopTracking(const DomainName& domain) {
107 graph_->StopTracking(domain, [this](const DomainName& domain) {
108 callbacks_.OnStopTracking(domain);
109 });
110 }
111
112 StrictMock<DomainChangeImpl> callbacks_;
113 NetworkInterfaceIndex network_interface_ = 1234;
114 std::unique_ptr<DnsDataGraph> graph_;
115 DomainName ptr_domain_{"_cast", "_tcp", "local"};
116 DomainName primary_domain_{"test", "_cast", "_tcp", "local"};
117 DomainName secondary_domain_{"test2", "_cast", "_tcp", "local"};
118 DomainName tertiary_domain_{"test3", "_cast", "_tcp", "local"};
119 };
120
TEST_F(DnsDataGraphTests,CallbacksCalledForStartStopTracking)121 TEST_F(DnsDataGraphTests, CallbacksCalledForStartStopTracking) {
122 EXPECT_CALL(callbacks_, OnStopTracking(ptr_domain_));
123 StopTracking(ptr_domain_);
124
125 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{0});
126 }
127
TEST_F(DnsDataGraphTests,ApplyChangeForUntrackedDomainError)128 TEST_F(DnsDataGraphTests, ApplyChangeForUntrackedDomainError) {
129 Error result = ApplyDataRecordChange(GetFakeSrvRecord(primary_domain_),
130 RecordChangedEvent::kCreated);
131 EXPECT_EQ(result.code(), Error::Code::kOperationCancelled);
132 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{1});
133 }
134
TEST_F(DnsDataGraphTests,ChildrenStopTrackingWhenRootQueryStopped)135 TEST_F(DnsDataGraphTests, ChildrenStopTrackingWhenRootQueryStopped) {
136 auto ptr = GetFakePtrRecord(primary_domain_);
137 auto srv = GetFakeSrvRecord(primary_domain_, secondary_domain_);
138 auto a = GetFakeARecord(secondary_domain_);
139
140 TriggerRecordCreationWithCallback(ptr, primary_domain_);
141 TriggerRecordCreationWithCallback(srv, secondary_domain_);
142 TriggerRecordCreation(a);
143
144 EXPECT_CALL(callbacks_, OnStopTracking(ptr_domain_));
145 EXPECT_CALL(callbacks_, OnStopTracking(primary_domain_));
146 EXPECT_CALL(callbacks_, OnStopTracking(secondary_domain_));
147 StopTracking(ptr_domain_);
148 testing::Mock::VerifyAndClearExpectations(&callbacks_);
149
150 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{0});
151 }
152
TEST_F(DnsDataGraphTests,CyclicSrvStopsTrackingWhenRootQueryStopped)153 TEST_F(DnsDataGraphTests, CyclicSrvStopsTrackingWhenRootQueryStopped) {
154 auto ptr = GetFakePtrRecord(primary_domain_);
155 auto srv = GetFakeSrvRecord(primary_domain_);
156 auto a = GetFakeARecord(primary_domain_);
157
158 TriggerRecordCreationWithCallback(ptr, primary_domain_);
159 TriggerRecordCreation(srv);
160 TriggerRecordCreation(a);
161
162 EXPECT_CALL(callbacks_, OnStopTracking(ptr_domain_));
163 EXPECT_CALL(callbacks_, OnStopTracking(primary_domain_));
164 StopTracking(ptr_domain_);
165 testing::Mock::VerifyAndClearExpectations(&callbacks_);
166
167 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{0});
168 }
169
TEST_F(DnsDataGraphTests,ChildrenStopTrackingWhenParentDeleted)170 TEST_F(DnsDataGraphTests, ChildrenStopTrackingWhenParentDeleted) {
171 auto ptr = GetFakePtrRecord(primary_domain_);
172 auto srv = GetFakeSrvRecord(primary_domain_, secondary_domain_);
173 auto a = GetFakeARecord(secondary_domain_);
174
175 TriggerRecordCreationWithCallback(ptr, primary_domain_);
176 TriggerRecordCreationWithCallback(srv, secondary_domain_);
177 TriggerRecordCreation(a);
178
179 EXPECT_CALL(callbacks_, OnStopTracking(primary_domain_));
180 EXPECT_CALL(callbacks_, OnStopTracking(secondary_domain_));
181 auto result = ApplyDataRecordChange(ptr, RecordChangedEvent::kExpired);
182 EXPECT_TRUE(result.ok()) << "Failed with error code " << result.code();
183 testing::Mock::VerifyAndClearExpectations(&callbacks_);
184
185 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{1});
186 }
187
TEST_F(DnsDataGraphTests,OnlyAffectedNodesChangedWhenParentDeleted)188 TEST_F(DnsDataGraphTests, OnlyAffectedNodesChangedWhenParentDeleted) {
189 auto ptr = GetFakePtrRecord(primary_domain_);
190 auto srv = GetFakeSrvRecord(primary_domain_, secondary_domain_);
191 auto a = GetFakeARecord(secondary_domain_);
192
193 TriggerRecordCreationWithCallback(ptr, primary_domain_);
194 TriggerRecordCreationWithCallback(srv, secondary_domain_);
195 TriggerRecordCreation(a);
196
197 EXPECT_CALL(callbacks_, OnStopTracking(secondary_domain_));
198 auto result = ApplyDataRecordChange(srv, RecordChangedEvent::kExpired);
199 EXPECT_TRUE(result.ok()) << "Failed with error code " << result.code();
200 testing::Mock::VerifyAndClearExpectations(&callbacks_);
201
202 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{2});
203 }
204
TEST_F(DnsDataGraphTests,CreateFailsForExistingRecord)205 TEST_F(DnsDataGraphTests, CreateFailsForExistingRecord) {
206 auto ptr = GetFakePtrRecord(primary_domain_);
207 auto srv = GetFakeSrvRecord(primary_domain_);
208
209 TriggerRecordCreationWithCallback(ptr, primary_domain_);
210 TriggerRecordCreation(srv);
211
212 auto result = ApplyDataRecordChange(srv, RecordChangedEvent::kCreated);
213 EXPECT_FALSE(result.ok());
214 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{2});
215 }
216
TEST_F(DnsDataGraphTests,UpdateFailsForNonExistingRecord)217 TEST_F(DnsDataGraphTests, UpdateFailsForNonExistingRecord) {
218 auto ptr = GetFakePtrRecord(primary_domain_);
219 auto srv = GetFakeSrvRecord(primary_domain_);
220
221 TriggerRecordCreationWithCallback(ptr, primary_domain_);
222
223 auto result = ApplyDataRecordChange(srv, RecordChangedEvent::kUpdated);
224 EXPECT_FALSE(result.ok());
225 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{2});
226 }
227
TEST_F(DnsDataGraphTests,DeleteFailsForNonExistingRecord)228 TEST_F(DnsDataGraphTests, DeleteFailsForNonExistingRecord) {
229 auto ptr = GetFakePtrRecord(primary_domain_);
230 auto srv = GetFakeSrvRecord(primary_domain_);
231
232 TriggerRecordCreationWithCallback(ptr, primary_domain_);
233
234 auto result = ApplyDataRecordChange(srv, RecordChangedEvent::kExpired);
235 EXPECT_FALSE(result.ok());
236 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{2});
237 }
238
TEST_F(DnsDataGraphTests,DeleteSucceedsForRecordWithDifferentTtl)239 TEST_F(DnsDataGraphTests, DeleteSucceedsForRecordWithDifferentTtl) {
240 const MdnsRecord ptr = GetFakePtrRecord(primary_domain_);
241 TriggerRecordCreationWithCallback(ptr, primary_domain_);
242
243 EXPECT_CALL(callbacks_, OnStopTracking(primary_domain_));
244 const MdnsRecord new_ptr(ptr.name(), ptr.dns_type(), ptr.dns_class(),
245 ptr.record_type(),
246 ptr.ttl() + std::chrono::seconds(10), ptr.rdata());
247 const auto result =
248 ApplyDataRecordChange(new_ptr, RecordChangedEvent::kExpired);
249
250 EXPECT_TRUE(result.ok());
251 EXPECT_EQ(graph_->GetTrackedDomainCount(), size_t{1});
252 }
253
TEST_F(DnsDataGraphTests,UpdateEndpointsWorksAsExpected)254 TEST_F(DnsDataGraphTests, UpdateEndpointsWorksAsExpected) {
255 auto ptr = GetFakePtrRecord(primary_domain_);
256 auto srv = GetFakeSrvRecord(primary_domain_, secondary_domain_);
257 auto txt = GetFakeTxtRecord(primary_domain_);
258 auto a = GetFakeARecord(secondary_domain_);
259
260 TriggerRecordCreationWithCallback(ptr, primary_domain_);
261 TriggerRecordCreation(txt);
262 TriggerRecordCreationWithCallback(srv, secondary_domain_);
263 TriggerRecordCreation(a);
264
265 std::vector<ErrorOr<DnsSdInstanceEndpoint>> endpoints =
266 graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
267 primary_domain_);
268 ASSERT_EQ(endpoints.size(), size_t{1});
269 ErrorOr<DnsSdInstanceEndpoint> endpoint_or_error = std::move(endpoints[0]);
270 ASSERT_TRUE(endpoint_or_error.is_value());
271 DnsSdInstanceEndpoint endpoint = std::move(endpoint_or_error.value());
272
273 ARecordRdata rdata(IPAddress(192, 168, 1, 2));
274 MdnsRecord new_a(secondary_domain_, DnsType::kA, DnsClass::kIN,
275 RecordType::kUnique, std::chrono::seconds(0),
276 std::move(rdata));
277 auto result = ApplyDataRecordChange(new_a, RecordChangedEvent::kUpdated);
278
279 endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
280 primary_domain_);
281 ASSERT_EQ(endpoints.size(), size_t{1});
282 endpoint_or_error = std::move(endpoints[0]);
283 ASSERT_TRUE(endpoint_or_error.is_value());
284 DnsSdInstanceEndpoint endpoint2 = std::move(endpoint_or_error.value());
285 ASSERT_EQ(endpoint.addresses().size(), size_t{1});
286 ASSERT_EQ(endpoint.addresses().size(), endpoint2.addresses().size());
287 EXPECT_NE(endpoint.addresses()[0], endpoint2.addresses()[0]);
288 EXPECT_EQ(endpoint.instance_id(), endpoint2.instance_id());
289 EXPECT_EQ(endpoint.service_id(), endpoint2.service_id());
290 EXPECT_EQ(endpoint.domain_id(), endpoint2.domain_id());
291 EXPECT_EQ(endpoint.txt(), endpoint2.txt());
292 EXPECT_EQ(endpoint.port(), endpoint2.port());
293 }
294
TEST_F(DnsDataGraphTests,CreateEndpointsGeneratesCorrectRecords)295 TEST_F(DnsDataGraphTests, CreateEndpointsGeneratesCorrectRecords) {
296 auto ptr = GetFakePtrRecord(primary_domain_);
297 auto srv = GetFakeSrvRecord(primary_domain_, secondary_domain_);
298 auto txt = GetFakeTxtRecord(primary_domain_);
299 auto a = GetFakeARecord(secondary_domain_);
300 auto aaaa = GetFakeAAAARecord(secondary_domain_);
301
302 TriggerRecordCreationWithCallback(ptr, primary_domain_);
303 TriggerRecordCreation(txt);
304 TriggerRecordCreationWithCallback(srv, secondary_domain_);
305
306 std::vector<ErrorOr<DnsSdInstanceEndpoint>> endpoints =
307 graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
308 primary_domain_);
309 EXPECT_EQ(endpoints.size(), size_t{0});
310
311 TriggerRecordCreation(a);
312 endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
313 primary_domain_);
314 ASSERT_EQ(endpoints.size(), size_t{1});
315 ErrorOr<DnsSdInstanceEndpoint> endpoint_or_error = std::move(endpoints[0]);
316 ASSERT_TRUE(endpoint_or_error.is_value());
317 DnsSdInstanceEndpoint endpoint_a = std::move(endpoint_or_error.value());
318 EXPECT_TRUE(GetAddressV4(endpoint_a));
319 EXPECT_FALSE(GetAddressV6(endpoint_a));
320 EXPECT_EQ(GetAddressV4(endpoint_a), kFakeARecordAddress);
321 ExpectDomainEqual(endpoint_a, primary_domain_);
322 EXPECT_EQ(endpoint_a.port(), kFakeSrvRecordPort);
323
324 TriggerRecordCreation(aaaa);
325 endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
326 primary_domain_);
327 ASSERT_EQ(endpoints.size(), size_t{1});
328 endpoint_or_error = std::move(endpoints[0]);
329 ASSERT_TRUE(endpoint_or_error.is_value());
330 DnsSdInstanceEndpoint endpoint_a_aaaa = std::move(endpoint_or_error.value());
331 ASSERT_TRUE(GetAddressV4(endpoint_a_aaaa));
332 ASSERT_TRUE(GetAddressV6(endpoint_a_aaaa));
333 EXPECT_EQ(GetAddressV4(endpoint_a_aaaa), kFakeARecordAddress);
334 EXPECT_EQ(GetAddressV6(endpoint_a_aaaa), kFakeAAAARecordAddress);
335 EXPECT_EQ(static_cast<DnsSdInstance>(endpoint_a),
336 static_cast<DnsSdInstance>(endpoint_a_aaaa));
337
338 auto result = ApplyDataRecordChange(a, RecordChangedEvent::kExpired);
339 EXPECT_TRUE(result.ok()) << "Failed with error code " << result.code();
340 endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
341 primary_domain_);
342 ASSERT_EQ(endpoints.size(), size_t{1});
343 endpoint_or_error = std::move(endpoints[0]);
344 ASSERT_TRUE(endpoint_or_error.is_value());
345 DnsSdInstanceEndpoint endpoint_aaaa = std::move(endpoint_or_error.value());
346 EXPECT_FALSE(GetAddressV4(endpoint_aaaa));
347 ASSERT_TRUE(GetAddressV6(endpoint_aaaa));
348 EXPECT_EQ(GetAddressV6(endpoint_aaaa), kFakeAAAARecordAddress);
349 EXPECT_EQ(static_cast<DnsSdInstance>(endpoint_a),
350 static_cast<DnsSdInstance>(endpoint_aaaa));
351
352 result = ApplyDataRecordChange(aaaa, RecordChangedEvent::kExpired);
353 EXPECT_TRUE(result.ok()) << "Failed with error code " << result.code();
354 endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
355 primary_domain_);
356 ASSERT_EQ(endpoints.size(), size_t{0});
357 }
358
TEST_F(DnsDataGraphTests,CreateEndpointsHandlesSelfLoops)359 TEST_F(DnsDataGraphTests, CreateEndpointsHandlesSelfLoops) {
360 auto ptr = GetFakePtrRecord(primary_domain_);
361 auto srv = GetFakeSrvRecord(primary_domain_, primary_domain_);
362 auto txt = GetFakeTxtRecord(primary_domain_);
363 auto a = GetFakeARecord(primary_domain_);
364 auto aaaa = GetFakeAAAARecord(primary_domain_);
365
366 TriggerRecordCreationWithCallback(ptr, primary_domain_);
367 TriggerRecordCreation(srv);
368 TriggerRecordCreation(txt);
369 TriggerRecordCreation(a);
370 TriggerRecordCreation(aaaa);
371
372 auto endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(srv),
373 primary_domain_);
374 ASSERT_EQ(endpoints.size(), size_t{1});
375 ASSERT_TRUE(endpoints[0].is_value());
376 DnsSdInstanceEndpoint endpoint = std::move(endpoints[0].value());
377
378 EXPECT_EQ(GetAddressV4(endpoint), kFakeARecordAddress);
379 EXPECT_EQ(GetAddressV6(endpoint), kFakeAAAARecordAddress);
380 ExpectDomainEqual(endpoint, primary_domain_);
381 EXPECT_EQ(endpoint.port(), kFakeSrvRecordPort);
382
383 auto endpoints2 =
384 graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(ptr), ptr_domain_);
385 ASSERT_EQ(endpoints2.size(), size_t{1});
386 ASSERT_TRUE(endpoints2[0].is_value());
387 DnsSdInstanceEndpoint endpoint2 = std::move(endpoints2[0].value());
388
389 EXPECT_EQ(GetAddressV4(endpoint2), kFakeARecordAddress);
390 EXPECT_EQ(GetAddressV6(endpoint2), kFakeAAAARecordAddress);
391 ExpectDomainEqual(endpoint2, primary_domain_);
392 EXPECT_EQ(endpoint2.port(), kFakeSrvRecordPort);
393
394 EXPECT_EQ(static_cast<DnsSdInstance>(endpoint),
395 static_cast<DnsSdInstance>(endpoint2));
396 EXPECT_EQ(endpoint, endpoint2);
397 }
398
TEST_F(DnsDataGraphTests,CreateEndpointsWithMultipleParents)399 TEST_F(DnsDataGraphTests, CreateEndpointsWithMultipleParents) {
400 auto ptr = GetFakePtrRecord(primary_domain_);
401 auto srv = GetFakeSrvRecord(primary_domain_, tertiary_domain_);
402 auto txt = GetFakeTxtRecord(primary_domain_);
403 auto ptr2 = GetFakePtrRecord(secondary_domain_);
404 auto srv2 = GetFakeSrvRecord(secondary_domain_, tertiary_domain_);
405 auto txt2 = GetFakeTxtRecord(secondary_domain_);
406 auto a = GetFakeARecord(tertiary_domain_);
407 auto aaaa = GetFakeAAAARecord(tertiary_domain_);
408
409 TriggerRecordCreationWithCallback(ptr, primary_domain_);
410 TriggerRecordCreationWithCallback(srv, tertiary_domain_);
411 TriggerRecordCreation(txt);
412 TriggerRecordCreationWithCallback(ptr2, secondary_domain_);
413 TriggerRecordCreation(srv2);
414 TriggerRecordCreation(txt2);
415 TriggerRecordCreation(a);
416 TriggerRecordCreation(aaaa);
417
418 auto endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(a),
419 tertiary_domain_);
420 ASSERT_EQ(endpoints.size(), size_t{2});
421 ASSERT_TRUE(endpoints[0].is_value());
422 ASSERT_TRUE(endpoints[1].is_value());
423
424 DnsSdInstanceEndpoint endpoint_a = std::move(endpoints[0].value());
425 DnsSdInstanceEndpoint endpoint_b = std::move(endpoints[1].value());
426 DnsSdInstanceEndpoint* endpoint_1;
427 DnsSdInstanceEndpoint* endpoint_2;
428 if (endpoint_a.instance_id() == "test") {
429 endpoint_1 = &endpoint_a;
430 endpoint_2 = &endpoint_b;
431 } else {
432 endpoint_2 = &endpoint_a;
433 endpoint_1 = &endpoint_b;
434 }
435
436 EXPECT_EQ(GetAddressV4(*endpoint_1), kFakeARecordAddress);
437 EXPECT_EQ(GetAddressV6(*endpoint_1), kFakeAAAARecordAddress);
438 EXPECT_EQ(endpoint_1->port(), kFakeSrvRecordPort);
439 ExpectDomainEqual(*endpoint_1, primary_domain_);
440
441 EXPECT_EQ(GetAddressV4(*endpoint_2), kFakeARecordAddress);
442 EXPECT_EQ(GetAddressV6(*endpoint_2), kFakeAAAARecordAddress);
443 EXPECT_EQ(endpoint_2->port(), kFakeSrvRecordPort);
444 ExpectDomainEqual(*endpoint_2, secondary_domain_);
445 }
446
TEST_F(DnsDataGraphTests,FailedConversionOnlyFailsSingleEndpointCreation)447 TEST_F(DnsDataGraphTests, FailedConversionOnlyFailsSingleEndpointCreation) {
448 auto ptr = GetFakePtrRecord(primary_domain_);
449 auto srv = GetFakeSrvRecord(primary_domain_, tertiary_domain_);
450 auto txt = GetFakeTxtRecord(primary_domain_);
451 auto ptr2 = GetFakePtrRecord(secondary_domain_);
452 auto srv2 = GetFakeSrvRecord(secondary_domain_, tertiary_domain_);
453 auto txt2 = MdnsRecord(secondary_domain_, DnsType::kTXT, DnsClass::kIN,
454 RecordType::kUnique, std::chrono::seconds(0),
455 MakeTxtRecord({"=bad_txt_record"}));
456 auto a = GetFakeARecord(tertiary_domain_);
457 auto aaaa = GetFakeAAAARecord(tertiary_domain_);
458
459 TriggerRecordCreationWithCallback(ptr, primary_domain_);
460 TriggerRecordCreationWithCallback(ptr2, secondary_domain_);
461 TriggerRecordCreationWithCallback(srv, tertiary_domain_);
462 TriggerRecordCreation(srv2);
463 TriggerRecordCreation(txt);
464 TriggerRecordCreation(txt2);
465 TriggerRecordCreation(a);
466 TriggerRecordCreation(aaaa);
467
468 auto endpoints = graph_->CreateEndpoints(DnsDataGraph::GetDomainGroup(a),
469 tertiary_domain_);
470 ASSERT_EQ(endpoints.size(), size_t{2});
471 ASSERT_TRUE(endpoints[0].is_error() || endpoints[1].is_error());
472 ASSERT_TRUE(endpoints[0].is_value() || endpoints[1].is_value());
473
474 DnsSdInstanceEndpoint endpoint = endpoints[0].is_value()
475 ? std::move(endpoints[0].value())
476 : std::move(endpoints[1].value());
477 EXPECT_EQ(GetAddressV4(endpoint), kFakeARecordAddress);
478 EXPECT_EQ(GetAddressV6(endpoint), kFakeAAAARecordAddress);
479 EXPECT_EQ(endpoint.port(), kFakeSrvRecordPort);
480 ExpectDomainEqual(endpoint, primary_domain_);
481 }
482
483 } // namespace discovery
484 } // namespace openscreen
485