blob: b43a281aaec2e01f579296f26850a7f13f6bf6e4 [file] [log] [blame]
// 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 <algorithm>
#include <chrono>
#include <vector>
#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<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
EXPECT_TRUE(record.is_value());
EXPECT_TRUE(record.value().IsEmpty());
}
TEST(DnsSdConversionLayerTest, TestCreateTxtOnlyEmptyString) {
TxtRecordRdata txt;
ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
EXPECT_TRUE(record.is_value());
EXPECT_TRUE(record.value().IsEmpty());
}
TEST(DnsSdConversionLayerTest, TestCreateTxtValidKeyValue) {
TxtRecordRdata txt = MakeTxtRecord({"name=value"});
ErrorOr<DnsSdTxtRecord> 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<uint8_t>& 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<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
EXPECT_TRUE(record.is_error());
}
TEST(DnsSdConversionLayerTest, TestCreateTxtValidBool) {
TxtRecordRdata txt = MakeTxtRecord({"name"});
ErrorOr<DnsSdTxtRecord> 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<MdnsRecord> 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<PtrRecordRdata>(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<MdnsRecord> 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<SrvRecordRdata>(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<MdnsRecord> 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<ARecordRdata>(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<MdnsRecord> 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<MdnsRecord> 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<AAAARecordRdata>(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<MdnsRecord> 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<uint8_t> 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<MdnsRecord> 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<TxtRecordRdata>(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