blob: 76f310036bf11fde9829b95554974c0b7994e2c8 [file] [log] [blame]
// Copyright 2018 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 "osp/impl/discovery/mdns/domain_name.h"
#include <sstream>
#include "gtest/gtest.h"
#include "platform/base/error.h"
namespace openscreen {
namespace osp {
namespace {
ErrorOr<DomainName> FromLabels(const std::vector<std::string>& labels) {
return DomainName::FromLabels(labels.begin(), labels.end());
}
template <typename T>
T UnpackErrorOr(ErrorOr<T> error_or) {
EXPECT_TRUE(error_or);
return std::move(error_or.value());
}
} // namespace
TEST(DomainNameTest, Constructors) {
DomainName empty;
ASSERT_EQ(1u, empty.domain_name().size());
EXPECT_EQ(0, empty.domain_name()[0]);
DomainName original({10, 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n', 3,
'o', 'r', 'g', 0});
ASSERT_EQ(16u, original.domain_name().size());
auto data_copy = original.domain_name();
DomainName direct_ctor(std::move(data_copy));
EXPECT_EQ(direct_ctor.domain_name(), original.domain_name());
DomainName copy_ctor(original);
EXPECT_EQ(copy_ctor.domain_name(), original.domain_name());
DomainName move_ctor(std::move(copy_ctor));
EXPECT_EQ(move_ctor.domain_name(), original.domain_name());
DomainName copy_assign;
copy_assign = move_ctor;
EXPECT_EQ(copy_assign.domain_name(), original.domain_name());
DomainName move_assign;
move_assign = std::move(move_ctor);
EXPECT_EQ(move_assign.domain_name(), original.domain_name());
}
TEST(DomainNameTest, FromLabels) {
const auto typical =
std::vector<uint8_t>{10, 'o', 'p', 'e', 'n', 's', 'c', 'r',
'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
DomainName result = UnpackErrorOr(FromLabels({"openscreen", "org"}));
EXPECT_EQ(result.domain_name(), typical);
const auto includes_dot =
std::vector<uint8_t>{11, 'o', 'p', 'e', 'n', '.', 's', 'c', 'r',
'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
result = UnpackErrorOr(FromLabels({"open.screen", "org"}));
EXPECT_EQ(result.domain_name(), includes_dot);
const auto includes_non_ascii =
std::vector<uint8_t>{11, 'o', 'p', 'e', 'n', 7, 's', 'c', 'r',
'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
result = UnpackErrorOr(FromLabels({"open\7screen", "org"}));
EXPECT_EQ(result.domain_name(), includes_non_ascii);
ASSERT_FALSE(
FromLabels({"extremely-long-label-that-is-actually-too-long-"
"for-rfc-1034-and-will-not-generate"}));
ASSERT_FALSE(FromLabels({
"extremely-long-domain-name-that-is-made-of",
"valid-labels",
"however-overall-it-is-too-long-for-rfc-1034",
"so-it-should-fail-to-generate",
"filler-filler-filler-filler-filler",
"filler-filler-filler-filler-filler",
"filler-filler-filler-filler-filler",
"filler-filler-filler-filler-filler",
}));
}
TEST(DomainNameTest, Equality) {
DomainName alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
DomainName beta = UnpackErrorOr(FromLabels({"beta", "openscreen", "org"}));
const DomainName alpha_copy = alpha;
EXPECT_TRUE(alpha == alpha);
EXPECT_FALSE(alpha != alpha);
EXPECT_TRUE(alpha == alpha_copy);
EXPECT_FALSE(alpha != alpha_copy);
EXPECT_FALSE(alpha == beta);
EXPECT_TRUE(alpha != beta);
}
TEST(DomainNameTest, EndsWithLocalDomain) {
DomainName alpha;
EXPECT_FALSE(alpha.EndsWithLocalDomain());
alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
DomainName beta = UnpackErrorOr(FromLabels({"beta", "local"}));
EXPECT_FALSE(alpha.EndsWithLocalDomain());
EXPECT_TRUE(beta.EndsWithLocalDomain());
}
TEST(DomainNameTest, IsEmpty) {
DomainName alpha;
DomainName beta(std::vector<uint8_t>{0});
EXPECT_TRUE(alpha.IsEmpty());
EXPECT_TRUE(beta.IsEmpty());
alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
EXPECT_FALSE(alpha.IsEmpty());
}
TEST(DomainNameTest, Append) {
const auto expected_service_name =
std::vector<uint8_t>{5, 'a', 'l', 'p', 'h', 'a', '\0'};
const auto expected_service_type_initial = std::vector<uint8_t>{
11, '_', 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n', '\0'};
const auto expected_protocol =
std::vector<uint8_t>{5, '_', 'q', 'u', 'i', 'c', '\0'};
const auto expected_service_type =
std::vector<uint8_t>{11, '_', 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e',
'e', 'n', 5, '_', 'q', 'u', 'i', 'c', '\0'};
const auto total_expected = std::vector<uint8_t>{
5, 'a', 'l', 'p', 'h', 'a', 11, '_', 'o', 'p', 'e', 'n', 's',
'c', 'r', 'e', 'e', 'n', 5, '_', 'q', 'u', 'i', 'c', '\0'};
DomainName service_name = UnpackErrorOr(FromLabels({"alpha"}));
EXPECT_EQ(service_name.domain_name(), expected_service_name);
DomainName service_type = UnpackErrorOr(FromLabels({"_openscreen"}));
EXPECT_EQ(service_type.domain_name(), expected_service_type_initial);
DomainName protocol = UnpackErrorOr(FromLabels({"_quic"}));
EXPECT_EQ(protocol.domain_name(), expected_protocol);
EXPECT_TRUE(service_type.Append(protocol).ok());
EXPECT_EQ(service_type.domain_name(), expected_service_type);
DomainName result =
UnpackErrorOr(DomainName::Append(service_name, service_type));
EXPECT_EQ(result.domain_name(), total_expected);
}
TEST(DomainNameTest, GetLabels) {
const auto labels = std::vector<std::string>{"alpha", "beta", "gamma", "org"};
DomainName domain_name = UnpackErrorOr(FromLabels(labels));
const auto actual_labels = domain_name.GetLabels();
for (size_t i = 0; i < labels.size(); ++i) {
EXPECT_EQ(labels[i], actual_labels[i]);
}
}
TEST(DomainNameTest, StreamEscaping) {
{
std::stringstream ss;
ss << DomainName(std::vector<uint8_t>{1, 0, 0});
EXPECT_EQ(ss.str(), "\\x00.");
}
{
std::stringstream ss;
ss << DomainName(std::vector<uint8_t>{1, 1, 0});
EXPECT_EQ(ss.str(), "\\x01.");
}
{
std::stringstream ss;
ss << DomainName(std::vector<uint8_t>{1, 18, 0});
EXPECT_EQ(ss.str(), "\\x12.");
}
{
std::stringstream ss;
ss << DomainName(std::vector<uint8_t>{1, 255, 0});
EXPECT_EQ(ss.str(), "\\xff.");
}
}
} // namespace osp
} // namespace openscreen