xref: /aosp_15_r20/external/openscreen/discovery/mdns/mdns_sender_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_sender.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <memory>
8*3f982cf4SFabien Sanglard #include <vector>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_records.h"
11*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
12*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
13*3f982cf4SFabien Sanglard #include "platform/test/fake_udp_socket.h"
14*3f982cf4SFabien Sanglard #include "platform/test/mock_udp_socket.h"
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard namespace openscreen {
17*3f982cf4SFabien Sanglard namespace discovery {
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard using testing::_;
20*3f982cf4SFabien Sanglard using testing::Args;
21*3f982cf4SFabien Sanglard using testing::Return;
22*3f982cf4SFabien Sanglard using testing::StrictMock;
23*3f982cf4SFabien Sanglard using testing::WithArgs;
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard namespace {
26*3f982cf4SFabien Sanglard 
ACTION_P(VoidPointerMatchesBytes,expected_data)27*3f982cf4SFabien Sanglard ACTION_P(VoidPointerMatchesBytes, expected_data) {
28*3f982cf4SFabien Sanglard   const uint8_t* actual_data = static_cast<const uint8_t*>(arg0);
29*3f982cf4SFabien Sanglard   for (size_t i = 0; i < expected_data.size(); ++i) {
30*3f982cf4SFabien Sanglard     EXPECT_EQ(actual_data[i], expected_data[i]);
31*3f982cf4SFabien Sanglard   }
32*3f982cf4SFabien Sanglard }
33*3f982cf4SFabien Sanglard 
34*3f982cf4SFabien Sanglard }  // namespace
35*3f982cf4SFabien Sanglard 
36*3f982cf4SFabien Sanglard class MdnsSenderTest : public testing::Test {
37*3f982cf4SFabien Sanglard  public:
MdnsSenderTest()38*3f982cf4SFabien Sanglard   MdnsSenderTest()
39*3f982cf4SFabien Sanglard       : a_question_(DomainName{"testing", "local"},
40*3f982cf4SFabien Sanglard                     DnsType::kA,
41*3f982cf4SFabien Sanglard                     DnsClass::kIN,
42*3f982cf4SFabien Sanglard                     ResponseType::kMulticast),
43*3f982cf4SFabien Sanglard         a_record_(DomainName{"testing", "local"},
44*3f982cf4SFabien Sanglard                   DnsType::kA,
45*3f982cf4SFabien Sanglard                   DnsClass::kIN,
46*3f982cf4SFabien Sanglard                   RecordType::kShared,
47*3f982cf4SFabien Sanglard                   std::chrono::seconds(120),
48*3f982cf4SFabien Sanglard                   ARecordRdata(IPAddress{172, 0, 0, 1})),
49*3f982cf4SFabien Sanglard         query_message_(1, MessageType::Query),
50*3f982cf4SFabien Sanglard         response_message_(1, MessageType::Response),
51*3f982cf4SFabien Sanglard         ipv4_multicast_endpoint_{
52*3f982cf4SFabien Sanglard             .address = IPAddress(kDefaultMulticastGroupIPv4),
53*3f982cf4SFabien Sanglard             .port = kDefaultMulticastPort},
54*3f982cf4SFabien Sanglard         ipv6_multicast_endpoint_{
55*3f982cf4SFabien Sanglard             .address = IPAddress(kDefaultMulticastGroupIPv6),
56*3f982cf4SFabien Sanglard             .port = kDefaultMulticastPort} {
57*3f982cf4SFabien Sanglard     query_message_.AddQuestion(a_question_);
58*3f982cf4SFabien Sanglard     response_message_.AddAnswer(a_record_);
59*3f982cf4SFabien Sanglard   }
60*3f982cf4SFabien Sanglard 
61*3f982cf4SFabien Sanglard  protected:
62*3f982cf4SFabien Sanglard   // clang-format off
63*3f982cf4SFabien Sanglard   const std::vector<uint8_t> kQueryBytes = {
64*3f982cf4SFabien Sanglard       0x00, 0x01,  // ID = 1
65*3f982cf4SFabien Sanglard       0x00, 0x00,  // FLAGS = None
66*3f982cf4SFabien Sanglard       0x00, 0x01,  // Question count
67*3f982cf4SFabien Sanglard       0x00, 0x00,  // Answer count
68*3f982cf4SFabien Sanglard       0x00, 0x00,  // Authority count
69*3f982cf4SFabien Sanglard       0x00, 0x00,  // Additional count
70*3f982cf4SFabien Sanglard       // Question
71*3f982cf4SFabien Sanglard       0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
72*3f982cf4SFabien Sanglard       0x05, 'l', 'o', 'c', 'a', 'l',
73*3f982cf4SFabien Sanglard       0x00,
74*3f982cf4SFabien Sanglard       0x00, 0x01,  // TYPE = A (1)
75*3f982cf4SFabien Sanglard       0x00, 0x01,  // CLASS = IN (1)
76*3f982cf4SFabien Sanglard   };
77*3f982cf4SFabien Sanglard 
78*3f982cf4SFabien Sanglard   const std::vector<uint8_t> kResponseBytes = {
79*3f982cf4SFabien Sanglard       0x00, 0x01,  // ID = 1
80*3f982cf4SFabien Sanglard       0x84, 0x00,  // FLAGS = AA | RESPONSE
81*3f982cf4SFabien Sanglard       0x00, 0x00,  // Question count
82*3f982cf4SFabien Sanglard       0x00, 0x01,  // Answer count
83*3f982cf4SFabien Sanglard       0x00, 0x00,  // Authority count
84*3f982cf4SFabien Sanglard       0x00, 0x00,  // Additional count
85*3f982cf4SFabien Sanglard       // Answer
86*3f982cf4SFabien Sanglard       0x07, 't', 'e', 's', 't', 'i', 'n', 'g',
87*3f982cf4SFabien Sanglard       0x05, 'l', 'o', 'c', 'a', 'l',
88*3f982cf4SFabien Sanglard       0x00,
89*3f982cf4SFabien Sanglard       0x00, 0x01,              // TYPE = A (1)
90*3f982cf4SFabien Sanglard       0x00, 0x01,              // CLASS = IN (1)
91*3f982cf4SFabien Sanglard       0x00, 0x00, 0x00, 0x78,  // TTL = 120 seconds
92*3f982cf4SFabien Sanglard       0x00, 0x04,              // RDLENGTH = 4 bytes
93*3f982cf4SFabien Sanglard       0xac, 0x00, 0x00, 0x01,  // 172.0.0.1
94*3f982cf4SFabien Sanglard   };
95*3f982cf4SFabien Sanglard   // clang-format on
96*3f982cf4SFabien Sanglard 
97*3f982cf4SFabien Sanglard   MdnsQuestion a_question_;
98*3f982cf4SFabien Sanglard   MdnsRecord a_record_;
99*3f982cf4SFabien Sanglard   MdnsMessage query_message_;
100*3f982cf4SFabien Sanglard   MdnsMessage response_message_;
101*3f982cf4SFabien Sanglard   IPEndpoint ipv4_multicast_endpoint_;
102*3f982cf4SFabien Sanglard   IPEndpoint ipv6_multicast_endpoint_;
103*3f982cf4SFabien Sanglard };
104*3f982cf4SFabien Sanglard 
TEST_F(MdnsSenderTest,SendMulticast)105*3f982cf4SFabien Sanglard TEST_F(MdnsSenderTest, SendMulticast) {
106*3f982cf4SFabien Sanglard   StrictMock<MockUdpSocket> socket;
107*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, IsIPv4()).WillRepeatedly(Return(true));
108*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, IsIPv6()).WillRepeatedly(Return(true));
109*3f982cf4SFabien Sanglard   MdnsSender sender(&socket);
110*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, SendMessage(_, kQueryBytes.size(), _))
111*3f982cf4SFabien Sanglard       .WillOnce(WithArgs<0>(VoidPointerMatchesBytes(kQueryBytes)));
112*3f982cf4SFabien Sanglard   EXPECT_EQ(sender.SendMulticast(query_message_), Error::Code::kNone);
113*3f982cf4SFabien Sanglard }
114*3f982cf4SFabien Sanglard 
TEST_F(MdnsSenderTest,SendUnicastIPv4)115*3f982cf4SFabien Sanglard TEST_F(MdnsSenderTest, SendUnicastIPv4) {
116*3f982cf4SFabien Sanglard   IPEndpoint endpoint{.address = IPAddress{192, 168, 1, 1}, .port = 31337};
117*3f982cf4SFabien Sanglard 
118*3f982cf4SFabien Sanglard   StrictMock<MockUdpSocket> socket;
119*3f982cf4SFabien Sanglard   MdnsSender sender(&socket);
120*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, SendMessage(_, kResponseBytes.size(), _))
121*3f982cf4SFabien Sanglard       .WillOnce(WithArgs<0>(VoidPointerMatchesBytes(kResponseBytes)));
122*3f982cf4SFabien Sanglard   EXPECT_EQ(sender.SendMessage(response_message_, endpoint),
123*3f982cf4SFabien Sanglard             Error::Code::kNone);
124*3f982cf4SFabien Sanglard }
125*3f982cf4SFabien Sanglard 
TEST_F(MdnsSenderTest,SendUnicastIPv6)126*3f982cf4SFabien Sanglard TEST_F(MdnsSenderTest, SendUnicastIPv6) {
127*3f982cf4SFabien Sanglard   constexpr uint16_t kIPv6AddressHextets[] = {
128*3f982cf4SFabien Sanglard       0xfe80, 0x0000, 0x0000, 0x0000, 0x0202, 0xb3ff, 0xfe1e, 0x8329,
129*3f982cf4SFabien Sanglard   };
130*3f982cf4SFabien Sanglard   IPEndpoint endpoint{.address = IPAddress(kIPv6AddressHextets), .port = 31337};
131*3f982cf4SFabien Sanglard 
132*3f982cf4SFabien Sanglard   StrictMock<MockUdpSocket> socket;
133*3f982cf4SFabien Sanglard   MdnsSender sender(&socket);
134*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, SendMessage(_, kResponseBytes.size(), _))
135*3f982cf4SFabien Sanglard       .WillOnce(WithArgs<0>(VoidPointerMatchesBytes(kResponseBytes)));
136*3f982cf4SFabien Sanglard   EXPECT_EQ(sender.SendMessage(response_message_, endpoint),
137*3f982cf4SFabien Sanglard             Error::Code::kNone);
138*3f982cf4SFabien Sanglard }
139*3f982cf4SFabien Sanglard 
TEST_F(MdnsSenderTest,MessageTooBig)140*3f982cf4SFabien Sanglard TEST_F(MdnsSenderTest, MessageTooBig) {
141*3f982cf4SFabien Sanglard   MdnsMessage big_message_(1, MessageType::Query);
142*3f982cf4SFabien Sanglard   for (size_t i = 0; i < 100; ++i) {
143*3f982cf4SFabien Sanglard     big_message_.AddQuestion(a_question_);
144*3f982cf4SFabien Sanglard     big_message_.AddAnswer(a_record_);
145*3f982cf4SFabien Sanglard   }
146*3f982cf4SFabien Sanglard 
147*3f982cf4SFabien Sanglard   StrictMock<MockUdpSocket> socket;
148*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, IsIPv4()).WillRepeatedly(Return(true));
149*3f982cf4SFabien Sanglard   EXPECT_CALL(socket, IsIPv6()).WillRepeatedly(Return(true));
150*3f982cf4SFabien Sanglard   MdnsSender sender(&socket);
151*3f982cf4SFabien Sanglard   EXPECT_EQ(sender.SendMulticast(big_message_),
152*3f982cf4SFabien Sanglard             Error::Code::kInsufficientBuffer);
153*3f982cf4SFabien Sanglard }
154*3f982cf4SFabien Sanglard 
TEST_F(MdnsSenderTest,ReturnsErrorOnSocketFailure)155*3f982cf4SFabien Sanglard TEST_F(MdnsSenderTest, ReturnsErrorOnSocketFailure) {
156*3f982cf4SFabien Sanglard   FakeUdpSocket::MockClient socket_client;
157*3f982cf4SFabien Sanglard   FakeUdpSocket socket(nullptr, &socket_client);
158*3f982cf4SFabien Sanglard   MdnsSender sender(&socket);
159*3f982cf4SFabien Sanglard   Error error = Error(Error::Code::kConnectionFailed, "error message");
160*3f982cf4SFabien Sanglard   socket.EnqueueSendResult(error);
161*3f982cf4SFabien Sanglard   EXPECT_CALL(socket_client, OnSendError(_, error)).Times(1);
162*3f982cf4SFabien Sanglard   EXPECT_EQ(sender.SendMulticast(query_message_), Error::Code::kNone);
163*3f982cf4SFabien Sanglard   EXPECT_EQ(socket.send_queue_size(), size_t{0});
164*3f982cf4SFabien Sanglard }
165*3f982cf4SFabien Sanglard 
166*3f982cf4SFabien Sanglard }  // namespace discovery
167*3f982cf4SFabien Sanglard }  // namespace openscreen
168