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/impl/conversion_layer.h"
6
7 #include <algorithm>
8 #include <chrono>
9 #include <vector>
10
11 #include "discovery/dnssd/impl/instance_key.h"
12 #include "discovery/dnssd/impl/service_key.h"
13 #include "discovery/dnssd/testing/fake_dns_record_factory.h"
14 #include "discovery/mdns/testing/mdns_test_util.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17
18 namespace openscreen {
19 namespace discovery {
20
21 // TXT Conversions.
TEST(DnsSdConversionLayerTest,TestCreateTxtEmpty)22 TEST(DnsSdConversionLayerTest, TestCreateTxtEmpty) {
23 TxtRecordRdata txt = MakeTxtRecord({});
24 ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
25 EXPECT_TRUE(record.is_value());
26 EXPECT_TRUE(record.value().IsEmpty());
27 }
28
TEST(DnsSdConversionLayerTest,TestCreateTxtOnlyEmptyString)29 TEST(DnsSdConversionLayerTest, TestCreateTxtOnlyEmptyString) {
30 TxtRecordRdata txt;
31 ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
32 EXPECT_TRUE(record.is_value());
33 EXPECT_TRUE(record.value().IsEmpty());
34 }
35
TEST(DnsSdConversionLayerTest,TestCreateTxtValidKeyValue)36 TEST(DnsSdConversionLayerTest, TestCreateTxtValidKeyValue) {
37 TxtRecordRdata txt = MakeTxtRecord({"name=value"});
38 ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
39 ASSERT_TRUE(record.is_value());
40 ASSERT_TRUE(record.value().GetValue("name").is_value());
41
42 // EXPECT_STREQ is causing memory leaks
43 std::string expected = "value";
44 ASSERT_TRUE(record.value().GetValue("name").is_value());
45 const std::vector<uint8_t>& value = record.value().GetValue("name").value();
46 ASSERT_EQ(value.size(), expected.size());
47 for (size_t i = 0; i < expected.size(); i++) {
48 EXPECT_EQ(expected[i], value[i]);
49 }
50 }
51
TEST(DnsSdConversionLayerTest,TestCreateTxtInvalidKeyValue)52 TEST(DnsSdConversionLayerTest, TestCreateTxtInvalidKeyValue) {
53 TxtRecordRdata txt = MakeTxtRecord({"=value"});
54 ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
55 EXPECT_TRUE(record.is_error());
56 }
57
TEST(DnsSdConversionLayerTest,TestCreateTxtValidBool)58 TEST(DnsSdConversionLayerTest, TestCreateTxtValidBool) {
59 TxtRecordRdata txt = MakeTxtRecord({"name"});
60 ErrorOr<DnsSdTxtRecord> record = CreateFromDnsTxt(txt);
61 ASSERT_TRUE(record.is_value());
62 ASSERT_TRUE(record.value().GetFlag("name").is_value());
63 EXPECT_TRUE(record.value().GetFlag("name").value());
64 }
65
66 // Get*QueryInfo methods.
TEST(DnsSdConversionLayerTest,GetInstanceQueryInfoTest)67 TEST(DnsSdConversionLayerTest, GetInstanceQueryInfoTest) {
68 InstanceKey key{"instance.Id", "_service-id._udp", "192.168.0.0"};
69 DnsQueryInfo query = GetInstanceQueryInfo(key);
70 EXPECT_EQ(query.dns_type, DnsType::kANY);
71 EXPECT_EQ(query.dns_class, DnsClass::kANY);
72 ASSERT_EQ(query.name.labels().size(), size_t{7});
73 EXPECT_EQ(query.name.labels()[0], "instance.Id");
74 EXPECT_EQ(query.name.labels()[1], "_service-id");
75 EXPECT_EQ(query.name.labels()[2], "_udp");
76 EXPECT_EQ(query.name.labels()[3], "192");
77 EXPECT_EQ(query.name.labels()[4], "168");
78 EXPECT_EQ(query.name.labels()[5], "0");
79 EXPECT_EQ(query.name.labels()[6], "0");
80 }
81
TEST(DnsSdConversionLayerTest,GetPtrQueryInfoTest)82 TEST(DnsSdConversionLayerTest, GetPtrQueryInfoTest) {
83 ServiceKey key{"_service-id._udp", "192.168.0.0"};
84 DnsQueryInfo query = GetPtrQueryInfo(key);
85 EXPECT_EQ(query.dns_type, DnsType::kPTR);
86 EXPECT_EQ(query.dns_class, DnsClass::kANY);
87 ASSERT_EQ(query.name.labels().size(), size_t{6});
88 EXPECT_EQ(query.name.labels()[0], "_service-id");
89 EXPECT_EQ(query.name.labels()[1], "_udp");
90 EXPECT_EQ(query.name.labels()[2], "192");
91 EXPECT_EQ(query.name.labels()[3], "168");
92 EXPECT_EQ(query.name.labels()[4], "0");
93 EXPECT_EQ(query.name.labels()[5], "0");
94 }
95
96 // GetDnsRecords tests.
TEST(DnsSdConversionLayerTest,GetDnsRecordsPtr)97 TEST(DnsSdConversionLayerTest, GetDnsRecordsPtr) {
98 DnsSdTxtRecord txt;
99 DnsSdInstanceEndpoint instance_endpoint(
100 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
101 FakeDnsRecordFactory::kDomainName, txt, 0,
102 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
103 FakeDnsRecordFactory::kPortNum},
104 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
105 FakeDnsRecordFactory::kPortNum});
106 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
107 auto it = std::find_if(records.begin(), records.end(),
108 [](const MdnsRecord& record) {
109 return record.dns_type() == DnsType::kPTR;
110 });
111 ASSERT_NE(it, records.end());
112
113 EXPECT_EQ(it->dns_class(), DnsClass::kIN);
114 EXPECT_EQ(it->record_type(), RecordType::kShared);
115 EXPECT_EQ(it->name().labels().size(), size_t{3});
116 EXPECT_EQ(it->name().labels()[0],
117 FakeDnsRecordFactory::kServiceNameServicePart);
118 EXPECT_EQ(it->name().labels()[1],
119 FakeDnsRecordFactory::kServiceNameProtocolPart);
120 EXPECT_EQ(it->name().labels()[2], FakeDnsRecordFactory::kDomainName);
121
122 const auto& rdata = absl::get<PtrRecordRdata>(it->rdata());
123 EXPECT_EQ(rdata.ptr_domain().labels().size(), size_t{4});
124 EXPECT_EQ(rdata.ptr_domain().labels()[0],
125 FakeDnsRecordFactory::kInstanceName);
126 EXPECT_EQ(rdata.ptr_domain().labels()[1],
127 FakeDnsRecordFactory::kServiceNameServicePart);
128 EXPECT_EQ(rdata.ptr_domain().labels()[2],
129 FakeDnsRecordFactory::kServiceNameProtocolPart);
130 EXPECT_EQ(rdata.ptr_domain().labels()[3], FakeDnsRecordFactory::kDomainName);
131 }
132
TEST(DnsSdConversionLayerTest,GetDnsRecordsSrv)133 TEST(DnsSdConversionLayerTest, GetDnsRecordsSrv) {
134 DnsSdTxtRecord txt;
135 DnsSdInstanceEndpoint instance_endpoint(
136 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
137 FakeDnsRecordFactory::kDomainName, txt, 0,
138 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
139 FakeDnsRecordFactory::kPortNum},
140 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
141 FakeDnsRecordFactory::kPortNum});
142 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
143 auto it = std::find_if(records.begin(), records.end(),
144 [](const MdnsRecord& record) {
145 return record.dns_type() == DnsType::kSRV;
146 });
147 ASSERT_NE(it, records.end());
148
149 EXPECT_EQ(it->dns_class(), DnsClass::kIN);
150 EXPECT_EQ(it->record_type(), RecordType::kUnique);
151 EXPECT_EQ(it->name().labels().size(), size_t{4});
152 EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName);
153 EXPECT_EQ(it->name().labels()[1],
154 FakeDnsRecordFactory::kServiceNameServicePart);
155 EXPECT_EQ(it->name().labels()[2],
156 FakeDnsRecordFactory::kServiceNameProtocolPart);
157 EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName);
158
159 const auto& rdata = absl::get<SrvRecordRdata>(it->rdata());
160 EXPECT_EQ(rdata.priority(), 0);
161 EXPECT_EQ(rdata.weight(), 0);
162 EXPECT_EQ(rdata.port(), FakeDnsRecordFactory::kPortNum);
163 }
164
TEST(DnsSdConversionLayerTest,GetDnsRecordsAPresent)165 TEST(DnsSdConversionLayerTest, GetDnsRecordsAPresent) {
166 DnsSdTxtRecord txt;
167 DnsSdInstanceEndpoint instance_endpoint(
168 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
169 FakeDnsRecordFactory::kDomainName, txt, 0,
170 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
171 FakeDnsRecordFactory::kPortNum},
172 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
173 FakeDnsRecordFactory::kPortNum});
174 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
175 auto it = std::find_if(records.begin(), records.end(),
176 [](const MdnsRecord& record) {
177 return record.dns_type() == DnsType::kA;
178 });
179 ASSERT_NE(it, records.end());
180
181 EXPECT_EQ(it->dns_class(), DnsClass::kIN);
182 EXPECT_EQ(it->record_type(), RecordType::kUnique);
183 EXPECT_EQ(it->name().labels().size(), size_t{4});
184 EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName);
185 EXPECT_EQ(it->name().labels()[1],
186 FakeDnsRecordFactory::kServiceNameServicePart);
187 EXPECT_EQ(it->name().labels()[2],
188 FakeDnsRecordFactory::kServiceNameProtocolPart);
189 EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName);
190
191 const auto& rdata = absl::get<ARecordRdata>(it->rdata());
192 EXPECT_EQ(rdata.ipv4_address(),
193 IPAddress(FakeDnsRecordFactory::kV4AddressOctets));
194 }
195
TEST(DnsSdConversionLayerTest,GetDnsRecordsANotPresent)196 TEST(DnsSdConversionLayerTest, GetDnsRecordsANotPresent) {
197 DnsSdTxtRecord txt;
198 DnsSdInstanceEndpoint instance_endpoint(
199 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
200 FakeDnsRecordFactory::kDomainName, txt, 0,
201 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
202 FakeDnsRecordFactory::kPortNum});
203 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
204 auto it = std::find_if(records.begin(), records.end(),
205 [](const MdnsRecord& record) {
206 return record.dns_type() == DnsType::kA;
207 });
208 EXPECT_EQ(it, records.end());
209 }
210
TEST(DnsSdConversionLayerTest,GetDnsRecordsAAAAPresent)211 TEST(DnsSdConversionLayerTest, GetDnsRecordsAAAAPresent) {
212 DnsSdTxtRecord txt;
213 DnsSdInstanceEndpoint instance_endpoint(
214 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
215 FakeDnsRecordFactory::kDomainName, txt, 0,
216 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
217 FakeDnsRecordFactory::kPortNum},
218 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
219 FakeDnsRecordFactory::kPortNum});
220 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
221 auto it = std::find_if(records.begin(), records.end(),
222 [](const MdnsRecord& record) {
223 return record.dns_type() == DnsType::kAAAA;
224 });
225 ASSERT_NE(it, records.end());
226
227 EXPECT_EQ(it->dns_class(), DnsClass::kIN);
228 EXPECT_EQ(it->record_type(), RecordType::kUnique);
229 EXPECT_EQ(it->name().labels().size(), size_t{4});
230 EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName);
231 EXPECT_EQ(it->name().labels()[1],
232 FakeDnsRecordFactory::kServiceNameServicePart);
233 EXPECT_EQ(it->name().labels()[2],
234 FakeDnsRecordFactory::kServiceNameProtocolPart);
235 EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName);
236
237 const auto& rdata = absl::get<AAAARecordRdata>(it->rdata());
238 EXPECT_EQ(rdata.ipv6_address(),
239 IPAddress(FakeDnsRecordFactory::kV6AddressHextets));
240 }
241
TEST(DnsSdConversionLayerTest,GetDnsRecordsAAAANotPresent)242 TEST(DnsSdConversionLayerTest, GetDnsRecordsAAAANotPresent) {
243 DnsSdTxtRecord txt;
244 DnsSdInstanceEndpoint instance_endpoint(
245 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
246 FakeDnsRecordFactory::kDomainName, txt, 0,
247 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
248 FakeDnsRecordFactory::kPortNum});
249 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
250 auto it = std::find_if(records.begin(), records.end(),
251 [](const MdnsRecord& record) {
252 return record.dns_type() == DnsType::kAAAA;
253 });
254 EXPECT_EQ(it, records.end());
255 }
256
TEST(DnsSdConversionLayerTest,GetDnsRecordsTxt)257 TEST(DnsSdConversionLayerTest, GetDnsRecordsTxt) {
258 DnsSdTxtRecord txt;
259 std::vector<uint8_t> value{'v', 'a', 'l', 'u', 'e'};
260 txt.SetValue("name", value);
261 txt.SetFlag("boolean", true);
262 DnsSdInstanceEndpoint instance_endpoint(
263 FakeDnsRecordFactory::kInstanceName, FakeDnsRecordFactory::kServiceName,
264 FakeDnsRecordFactory::kDomainName, txt, 0,
265 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV4AddressOctets),
266 FakeDnsRecordFactory::kPortNum},
267 IPEndpoint{IPAddress(FakeDnsRecordFactory::kV6AddressHextets),
268 FakeDnsRecordFactory::kPortNum});
269 std::vector<MdnsRecord> records = GetDnsRecords(instance_endpoint);
270 auto it = std::find_if(records.begin(), records.end(),
271 [](const MdnsRecord& record) {
272 return record.dns_type() == DnsType::kTXT;
273 });
274 ASSERT_NE(it, records.end());
275
276 EXPECT_EQ(it->dns_class(), DnsClass::kIN);
277 EXPECT_EQ(it->record_type(), RecordType::kUnique);
278 EXPECT_EQ(it->name().labels().size(), size_t{4});
279 EXPECT_EQ(it->name().labels()[0], FakeDnsRecordFactory::kInstanceName);
280 EXPECT_EQ(it->name().labels()[1],
281 FakeDnsRecordFactory::kServiceNameServicePart);
282 EXPECT_EQ(it->name().labels()[2],
283 FakeDnsRecordFactory::kServiceNameProtocolPart);
284 EXPECT_EQ(it->name().labels()[3], FakeDnsRecordFactory::kDomainName);
285
286 const auto& rdata = absl::get<TxtRecordRdata>(it->rdata());
287 EXPECT_EQ(rdata.texts().size(), size_t{2});
288
289 auto it2 =
290 std::find(rdata.texts().begin(), rdata.texts().end(), "name=value");
291 EXPECT_NE(it2, rdata.texts().end());
292
293 it2 = std::find(rdata.texts().begin(), rdata.texts().end(), "boolean");
294 EXPECT_NE(it2, rdata.texts().end());
295 }
296
297 } // namespace discovery
298 } // namespace openscreen
299