You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
17 KiB
470 lines
17 KiB
// 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/mdns/mdns_writer.h"
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "discovery/mdns/testing/mdns_test_util.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace openscreen {
|
|
namespace discovery {
|
|
|
|
using testing::ElementsAreArray;
|
|
|
|
namespace {
|
|
|
|
constexpr std::chrono::seconds kTtl{120};
|
|
|
|
template <class T>
|
|
void TestWriteEntrySucceeds(const T& entry,
|
|
const uint8_t* expected_data,
|
|
size_t expected_size) {
|
|
std::vector<uint8_t> buffer(expected_size);
|
|
MdnsWriter writer(buffer.data(), buffer.size());
|
|
EXPECT_TRUE(writer.Write(entry));
|
|
EXPECT_EQ(writer.remaining(), UINT64_C(0));
|
|
EXPECT_THAT(buffer, ElementsAreArray(expected_data, expected_size));
|
|
}
|
|
|
|
template <class T>
|
|
void TestWriteEntryInsufficientBuffer(const T& entry) {
|
|
std::vector<uint8_t> buffer(entry.MaxWireSize() - 1);
|
|
MdnsWriter writer(buffer.data(), buffer.size());
|
|
EXPECT_FALSE(writer.Write(entry));
|
|
// There should be no side effects for failing to write an entry. The
|
|
// underlying pointer should not have changed.
|
|
EXPECT_EQ(writer.offset(), UINT64_C(0));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResult[] = {
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00
|
|
};
|
|
// clang-format on
|
|
uint8_t result[sizeof(kExpectedResult)];
|
|
MdnsWriter writer(result, sizeof(kExpectedResult));
|
|
ASSERT_TRUE(writer.Write(DomainName{"testing", "local"}));
|
|
EXPECT_EQ(0UL, writer.remaining());
|
|
EXPECT_EQ(0, memcmp(kExpectedResult, result, sizeof(result)));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName_CompressedMessage) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResultCompressed[] = {
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x06, 'p', 'r', 'e', 'f', 'i', 'x',
|
|
0xC0, 0x08, // byte 8
|
|
0x03, 'n', 'e', 'w',
|
|
0xC0, 0x0F, // byte 15
|
|
0xC0, 0x0F, // byte 15
|
|
};
|
|
// clang-format on
|
|
uint8_t result[sizeof(kExpectedResultCompressed)];
|
|
MdnsWriter writer(result, sizeof(kExpectedResultCompressed));
|
|
ASSERT_TRUE(writer.Write(DomainName{"testing", "local"}));
|
|
ASSERT_TRUE(writer.Write(DomainName{"prefix", "local"}));
|
|
ASSERT_TRUE(writer.Write(DomainName{"new", "prefix", "local"}));
|
|
ASSERT_TRUE(writer.Write(DomainName{"prefix", "local"}));
|
|
EXPECT_EQ(0UL, writer.remaining());
|
|
EXPECT_THAT(std::vector<uint8_t>(result, result + sizeof(result)),
|
|
ElementsAreArray(kExpectedResultCompressed));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName_NotEnoughSpace) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResultCompressed[] = {
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x09, 'd', 'i', 'f', 'f', 'e', 'r', 'e', 'n', 't',
|
|
0x06, 'd', 'o', 'm', 'a', 'i', 'n',
|
|
0x00
|
|
};
|
|
// clang-format on
|
|
uint8_t result[sizeof(kExpectedResultCompressed)];
|
|
MdnsWriter writer(result, sizeof(kExpectedResultCompressed));
|
|
ASSERT_TRUE(writer.Write(DomainName{"testing", "local"}));
|
|
// Not enough space to write this domain name. Failure to write it must not
|
|
// affect correct successful write of the next domain name.
|
|
ASSERT_FALSE(writer.Write(DomainName{"a", "different", "domain"}));
|
|
ASSERT_TRUE(writer.Write(DomainName{"different", "domain"}));
|
|
EXPECT_EQ(0UL, writer.remaining());
|
|
EXPECT_THAT(std::vector<uint8_t>(result, result + sizeof(result)),
|
|
ElementsAreArray(kExpectedResultCompressed));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName_Long) {
|
|
constexpr char kLongLabel[] =
|
|
"12345678901234567890123456789012345678901234567890";
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResult[] = {
|
|
0x32, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
|
|
'4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
|
|
0x32, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
|
|
'4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
|
|
0x32, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
|
|
'4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
|
|
0x32, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
|
|
'4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
|
|
0x00,
|
|
};
|
|
// clang-format on
|
|
DomainName name{kLongLabel, kLongLabel, kLongLabel, kLongLabel};
|
|
uint8_t result[sizeof(kExpectedResult)];
|
|
MdnsWriter writer(result, sizeof(kExpectedResult));
|
|
ASSERT_TRUE(writer.Write(name));
|
|
EXPECT_EQ(0UL, writer.remaining());
|
|
EXPECT_EQ(0, memcmp(kExpectedResult, result, sizeof(result)));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName_Empty) {
|
|
DomainName name;
|
|
uint8_t result[256];
|
|
MdnsWriter writer(result, sizeof(result));
|
|
EXPECT_FALSE(writer.Write(name));
|
|
// The writer should not have moved its internal pointer when it fails to
|
|
// write. It should fail without any side effects.
|
|
EXPECT_EQ(0u, writer.offset());
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteDomainName_NoCompressionForBigOffsets) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResultCompressed[] = {
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
};
|
|
// clang-format on
|
|
|
|
DomainName name{"testing", "local"};
|
|
// Maximum supported value for label pointer offset is 0x3FFF.
|
|
// Labels written into a buffer at greater offsets must not
|
|
// produce compression label pointers.
|
|
std::vector<uint8_t> buffer(0x4000 + sizeof(kExpectedResultCompressed));
|
|
{
|
|
MdnsWriter writer(buffer.data(), buffer.size());
|
|
writer.Skip(0x4000);
|
|
ASSERT_TRUE(writer.Write(name));
|
|
ASSERT_TRUE(writer.Write(name));
|
|
EXPECT_EQ(0UL, writer.remaining());
|
|
}
|
|
buffer.erase(buffer.begin(), buffer.begin() + 0x4000);
|
|
EXPECT_THAT(buffer, ElementsAreArray(kExpectedResultCompressed));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteRawRecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x08, // RDLENGTH = 8 bytes
|
|
0x05, 'c', 'n', 'a', 'm', 'e', 0xc0, 0x00,
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
RawRecordRdata(kExpectedRdata + 2, sizeof(kExpectedRdata) - 2),
|
|
kExpectedRdata, sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteRawRecordRdata_InsufficientBuffer) {
|
|
// clang-format off
|
|
constexpr uint8_t kRawRdata[] = {
|
|
0x05, 'c', 'n', 'a', 'm', 'e', 0xc0, 0x00,
|
|
};
|
|
// clang-format on
|
|
TestWriteEntryInsufficientBuffer(
|
|
RawRecordRdata(kRawRdata, sizeof(kRawRdata)));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteSrvRecordRdata) {
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x15, // RDLENGTH = 21
|
|
0x00, 0x05, // PRIORITY = 5
|
|
0x00, 0x06, // WEIGHT = 6
|
|
0x1f, 0x49, // PORT = 8009
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l', 0x00,
|
|
};
|
|
TestWriteEntrySucceeds(
|
|
SrvRecordRdata(5, 6, 8009, DomainName{"testing", "local"}),
|
|
kExpectedRdata, sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteSrvRecordRdata_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(
|
|
SrvRecordRdata(5, 6, 8009, DomainName{"testing", "local"}));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteARecordRdata) {
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x4, // RDLENGTH = 4
|
|
0x08, 0x08, 0x08, 0x08, // ADDRESS = 8.8.8.8
|
|
};
|
|
TestWriteEntrySucceeds(ARecordRdata(IPAddress{8, 8, 8, 8}), kExpectedRdata,
|
|
sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteARecordRdata_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(ARecordRdata(IPAddress{8, 8, 8, 8}));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteAAAARecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x10, // RDLENGTH = 16
|
|
// ADDRESS = FE80:0000:0000:0000:0202:B3FF:FE1E:8329
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x02, 0x02, 0xb3, 0xff, 0xfe, 0x1e, 0x83, 0x29,
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
AAAARecordRdata(IPAddress(IPAddress::Version::kV6, kExpectedRdata + 2)),
|
|
kExpectedRdata, sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteAAAARecordRdata_InsufficientBuffer) {
|
|
// clang-format off
|
|
constexpr uint16_t kAAAARdata[] = {
|
|
// ADDRESS = FE80:0000:0000:0000:0202:B3FF:FE1E:8329
|
|
0xfe80, 0x0000, 0x0000, 0x0000,
|
|
0x0202, 0xb3ff, 0xfe1e, 0x8329,
|
|
};
|
|
// clang-format on
|
|
TestWriteEntryInsufficientBuffer(AAAARecordRdata(IPAddress(kAAAARdata)));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteNSECRecordRdata) {
|
|
const DomainName domain{"testing", "local"};
|
|
NsecRecordRdata(DomainName{"mydevice", "testing", "local"}, DnsType::kA,
|
|
DnsType::kTXT, DnsType::kSRV, DnsType::kNSEC);
|
|
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x20, // RDLENGTH = 32
|
|
0x08, 'm', 'y', 'd', 'e', 'v', 'i', 'c', 'e',
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
// It takes 8 bytes to encode the kA and kSRV records because:
|
|
// - Both record types have value less than 256, so they are both in window
|
|
// block 1.
|
|
// - The bitmap length for this block is always a single byte
|
|
// - DnsTypes have the following values:
|
|
// - kA = 1 (encoded in byte 1)
|
|
// kTXT = 16 (encoded in byte 3)
|
|
// - kSRV = 33 (encoded in byte 5)
|
|
// - kNSEC = 47 (encoded in 6 bytes)
|
|
// - The largest of these is 47, so 6 bytes are needed to encode this data.
|
|
// So the full encoded version is:
|
|
// 00000000 00000110 01000000 00000000 10000000 00000000 0100000 00000001
|
|
// |window| | size | | 0-7 | | 8-15 | |16-23 | |24-31 | |32-39 | |40-47 |
|
|
0x00, 0x06, 0x40, 0x00, 0x80, 0x00, 0x40, 0x01
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
NsecRecordRdata(DomainName{"mydevice", "testing", "local"}, DnsType::kA,
|
|
DnsType::kTXT, DnsType::kSRV, DnsType::kNSEC),
|
|
kExpectedRdata, sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteNSECRecordRdata_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(
|
|
NsecRecordRdata(DomainName{"mydevice", "testing", "local"}, DnsType::kA,
|
|
DnsType::kTXT, DnsType::kSRV, DnsType::kNSEC));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WritePtrRecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x18, // RDLENGTH = 24
|
|
0x08, 'm', 'y', 'd', 'e', 'v', 'i', 'c', 'e',
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
PtrRecordRdata(DomainName{"mydevice", "testing", "local"}),
|
|
kExpectedRdata, sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WritePtrRecordRdata_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(
|
|
PtrRecordRdata(DomainName{"mydevice", "testing", "local"}));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteTxtRecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x0C, // RDLENGTH = 12
|
|
0x05, 'f', 'o', 'o', '=', '1',
|
|
0x05, 'b', 'a', 'r', '=', '2',
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(MakeTxtRecord({"foo=1", "bar=2"}), kExpectedRdata,
|
|
sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteTxtRecordRdata_Empty) {
|
|
constexpr uint8_t kExpectedRdata[] = {
|
|
0x00, 0x01, // RDLENGTH = 1
|
|
0x00, // empty string
|
|
};
|
|
TestWriteEntrySucceeds(TxtRecordRdata(), kExpectedRdata,
|
|
sizeof(kExpectedRdata));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteTxtRecordRdata_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(MakeTxtRecord({"foo=1", "bar=2"}));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsRecord_ARecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResult[] = {
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x00, 0x01, // TYPE = A (1)
|
|
0x80, 0x01, // CLASS = IN (1) | CACHE_FLUSH_BIT
|
|
0x00, 0x00, 0x00, 0x78, // TTL = 120 seconds
|
|
0x00, 0x04, // RDLENGTH = 4 bytes
|
|
0xac, 0x00, 0x00, 0x01, // 172.0.0.1
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(MdnsRecord(DomainName{"testing", "local"}, DnsType::kA,
|
|
DnsClass::kIN, RecordType::kUnique, kTtl,
|
|
ARecordRdata(IPAddress{172, 0, 0, 1})),
|
|
kExpectedResult, sizeof(kExpectedResult));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsRecord_PtrRecordRdata) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResult[] = {
|
|
0x08, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e',
|
|
0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x00, 0x0c, // TYPE = PTR (12)
|
|
0x00, 0x01, // CLASS = IN (1)
|
|
0x00, 0x00, 0x00, 0x78, // TTL = 120 seconds
|
|
0x00, 0x02, // RDLENGTH = 2 bytes
|
|
0xc0, 0x09, // Domain name label pointer to byte
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
MdnsRecord(DomainName{"_service", "testing", "local"}, DnsType::kPTR,
|
|
DnsClass::kIN, RecordType::kShared, kTtl,
|
|
PtrRecordRdata(DomainName{"testing", "local"})),
|
|
kExpectedResult, sizeof(kExpectedResult));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsRecord_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(MdnsRecord(
|
|
DomainName{"testing", "local"}, DnsType::kA, DnsClass::kIN,
|
|
RecordType::kUnique, kTtl, ARecordRdata(IPAddress{172, 0, 0, 1})));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsQuestion) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedResult[] = {
|
|
0x04, 'w', 'i', 'r', 'e',
|
|
0x06, 'f', 'o', 'r', 'm', 'a', 't',
|
|
0x05, 'l', 'o', 'c', 'a', 'l',
|
|
0x00,
|
|
0x00, 0x0c, // TYPE = PTR (12)
|
|
0x80, 0x01, // CLASS = IN (1) | UNICAST_BIT
|
|
};
|
|
// clang-format on
|
|
TestWriteEntrySucceeds(
|
|
MdnsQuestion(DomainName{"wire", "format", "local"}, DnsType::kPTR,
|
|
DnsClass::kIN, ResponseType::kUnicast),
|
|
kExpectedResult, sizeof(kExpectedResult));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsQuestion_InsufficientBuffer) {
|
|
TestWriteEntryInsufficientBuffer(
|
|
MdnsQuestion(DomainName{"wire", "format", "local"}, DnsType::kPTR,
|
|
DnsClass::kIN, ResponseType::kUnicast));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsMessage) {
|
|
// clang-format off
|
|
constexpr uint8_t kExpectedMessage[] = {
|
|
0x00, 0x01, // ID = 1
|
|
0x00, 0x00, // FLAGS = None
|
|
0x00, 0x01, // Question count
|
|
0x00, 0x00, // Answer count
|
|
0x00, 0x01, // Authority count
|
|
0x00, 0x00, // Additional count
|
|
// Question
|
|
0x08, 'q', 'u', 'e', 's', 't', 'i', 'o', 'n',
|
|
0x00,
|
|
0x00, 0x0c, // TYPE = PTR (12)
|
|
0x00, 0x01, // CLASS = IN (1)
|
|
// Authority Record
|
|
0x04, 'a', 'u', 't', 'h',
|
|
0x00,
|
|
0x00, 0x10, // TYPE = TXT (16)
|
|
0x00, 0x01, // CLASS = IN (1)
|
|
0x00, 0x00, 0x00, 0x78, // TTL = 120 seconds
|
|
0x00, 0x0c, // RDLENGTH = 12 bytes
|
|
0x05, 'f', 'o', 'o', '=', '1',
|
|
0x05, 'b', 'a', 'r', '=', '2',
|
|
};
|
|
// clang-format on
|
|
MdnsQuestion question(DomainName{"question"}, DnsType::kPTR, DnsClass::kIN,
|
|
ResponseType::kMulticast);
|
|
|
|
MdnsRecord auth_record(DomainName{"auth"}, DnsType::kTXT, DnsClass::kIN,
|
|
RecordType::kShared, kTtl,
|
|
MakeTxtRecord({"foo=1", "bar=2"}));
|
|
|
|
MdnsMessage message(1, MessageType::Query);
|
|
message.AddQuestion(question);
|
|
message.AddAuthorityRecord(auth_record);
|
|
|
|
std::vector<uint8_t> buffer(sizeof(kExpectedMessage));
|
|
MdnsWriter writer(buffer.data(), buffer.size());
|
|
EXPECT_TRUE(writer.Write(message));
|
|
EXPECT_EQ(writer.remaining(), UINT64_C(0));
|
|
EXPECT_THAT(buffer, ElementsAreArray(kExpectedMessage));
|
|
}
|
|
|
|
TEST(MdnsWriterTest, WriteMdnsMessage_InsufficientBuffer) {
|
|
MdnsQuestion question(DomainName{"question"}, DnsType::kPTR, DnsClass::kIN,
|
|
ResponseType::kMulticast);
|
|
|
|
MdnsRecord auth_record(DomainName{"auth"}, DnsType::kTXT, DnsClass::kIN,
|
|
RecordType::kShared, kTtl,
|
|
MakeTxtRecord({"foo=1", "bar=2"}));
|
|
|
|
MdnsMessage message(1, MessageType::Query);
|
|
message.AddQuestion(question);
|
|
message.AddAuthorityRecord(auth_record);
|
|
TestWriteEntryInsufficientBuffer(message);
|
|
}
|
|
|
|
} // namespace discovery
|
|
} // namespace openscreen
|