blob: 3395938db772bd97865f28f76b90a8c34dbb0409 [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/public/dns_sd_instance.h"
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace openscreen {
namespace discovery {
TEST(DnsSdInstanceTests, InstanceLength) {
EXPECT_TRUE(IsInstanceValid("instance"));
EXPECT_TRUE(IsInstanceValid("name"));
EXPECT_TRUE(IsInstanceValid(""));
EXPECT_TRUE(IsInstanceValid(
"Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
EXPECT_FALSE(IsInstanceValid(
"Something64CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGH"));
}
TEST(DnsSdInstanceTests, InstanceCharacters) {
EXPECT_TRUE(IsInstanceValid("IncludingSpecialCharacters.+ =*&<<+`~\\/"));
EXPECT_TRUE(IsInstanceValid(".+ =*&<<+`~\\/ "));
EXPECT_FALSE(IsInstanceValid(std::string(1, uint8_t{0x7F})));
EXPECT_FALSE(IsInstanceValid(std::string("name with ") +
std::string(1, uint8_t{0x7F}) +
" in the middle"));
for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
EXPECT_FALSE(IsInstanceValid(std::string(1, bad_char)));
EXPECT_FALSE(IsInstanceValid(std::string("name with ") +
std::string(1, bad_char) + " in the middle"));
}
}
TEST(DnsSdInstanceTests, InstanceUTF8) {
std::vector<uint8_t> char_sets[] = {
{0x80},
{0xC0},
{0xC0, 0xFF},
{0xE0},
{0xE0, 0xFF},
{0xE0, 0x80, 0x00},
{0xF0},
{0xF0, 0x00},
{0xF0, 0x80, 0xFF},
{0xF0, 0x80, 0x80, 0x0A},
};
for (const auto& set : char_sets) {
std::string test_string = "start";
for (uint8_t ch : set) {
test_string.append(std::string(1, ch));
}
EXPECT_FALSE(IsInstanceValid(test_string));
}
}
TEST(DnsSdInstanceTests, ServiceLength) {
// Too short.
EXPECT_TRUE(IsServiceValid("_a._udp"));
EXPECT_FALSE(IsServiceValid("_._udp"));
// Too long.
EXPECT_TRUE(IsServiceValid("_abcdefghijklmno._udp"));
EXPECT_FALSE(IsServiceValid("_abcdefghijklmnop._udp"));
}
TEST(DnsSdInstanceTests, ServiceNonProtocolNameFormatting) {
EXPECT_TRUE(IsServiceValid("_abcd._udp"));
// Unexprected protocol string,
EXPECT_FALSE(IsServiceValid("_abcd._ssl"));
EXPECT_FALSE(IsServiceValid("_abcd._tls"));
EXPECT_FALSE(IsServiceValid("_abcd._ucp"));
// Extra characters before
EXPECT_FALSE(IsServiceValid(" _abcd._udp"));
EXPECT_FALSE(IsServiceValid("a_abcd._udp"));
EXPECT_FALSE(IsServiceValid("-_abcd._udp"));
// Extra characters after.
EXPECT_FALSE(IsServiceValid("a_abcd._udp "));
EXPECT_FALSE(IsServiceValid("a_abcd._udp-"));
EXPECT_FALSE(IsServiceValid("a_abcd._udpp"));
EXPECT_FALSE(IsServiceValid("a_abcd._tcp_udp"));
}
TEST(DnsSdInstanceTests, ServiceProtocolNameFormatting) {
EXPECT_TRUE(IsServiceValid("_abcd._udp"));
// Disallowed Characters
EXPECT_FALSE(IsServiceValid("_ab`d._udp"));
EXPECT_FALSE(IsServiceValid("_a\\cd._udp"));
EXPECT_FALSE(IsServiceValid("_ab.d._udp"));
// Contains no letters
EXPECT_FALSE(IsServiceValid("_123._udp"));
EXPECT_FALSE(IsServiceValid("_1-3._udp"));
// Improperly placed hyphen.
EXPECT_FALSE(IsServiceValid("_-abcd._udp"));
EXPECT_FALSE(IsServiceValid("_abcd-._udp"));
// Adjacent hyphens.
EXPECT_FALSE(IsServiceValid("_abc--d._udp"));
EXPECT_FALSE(IsServiceValid("_a--bcd._tcp"));
EXPECT_FALSE(IsServiceValid("_0a1b--c02d._udp"));
EXPECT_FALSE(IsServiceValid("_0a--1._udp"));
EXPECT_FALSE(IsServiceValid("_a--b._udp"));
// Multiple, non-adjacent hyphens.
EXPECT_TRUE(IsServiceValid("_a-b-c._udp"));
EXPECT_TRUE(IsServiceValid("_a-1-c._udp"));
}
TEST(DnsSdInstanceTests, DomainDotPositions) {
EXPECT_TRUE(IsDomainValid("192.168.0.0"));
EXPECT_TRUE(IsDomainValid("...."));
EXPECT_TRUE(IsDomainValid(
"Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG."
"Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
EXPECT_FALSE(IsDomainValid(
"Something64CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGH."
"Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
}
TEST(DnsSdInstanceTests, DomainCharacters) {
EXPECT_TRUE(IsDomainValid("IncludingSpecialCharacters.+ =*&<<+`~\\/"));
EXPECT_TRUE(IsDomainValid(".+ =*&<<+`~\\/ "));
EXPECT_FALSE(IsDomainValid(std::string(1, uint8_t{0x7F})));
EXPECT_FALSE(IsDomainValid(std::string("name with ") +
std::string(1, uint8_t{0x7F}) + " in the middle"));
for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
EXPECT_FALSE(IsDomainValid(std::string(1, bad_char)));
EXPECT_FALSE(IsDomainValid(std::string("name with ") +
std::string(1, bad_char) + " in the middle"));
}
}
TEST(DnsSdInstanceTests, DomainUTF8) {
std::vector<uint8_t> char_sets[] = {
{0x80},
{0xC0},
{0xC0, 0xFF},
{0xE0},
{0xE0, 0xFF},
{0xE0, 0x80, 0x00},
{0xF0},
{0xF0, 0x00},
{0xF0, 0x80, 0xFF},
{0xF0, 0x80, 0x80, 0x0A},
};
for (const auto& set : char_sets) {
std::string test_string = "start";
for (uint8_t ch : set) {
test_string.append(std::string(1, ch));
}
EXPECT_FALSE(IsDomainValid(test_string));
}
}
TEST(DnsSdInstanceTests, SubtypeCharacters) {
EXPECT_TRUE(IsSubtypeValid("IncludingSpecialCharacters+ =*&<<+`~\\/"));
EXPECT_TRUE(IsSubtypeValid("+ =*&<<+`~\\/ "));
EXPECT_FALSE(IsSubtypeValid("foo.bar"));
EXPECT_FALSE(IsSubtypeValid(std::string(1, uint8_t{0x7F})));
EXPECT_FALSE(IsSubtypeValid(std::string("name with ") +
std::string(1, uint8_t{0x7F}) +
" in the middle"));
for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
EXPECT_FALSE(IsSubtypeValid(std::string(1, bad_char)));
EXPECT_FALSE(IsSubtypeValid(std::string("name with ") +
std::string(1, bad_char) + " in the middle"));
}
}
TEST(DnsSdInstanceTests, SubtypeUTF8) {
// Sets of bytes which do not form valid UTF8 encoded chars.
std::vector<uint8_t> char_sets[] = {
{0x80},
{0xC0},
{0xC0, 0xFF},
{0xE0},
{0xE0, 0xFF},
{0xE0, 0x80, 0x00},
{0xF0},
{0xF0, 0x00},
{0xF0, 0x80, 0xFF},
{0xF0, 0x80, 0x80, 0x0A},
};
for (const auto& set : char_sets) {
std::string test_string = "start";
for (uint8_t ch : set) {
test_string.append(std::string(1, ch));
}
EXPECT_FALSE(IsSubtypeValid(test_string));
}
}
TEST(DnsSdInstanceTests, SubtypeLength) {
std::string kCharsAlmostMaxLength =
"123456989012345678901234567890123456789012345678901234567890123";
ASSERT_EQ(kCharsAlmostMaxLength.size(), size_t{63});
EXPECT_TRUE(IsSubtypeValid(kCharsAlmostMaxLength));
EXPECT_FALSE(IsSubtypeValid(kCharsAlmostMaxLength + "4"));
}
TEST(DnsSdInstanceTests, ComparisonTests) {
DnsSdTxtRecord set_record;
set_record.SetValue("foo", "bar");
DnsSdInstance kIn1("instance", "_service._tcp", "local", {}, 80);
DnsSdInstance kIn2("instance", "_service._tcp", "local", {}, 80);
DnsSdInstance kIn3("instance2", "_service._tcp", "local", {}, 80);
DnsSdInstance kIn4("instance", "_service2._tcp", "local", {}, 80);
DnsSdInstance kIn5("instance", "_service._tcp", "local2", {}, 80);
DnsSdInstance kIn6("instance", "_service._tcp", "local", set_record, 80);
DnsSdInstance kIn7("instance", "_service._tcp", "local", {}, 79);
DnsSdInstance kIn8("instance", "_service._tcp", "local", {}, 80, "foo");
DnsSdInstance kIn9("instance", "_service._tcp", "local", {}, 80, "foobar");
DnsSdInstance kIn10("instance", "_service._tcp", "local", {}, 80, "foo",
"bar");
EXPECT_EQ(kIn1, kIn2);
EXPECT_LT(kIn1, kIn3);
EXPECT_LT(kIn1, kIn4);
EXPECT_LT(kIn1, kIn5);
EXPECT_LT(kIn1, kIn6);
EXPECT_GT(kIn1, kIn7);
EXPECT_LT(kIn1, kIn8);
EXPECT_LT(kIn1, kIn9);
EXPECT_LT(kIn1, kIn10);
EXPECT_LT(kIn8, kIn9);
EXPECT_LT(kIn8, kIn10);
EXPECT_LT(kIn9, kIn10);
}
} // namespace discovery
} // namespace openscreen