// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "discovery/dnssd/impl/conversion_layer.h" #include #include #include #include "discovery/dnssd/impl/instance_key.h" #include "discovery/dnssd/impl/service_key.h" #include "discovery/dnssd/testing/fake_dns_record_factory.h" #include "discovery/mdns/testing/mdns_test_util.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace openscreen { namespace discovery { // TXT Conversions. TEST(DnsSdConversionLayerTest, TestCreateTxtEmpty) { TxtRecordRdata txt = MakeTxtRecord({}); ErrorOr record = CreateFromDnsTxt(txt); EXPECT_TRUE(record.is_value()); EXPECT_TRUE(record.value().IsEmpty()); } TEST(DnsSdConversionLayerTest, TestCreateTxtOnlyEmptyString) { TxtRecordRdata txt; ErrorOr record = CreateFromDnsTxt(txt); EXPECT_TRUE(record.is_value()); EXPECT_TRUE(record.value().IsEmpty()); } TEST(DnsSdConversionLayerTest, TestCreateTxtValidKeyValue) { TxtRecordRdata txt = MakeTxtRecord({"name=value"}); ErrorOr record = CreateFromDnsTxt(txt); ASSERT_TRUE(record.is_value()); ASSERT_TRUE(record.value().GetValue("name").is_value()); // EXPECT_STREQ is causing memory leaks std::string expected = "value"; ASSERT_TRUE(record.value().GetValue("name").is_value()); const std::vector& value = record.value().GetValue("name").value(); ASSERT_EQ(value.size(), expected.size()); for (size_t i = 0; i < expected.size(); i++) { EXPECT_EQ(expected[i], value[i]); } } TEST(DnsSdConversionLayerTest, TestCreateTxtInvalidKeyValue) { TxtRecordRdata txt = MakeTxtRecord({"=value"}); ErrorOr record = CreateFromDnsTxt(txt); EXPECT_TRUE(record.is_error()); } TEST(DnsSdConversionLayerTest, TestCreateTxtValidBool) { TxtRecordRdata txt = MakeTxtRecord({"name"}); ErrorOr record = CreateFromDnsTxt(txt); ASSERT_TRUE(record.is_value()); ASSERT_TRUE(record.value().GetFlag("name").is_value()); EXPECT_TRUE(record.value().GetFlag("name").value()); } // Get*QueryInfo methods. TEST(DnsSdConversionLayerTest, GetInstanceQueryInfoTest) { InstanceKey key{"instance.Id", "_service-id._udp", "192.168.0.0"}; DnsQueryInfo query = GetInstanceQueryInfo(key); EXPECT_EQ(query.dns_type, DnsType::kANY); EXPECT_EQ(query.dns_class, DnsClass::kANY); ASSERT_EQ(query.name.labels().size(), size_t{7}); EXPECT_EQ(query.name.labels()[0], "instance.Id"); EXPECT_EQ(query.name.labels()[1], "_service-id"); EXPECT_EQ(query.name.labels()[2], "_udp"); EXPECT_EQ(query.name.labels()[3], "192"); EXPECT_EQ(query.name.labels()[4], "168"); EXPECT_EQ(query.name.labels()[5], "0"); EXPECT_EQ(query.name.labels()[6], "0"); } TEST(DnsSdConversionLayerTest, GetPtrQueryInfoTest) { ServiceKey key{"_service-id._udp", "192.168.0.0"}; DnsQueryInfo query = GetPtrQueryInfo(key); EXPECT_EQ(query.dns_type, DnsType::kPTR); EXPECT_EQ(query.dns_class, DnsClass::kANY); ASSERT_EQ(query.name.labels().size(), size_t{6}); EXPECT_EQ(query.name.labels()[0], "_service-id"); EXPECT_EQ(query.name.labels()[1], "_udp"); EXPECT_EQ(query.name.labels()[2], "192"); EXPECT_EQ(query.name.labels()[3], "168"); EXPECT_EQ(query.name.labels()[4], "0"); EXPECT_EQ(query.name.labels()[5], "0"); } // GetDnsRecords tests. TEST(DnsSdConversionLayerTest, GetDnsRecordsPtr) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kPTR; }); ASSERT_NE(it, records.end()); EXPECT_EQ(it->dns_class(), DnsClass::kIN); EXPECT_EQ(it->record_type(), RecordType::kShared); EXPECT_EQ(it->name().labels().size(), size_t{3}); EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(it->name().labels()[1], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kDomainName); const auto& rdata = absl::get(it->rdata()); EXPECT_EQ(rdata.ptr_domain().labels().size(), size_t{4}); EXPECT_EQ(rdata.ptr_domain().labels()[0], FakeDnsRecordFactory::kInstanceName); EXPECT_EQ(rdata.ptr_domain().labels()[1], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(rdata.ptr_domain().labels()[2], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(rdata.ptr_domain().labels()[3], FakeDnsRecordFactory::kDomainName); } TEST(DnsSdConversionLayerTest, GetDnsRecordsSrv) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kSRV; }); ASSERT_NE(it, records.end()); EXPECT_EQ(it->dns_class(), DnsClass::kIN); EXPECT_EQ(it->record_type(), RecordType::kUnique); EXPECT_EQ(it->name().labels().size(), size_t{4}); EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName); EXPECT_EQ(it->name().labels()[1], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName); const auto& rdata = absl::get(it->rdata()); EXPECT_EQ(rdata.priority(), 0); EXPECT_EQ(rdata.weight(), 0); EXPECT_EQ(rdata.port(), FakeDnsRecordFactory::kPortNum); } TEST(DnsSdConversionLayerTest, GetDnsRecordsAPresent) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kA; }); ASSERT_NE(it, records.end()); EXPECT_EQ(it->dns_class(), DnsClass::kIN); EXPECT_EQ(it->record_type(), RecordType::kUnique); EXPECT_EQ(it->name().labels().size(), size_t{4}); EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName); EXPECT_EQ(it->name().labels()[1], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName); const auto& rdata = absl::get(it->rdata()); EXPECT_EQ(rdata.ipv4_address(), IPAddress(FakeDnsRecordFactory::kV4AddressOctets)); } TEST(DnsSdConversionLayerTest, GetDnsRecordsANotPresent) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kA; }); EXPECT_EQ(it, records.end()); } TEST(DnsSdConversionLayerTest, GetDnsRecordsAAAAPresent) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kAAAA; }); ASSERT_NE(it, records.end()); EXPECT_EQ(it->dns_class(), DnsClass::kIN); EXPECT_EQ(it->record_type(), RecordType::kUnique); EXPECT_EQ(it->name().labels().size(), size_t{4}); EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName); EXPECT_EQ(it->name().labels()[1], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName); const auto& rdata = absl::get(it->rdata()); EXPECT_EQ(rdata.ipv6_address(), IPAddress(FakeDnsRecordFactory::kV6AddressHextets)); } TEST(DnsSdConversionLayerTest, GetDnsRecordsAAAANotPresent) { DnsSdTxtRecord txt; DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kAAAA; }); EXPECT_EQ(it, records.end()); } TEST(DnsSdConversionLayerTest, GetDnsRecordsTxt) { DnsSdTxtRecord txt; std::vector value{'v', 'a', 'l', 'u', 'e'}; txt.SetValue("name", value); txt.SetFlag("boolean", true); DnsSdInstanceEndpoint instance_endpoint( FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName, FakeDnsRecordFactory::kDomainName, txt, 0, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets), FakeDnsRecordFactory::kPortNum}, IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets), FakeDnsRecordFactory::kPortNum}); std::vector records = GetDnsRecords(instance_endpoint); auto it = std::find_if(records.begin(), records.end(), [](const MdnsRecord& record) { return record.dns_type() == DnsType::kTXT; }); ASSERT_NE(it, records.end()); EXPECT_EQ(it->dns_class(), DnsClass::kIN); EXPECT_EQ(it->record_type(), RecordType::kUnique); EXPECT_EQ(it->name().labels().size(), size_t{4}); EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName); EXPECT_EQ(it->name().labels()[1], FakeDnsRecordFactory::kServiceNameServicePart); EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kServiceNameProtocolPart); EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName); const auto& rdata = absl::get(it->rdata()); EXPECT_EQ(rdata.texts().size(), size_t{2}); auto it2 = std::find(rdata.texts().begin(), rdata.texts().end(), "name=value"); EXPECT_NE(it2, rdata.texts().end()); it2 = std::find(rdata.texts().begin(), rdata.texts().end(), "boolean"); EXPECT_NE(it2, rdata.texts().end()); } } // namespace discovery } // namespace openscreen