1 // Copyright 2019 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/public/dns_sd_instance.h"
6
7 #include <vector>
8
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11
12 namespace openscreen {
13 namespace discovery {
14
TEST(DnsSdInstanceTests,InstanceLength)15 TEST(DnsSdInstanceTests, InstanceLength) {
16 EXPECT_TRUE(IsInstanceValid("instance"));
17 EXPECT_TRUE(IsInstanceValid("name"));
18 EXPECT_TRUE(IsInstanceValid(""));
19 EXPECT_TRUE(IsInstanceValid(
20 "Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
21
22 EXPECT_FALSE(IsInstanceValid(
23 "Something64CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGH"));
24 }
25
TEST(DnsSdInstanceTests,InstanceCharacters)26 TEST(DnsSdInstanceTests, InstanceCharacters) {
27 EXPECT_TRUE(IsInstanceValid("IncludingSpecialCharacters.+ =*&<<+`~\\/"));
28 EXPECT_TRUE(IsInstanceValid(".+ =*&<<+`~\\/ "));
29
30 EXPECT_FALSE(IsInstanceValid(std::string(1, uint8_t{0x7F})));
31 EXPECT_FALSE(IsInstanceValid(std::string("name with ") +
32 std::string(1, uint8_t{0x7F}) +
33 " in the middle"));
34 for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
35 EXPECT_FALSE(IsInstanceValid(std::string(1, bad_char)));
36 EXPECT_FALSE(IsInstanceValid(std::string("name with ") +
37 std::string(1, bad_char) + " in the middle"));
38 }
39 }
40
TEST(DnsSdInstanceTests,InstanceUTF8)41 TEST(DnsSdInstanceTests, InstanceUTF8) {
42 std::vector<uint8_t> char_sets[] = {
43 {0x80},
44 {0xC0},
45 {0xC0, 0xFF},
46 {0xE0},
47 {0xE0, 0xFF},
48 {0xE0, 0x80, 0x00},
49 {0xF0},
50 {0xF0, 0x00},
51 {0xF0, 0x80, 0xFF},
52 {0xF0, 0x80, 0x80, 0x0A},
53 };
54
55 for (const auto& set : char_sets) {
56 std::string test_string = "start";
57 for (uint8_t ch : set) {
58 test_string.append(std::string(1, ch));
59 }
60
61 EXPECT_FALSE(IsInstanceValid(test_string));
62 }
63 }
64
TEST(DnsSdInstanceTests,ServiceLength)65 TEST(DnsSdInstanceTests, ServiceLength) {
66 // Too short.
67 EXPECT_TRUE(IsServiceValid("_a._udp"));
68 EXPECT_FALSE(IsServiceValid("_._udp"));
69
70 // Too long.
71 EXPECT_TRUE(IsServiceValid("_abcdefghijklmno._udp"));
72 EXPECT_FALSE(IsServiceValid("_abcdefghijklmnop._udp"));
73 }
74
TEST(DnsSdInstanceTests,ServiceNonProtocolNameFormatting)75 TEST(DnsSdInstanceTests, ServiceNonProtocolNameFormatting) {
76 EXPECT_TRUE(IsServiceValid("_abcd._udp"));
77
78 // Unexprected protocol string,
79 EXPECT_FALSE(IsServiceValid("_abcd._ssl"));
80 EXPECT_FALSE(IsServiceValid("_abcd._tls"));
81 EXPECT_FALSE(IsServiceValid("_abcd._ucp"));
82
83 // Extra characters before
84 EXPECT_FALSE(IsServiceValid(" _abcd._udp"));
85 EXPECT_FALSE(IsServiceValid("a_abcd._udp"));
86 EXPECT_FALSE(IsServiceValid("-_abcd._udp"));
87
88 // Extra characters after.
89 EXPECT_FALSE(IsServiceValid("a_abcd._udp "));
90 EXPECT_FALSE(IsServiceValid("a_abcd._udp-"));
91 EXPECT_FALSE(IsServiceValid("a_abcd._udpp"));
92 EXPECT_FALSE(IsServiceValid("a_abcd._tcp_udp"));
93 }
94
TEST(DnsSdInstanceTests,ServiceProtocolNameFormatting)95 TEST(DnsSdInstanceTests, ServiceProtocolNameFormatting) {
96 EXPECT_TRUE(IsServiceValid("_abcd._udp"));
97
98 // Disallowed Characters
99 EXPECT_FALSE(IsServiceValid("_ab`d._udp"));
100 EXPECT_FALSE(IsServiceValid("_a\\cd._udp"));
101 EXPECT_FALSE(IsServiceValid("_ab.d._udp"));
102
103 // Contains no letters
104 EXPECT_FALSE(IsServiceValid("_123._udp"));
105 EXPECT_FALSE(IsServiceValid("_1-3._udp"));
106
107 // Improperly placed hyphen.
108 EXPECT_FALSE(IsServiceValid("_-abcd._udp"));
109 EXPECT_FALSE(IsServiceValid("_abcd-._udp"));
110
111 // Adjacent hyphens.
112 EXPECT_FALSE(IsServiceValid("_abc--d._udp"));
113 EXPECT_FALSE(IsServiceValid("_a--bcd._tcp"));
114 EXPECT_FALSE(IsServiceValid("_0a1b--c02d._udp"));
115 EXPECT_FALSE(IsServiceValid("_0a--1._udp"));
116 EXPECT_FALSE(IsServiceValid("_a--b._udp"));
117
118 // Multiple, non-adjacent hyphens.
119 EXPECT_TRUE(IsServiceValid("_a-b-c._udp"));
120 EXPECT_TRUE(IsServiceValid("_a-1-c._udp"));
121 }
122
TEST(DnsSdInstanceTests,DomainDotPositions)123 TEST(DnsSdInstanceTests, DomainDotPositions) {
124 EXPECT_TRUE(IsDomainValid("192.168.0.0"));
125 EXPECT_TRUE(IsDomainValid("...."));
126 EXPECT_TRUE(IsDomainValid(
127 "Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG."
128 "Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
129
130 EXPECT_FALSE(IsDomainValid(
131 "Something64CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGH."
132 "Something63CharsLongabcdefghijklmnopqrstuvwxyz1234567890ABCDEFG"));
133 }
134
TEST(DnsSdInstanceTests,DomainCharacters)135 TEST(DnsSdInstanceTests, DomainCharacters) {
136 EXPECT_TRUE(IsDomainValid("IncludingSpecialCharacters.+ =*&<<+`~\\/"));
137 EXPECT_TRUE(IsDomainValid(".+ =*&<<+`~\\/ "));
138
139 EXPECT_FALSE(IsDomainValid(std::string(1, uint8_t{0x7F})));
140 EXPECT_FALSE(IsDomainValid(std::string("name with ") +
141 std::string(1, uint8_t{0x7F}) + " in the middle"));
142 for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
143 EXPECT_FALSE(IsDomainValid(std::string(1, bad_char)));
144 EXPECT_FALSE(IsDomainValid(std::string("name with ") +
145 std::string(1, bad_char) + " in the middle"));
146 }
147 }
148
TEST(DnsSdInstanceTests,DomainUTF8)149 TEST(DnsSdInstanceTests, DomainUTF8) {
150 std::vector<uint8_t> char_sets[] = {
151 {0x80},
152 {0xC0},
153 {0xC0, 0xFF},
154 {0xE0},
155 {0xE0, 0xFF},
156 {0xE0, 0x80, 0x00},
157 {0xF0},
158 {0xF0, 0x00},
159 {0xF0, 0x80, 0xFF},
160 {0xF0, 0x80, 0x80, 0x0A},
161 };
162
163 for (const auto& set : char_sets) {
164 std::string test_string = "start";
165 for (uint8_t ch : set) {
166 test_string.append(std::string(1, ch));
167 }
168
169 EXPECT_FALSE(IsDomainValid(test_string));
170 }
171 }
172
TEST(DnsSdInstanceTests,SubtypeCharacters)173 TEST(DnsSdInstanceTests, SubtypeCharacters) {
174 EXPECT_TRUE(IsSubtypeValid("IncludingSpecialCharacters+ =*&<<+`~\\/"));
175 EXPECT_TRUE(IsSubtypeValid("+ =*&<<+`~\\/ "));
176
177 EXPECT_FALSE(IsSubtypeValid("foo.bar"));
178 EXPECT_FALSE(IsSubtypeValid(std::string(1, uint8_t{0x7F})));
179 EXPECT_FALSE(IsSubtypeValid(std::string("name with ") +
180 std::string(1, uint8_t{0x7F}) +
181 " in the middle"));
182 for (uint8_t bad_char = 0x0; bad_char <= 0x1F; bad_char++) {
183 EXPECT_FALSE(IsSubtypeValid(std::string(1, bad_char)));
184 EXPECT_FALSE(IsSubtypeValid(std::string("name with ") +
185 std::string(1, bad_char) + " in the middle"));
186 }
187 }
188
TEST(DnsSdInstanceTests,SubtypeUTF8)189 TEST(DnsSdInstanceTests, SubtypeUTF8) {
190 // Sets of bytes which do not form valid UTF8 encoded chars.
191 std::vector<uint8_t> char_sets[] = {
192 {0x80},
193 {0xC0},
194 {0xC0, 0xFF},
195 {0xE0},
196 {0xE0, 0xFF},
197 {0xE0, 0x80, 0x00},
198 {0xF0},
199 {0xF0, 0x00},
200 {0xF0, 0x80, 0xFF},
201 {0xF0, 0x80, 0x80, 0x0A},
202 };
203
204 for (const auto& set : char_sets) {
205 std::string test_string = "start";
206 for (uint8_t ch : set) {
207 test_string.append(std::string(1, ch));
208 }
209
210 EXPECT_FALSE(IsSubtypeValid(test_string));
211 }
212 }
213
TEST(DnsSdInstanceTests,SubtypeLength)214 TEST(DnsSdInstanceTests, SubtypeLength) {
215 std::string kCharsAlmostMaxLength =
216 "123456989012345678901234567890123456789012345678901234567890123";
217
218 ASSERT_EQ(kCharsAlmostMaxLength.size(), size_t{63});
219 EXPECT_TRUE(IsSubtypeValid(kCharsAlmostMaxLength));
220 EXPECT_FALSE(IsSubtypeValid(kCharsAlmostMaxLength + "4"));
221 }
222
TEST(DnsSdInstanceTests,ComparisonTests)223 TEST(DnsSdInstanceTests, ComparisonTests) {
224 DnsSdTxtRecord set_record;
225 set_record.SetValue("foo", "bar");
226
227 DnsSdInstance kIn1("instance", "_service._tcp", "local", {}, 80);
228 DnsSdInstance kIn2("instance", "_service._tcp", "local", {}, 80);
229 DnsSdInstance kIn3("instance2", "_service._tcp", "local", {}, 80);
230 DnsSdInstance kIn4("instance", "_service2._tcp", "local", {}, 80);
231 DnsSdInstance kIn5("instance", "_service._tcp", "local2", {}, 80);
232 DnsSdInstance kIn6("instance", "_service._tcp", "local", set_record, 80);
233 DnsSdInstance kIn7("instance", "_service._tcp", "local", {}, 79);
234 DnsSdInstance kIn8("instance", "_service._tcp", "local", {}, 80, "foo");
235 DnsSdInstance kIn9("instance", "_service._tcp", "local", {}, 80, "foobar");
236 DnsSdInstance kIn10("instance", "_service._tcp", "local", {}, 80, "foo",
237 "bar");
238
239 EXPECT_EQ(kIn1, kIn2);
240 EXPECT_LT(kIn1, kIn3);
241 EXPECT_LT(kIn1, kIn4);
242 EXPECT_LT(kIn1, kIn5);
243 EXPECT_LT(kIn1, kIn6);
244 EXPECT_GT(kIn1, kIn7);
245 EXPECT_LT(kIn1, kIn8);
246 EXPECT_LT(kIn1, kIn9);
247 EXPECT_LT(kIn1, kIn10);
248
249 EXPECT_LT(kIn8, kIn9);
250 EXPECT_LT(kIn8, kIn10);
251 EXPECT_LT(kIn9, kIn10);
252 }
253
254 } // namespace discovery
255 } // namespace openscreen
256