1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 SUSE LINUX GmbH
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
14 #include "common/dns_resolve.h"
15 #include "test/common/dns_messages.h"
17 #include "common/debug.h"
18 #include "gmock/gmock.h"
25 #define dout_subsys ceph_subsys_
28 using ::testing::Return
;
30 using ::testing::SetArrayArgument
;
31 using ::testing::DoAll
;
32 using ::testing::StrEq
;
34 class DNSResolverTest
: public ::testing::Test
{
36 void SetUp() override
{
37 g_ceph_context
->_conf
->subsys
.set_log_level(dout_subsys
, TEST_DEBUG
);
40 void TearDown() override
{
41 DNSResolver::get_instance(nullptr);
45 TEST_F(DNSResolverTest
, resolve_ip_addr
) {
46 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
48 int lena
= sizeof(ns_query_msg_mon_a_payload
);
49 #ifdef HAVE_RES_NQUERY
50 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
51 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
52 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
54 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
55 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
56 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
60 DNSResolver::get_instance(resolvH
)->resolve_ip_addr(g_ceph_context
,
61 "mon.a.ceph.com", &addr
);
63 std::ostringstream os
;
65 ASSERT_EQ(os
.str(), "192.168.1.11:0/0");
68 TEST_F(DNSResolverTest
, resolve_ip_addr_fail
) {
69 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
71 #ifdef HAVE_RES_NQUERY
72 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("not_exists.com"), C_IN
, T_A
,_
,_
))
75 EXPECT_CALL(*resolvH
, res_query(StrEq("not_exists.com"), C_IN
, T_A
,_
,_
))
80 int ret
= DNSResolver::get_instance(resolvH
)->resolve_ip_addr(g_ceph_context
,
81 "not_exists.com", &addr
);
84 std::ostringstream os
;
86 ASSERT_EQ(os
.str(), "-");
90 TEST_F(DNSResolverTest
, resolve_srv_hosts_empty_domain
) {
91 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
94 int len
= sizeof(ns_search_msg_ok_payload
);
95 int lena
= sizeof(ns_query_msg_mon_a_payload
);
96 int lenb
= sizeof(ns_query_msg_mon_b_payload
);
97 int lenc
= sizeof(ns_query_msg_mon_c_payload
);
99 using ::testing::InSequence
;
103 #ifdef HAVE_RES_NQUERY
104 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_cephmon._tcp"), C_IN
, T_SRV
, _
, _
))
105 .WillOnce(DoAll(SetArrayArgument
<4>(ns_search_msg_ok_payload
,
106 ns_search_msg_ok_payload
+len
), Return(len
)));
108 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
109 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
110 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
112 EXPECT_CALL(*resolvH
, res_nquery(_
, StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
113 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_c_payload
,
114 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
116 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
117 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_b_payload
,
118 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
120 EXPECT_CALL(*resolvH
, res_search(StrEq("_cephmon._tcp"), C_IN
, T_SRV
, _
, _
))
121 .WillOnce(DoAll(SetArrayArgument
<3>(ns_search_msg_ok_payload
,
122 ns_search_msg_ok_payload
+len
), Return(len
)));
124 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
125 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
126 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
128 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
129 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_c_payload
,
130 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
132 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
133 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_b_payload
,
134 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
138 map
<string
, DNSResolver::Record
> records
;
139 DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(g_ceph_context
, "cephmon",
140 DNSResolver::SRV_Protocol::TCP
, &records
);
142 ASSERT_EQ(records
.size(), (unsigned int)3);
143 auto it
= records
.find("mon.a");
144 ASSERT_NE(it
, records
.end());
145 std::ostringstream os
;
146 os
<< it
->second
.addr
;
147 ASSERT_EQ(os
.str(), "192.168.1.11:6789/0");
149 it
= records
.find("mon.b");
150 ASSERT_NE(it
, records
.end());
151 os
<< it
->second
.addr
;
152 ASSERT_EQ(os
.str(), "192.168.1.12:6789/0");
154 it
= records
.find("mon.c");
155 ASSERT_NE(it
, records
.end());
156 os
<< it
->second
.addr
;
157 ASSERT_EQ(os
.str(), "192.168.1.13:6789/0");
160 TEST_F(DNSResolverTest
, resolve_srv_hosts_full_domain
) {
161 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
164 int len
= sizeof(ns_search_msg_ok_payload
);
165 int lena
= sizeof(ns_query_msg_mon_a_payload
);
166 int lenb
= sizeof(ns_query_msg_mon_b_payload
);
167 int lenc
= sizeof(ns_query_msg_mon_c_payload
);
169 using ::testing::InSequence
;
173 #ifdef HAVE_RES_NQUERY
174 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
175 .WillOnce(DoAll(SetArrayArgument
<4>(ns_search_msg_ok_payload
,
176 ns_search_msg_ok_payload
+len
), Return(len
)));
178 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
179 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
180 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
182 EXPECT_CALL(*resolvH
, res_nquery(_
, StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
183 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_c_payload
,
184 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
186 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
187 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_b_payload
,
188 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
190 EXPECT_CALL(*resolvH
, res_search(StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
191 .WillOnce(DoAll(SetArrayArgument
<3>(ns_search_msg_ok_payload
,
192 ns_search_msg_ok_payload
+len
), Return(len
)));
194 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
195 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
196 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
198 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
199 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_c_payload
,
200 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
202 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
203 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_b_payload
,
204 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
208 map
<string
, DNSResolver::Record
> records
;
209 DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(g_ceph_context
, "cephmon",
210 DNSResolver::SRV_Protocol::TCP
, "ceph.com", &records
);
212 ASSERT_EQ(records
.size(), (unsigned int)3);
213 auto it
= records
.find("mon.a");
214 ASSERT_NE(it
, records
.end());
215 std::ostringstream os
;
216 os
<< it
->second
.addr
;
217 ASSERT_EQ(os
.str(), "192.168.1.11:6789/0");
219 it
= records
.find("mon.b");
220 ASSERT_NE(it
, records
.end());
221 os
<< it
->second
.addr
;
222 ASSERT_EQ(os
.str(), "192.168.1.12:6789/0");
224 it
= records
.find("mon.c");
225 ASSERT_NE(it
, records
.end());
226 os
<< it
->second
.addr
;
227 ASSERT_EQ(os
.str(), "192.168.1.13:6789/0");
230 TEST_F(DNSResolverTest
, resolve_srv_hosts_fail
) {
231 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
234 using ::testing::InSequence
;
238 #ifdef HAVE_RES_NQUERY
239 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
240 .WillOnce(Return(0));
242 EXPECT_CALL(*resolvH
, res_search(StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
243 .WillOnce(Return(0));
247 map
<string
, DNSResolver::Record
> records
;
248 int ret
= DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(
249 g_ceph_context
, "noservice", DNSResolver::SRV_Protocol::TCP
, "", &records
);
252 ASSERT_TRUE(records
.empty());