blob: 9b1fd66e7b3162c0743f42259043d6cbfca86bc6 [file] [log] [blame]
Hungming Chenf9cd4eb2019-08-06 20:55:28 +09001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18#define LOG_TAG "resolv_gold_test"
19
Hungming Chen21c0f832019-09-20 18:38:47 +080020#include <android-base/file.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090021#include <gmock/gmock-matchers.h>
Hungming Chen21c0f832019-09-20 18:38:47 +080022#include <google/protobuf/text_format.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090023#include <gtest/gtest.h>
24
25#include "dns_responder/dns_responder.h"
26#include "getaddrinfo.h"
Hungming Chen21c0f832019-09-20 18:38:47 +080027#include "golddata.pb.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090028#include "resolv_cache.h"
29#include "resolv_test_utils.h"
30
31namespace android {
32namespace net {
33using android::net::NetworkDnsEventReported;
34using android::netdutils::ScopedAddrinfo;
35
Hungming Chen21c0f832019-09-20 18:38:47 +080036// Fixture test class definition.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090037class TestBase : public ::testing::Test {
38 protected:
39 void SetUp() override {
40 // Create cache for test
41 resolv_create_cache_for_net(TEST_NETID);
42 }
43
44 void TearDown() override {
45 // Delete cache for test
46 resolv_delete_cache_for_net(TEST_NETID);
47 }
48
49 int SetResolvers() {
50 const std::vector<std::string> servers = {test::kDefaultListenAddr};
51 const std::vector<std::string> domains = {"example.com"};
52 return resolv_set_nameservers(TEST_NETID, servers, domains, kParams);
53 }
54
Hungming Chen21c0f832019-09-20 18:38:47 +080055 const std::string kTestPath = android::base::GetExecutableDirectory();
56 const std::string kTestDataPath = kTestPath + "/testdata/";
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090057 static constexpr res_params kParams = {
58 .sample_validity = 300,
59 .success_threshold = 25,
60 .min_samples = 8,
61 .max_samples = 8,
62 .base_timeout_msec = 1000,
63 .retry_count = 2,
64 };
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090065 static constexpr android_net_context kNetcontext = {
66 .app_netid = TEST_NETID,
67 .app_mark = MARK_UNSET,
68 .dns_netid = TEST_NETID,
69 .dns_mark = MARK_UNSET,
70 .uid = NET_CONTEXT_INVALID_UID,
71 };
72};
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090073class ResolvGetAddrInfo : public TestBase {};
74
Hungming Chen21c0f832019-09-20 18:38:47 +080075// Parameterized test class definition.
76class ResolvGoldTest : public TestBase, public ::testing::WithParamInterface<std::string> {};
77
78// GetAddrInfo tests.
79INSTANTIATE_TEST_SUITE_P(GetAddrInfo, ResolvGoldTest,
80 ::testing::Values(std::string("getaddrinfo.topsite.google.pbtxt")),
81 [](const ::testing::TestParamInfo<std::string>& info) {
82 std::string name = info.param;
83 std::replace_if(
84 std::begin(name), std::end(name),
85 [](char ch) { return !std::isalnum(ch); }, '_');
86 return name;
87 });
88
89// Fixture tests.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090090TEST_F(ResolvGetAddrInfo, RemovePacketMapping) {
91 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
92 ASSERT_TRUE(dns.startServer());
93 ASSERT_EQ(0, SetResolvers());
94
95 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
96
97 addrinfo* res = nullptr;
98 const addrinfo hints = {.ai_family = AF_INET};
99 NetworkDnsEventReported event;
100 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
101 ScopedAddrinfo result(res);
102 ASSERT_NE(nullptr, result);
103 ASSERT_EQ(0, rv);
104 EXPECT_EQ("1.2.3.4", ToString(result));
105
106 // Remove existing DNS record.
107 dns.removeMappingBinaryPacket(kHelloExampleComQueryV4);
108
109 // Expect to have no answer in DNS query result.
110 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
111 result.reset(res);
112 ASSERT_EQ(nullptr, result);
113 ASSERT_EQ(EAI_NODATA, rv);
114}
115
116TEST_F(ResolvGetAddrInfo, ReplacePacketMapping) {
117 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
118 ASSERT_TRUE(dns.startServer());
119 ASSERT_EQ(0, SetResolvers());
120
121 // Register the record which uses IPv4 address 1.2.3.4.
122 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
123
124 // Expect that the DNS query returns IPv4 address 1.2.3.4.
125 addrinfo* res = nullptr;
126 const addrinfo hints = {.ai_family = AF_INET};
127 NetworkDnsEventReported event;
128 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
129 ScopedAddrinfo result(res);
130 ASSERT_NE(nullptr, result);
131 ASSERT_EQ(0, rv);
132 EXPECT_EQ("1.2.3.4", ToString(result));
133
134 // Replace the registered record with a record which uses new IPv4 address 5.6.7.8.
135 std::vector<uint8_t> newHelloExampleComResponseV4 = {
136 /* Header */
137 0x00, 0x00, /* Transaction ID: 0x0000 */
138 0x81, 0x80, /* Flags: qr rd ra */
139 0x00, 0x01, /* Questions: 1 */
140 0x00, 0x01, /* Answer RRs: 1 */
141 0x00, 0x00, /* Authority RRs: 0 */
142 0x00, 0x00, /* Additional RRs: 0 */
143 /* Queries */
144 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
145 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
146 0x00, 0x01, /* Type: A */
147 0x00, 0x01, /* Class: IN */
148 /* Answers */
149 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
150 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
151 0x00, 0x01, /* Type: A */
152 0x00, 0x01, /* Class: IN */
153 0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
154 0x00, 0x04, /* Data length: 4 */
155 0x05, 0x06, 0x07, 0x08 /* Address: 5.6.7.8 */
156 };
157 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, newHelloExampleComResponseV4);
158
159 // Expect that DNS query returns new IPv4 address 5.6.7.8.
160 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
161 result.reset(res);
162 ASSERT_NE(nullptr, result);
163 ASSERT_EQ(0, rv);
164 EXPECT_EQ("5.6.7.8", ToString(result));
165}
166
Hungming Chen21c0f832019-09-20 18:38:47 +0800167// Parameterized tests.
168TEST_P(ResolvGoldTest, GoldData) {
169 const auto& testFile = GetParam();
170
171 // Convert the testing configuration from .pbtxt file to proto.
172 std::string file_content;
173 ASSERT_TRUE(android::base::ReadFileToString(kTestDataPath + testFile, &file_content))
174 << strerror(errno);
175 android::net::GoldTest goldtest;
176 ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(file_content, &goldtest));
177 ASSERT_EQ(android::net::CallType::CALL_GETADDRINFO, goldtest.config().call());
178 ASSERT_TRUE(goldtest.config().has_addrinfo());
179
180 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
181 ASSERT_TRUE(dns.startServer());
182 ASSERT_EQ(0, SetResolvers());
183
184 // Register packet mapping (query, response) from proto.
185 for (const auto& m : goldtest.packet_mapping()) {
186 // Convert string to bytes because .proto type "bytes" is "string" type in C++.
187 // See also the section "Scalar Value Types" in "Language Guide (proto3)".
188 dns.addMappingBinaryPacket(std::vector<uint8_t>(m.query().begin(), m.query().end()),
189 std::vector<uint8_t>(m.response().begin(), m.response().end()));
190 }
191
192 addrinfo* res = nullptr;
193 const auto& args = goldtest.config().addrinfo();
194 const addrinfo hints = {
Hungming Chen21c0f832019-09-20 18:38:47 +0800195 // Clear the flag AI_ADDRCONFIG to avoid flaky test because AI_ADDRCONFIG looks at
196 // whether connectivity is available. It makes that the resolver may send only A
197 // or AAAA DNS query per connectivity even AF_UNSPEC has been assigned. See also
198 // have_ipv6() and have_ipv4() in packages/modules/DnsResolver/getaddrinfo.cpp.
199 // TODO: Consider keeping the configuration flag AI_ADDRCONFIG once the unit
200 // test can treat the IPv4 and IPv6 connectivity.
201 .ai_flags = args.ai_flags() & ~AI_ADDRCONFIG,
Nick Desaulniersdffafb72019-11-11 16:17:57 -0800202 .ai_family = args.family(),
203 .ai_socktype = args.socktype(),
204 .ai_protocol = args.protocol(),
Hungming Chen21c0f832019-09-20 18:38:47 +0800205 };
206 NetworkDnsEventReported event;
207 int rv = resolv_getaddrinfo(args.host().c_str(), nullptr, &hints, &kNetcontext, &res, &event);
208 ScopedAddrinfo result(res);
209 ASSERT_EQ(goldtest.result().return_code(), rv);
210
211 if (goldtest.result().return_code() != GT_EAI_NO_ERROR) {
212 ASSERT_EQ(nullptr, result);
213 } else {
214 ASSERT_NE(nullptr, result);
215 const auto& addresses = goldtest.result().addresses();
216 EXPECT_THAT(ToStrings(result),
217 ::testing::UnorderedElementsAreArray(
218 std::vector<std::string>(addresses.begin(), addresses.end())));
219 }
220 EXPECT_EQ((hints.ai_family == AF_UNSPEC) ? 2U : 1U, GetNumQueries(dns, args.host().c_str()));
221}
222
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900223} // end of namespace net
224} // end of namespace android