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 <arpa/nameser_compat.h>
16 #include "common/dns_resolve.h"
17 #include "test/common/dns_messages.h"
19 #include "common/debug.h"
20 #include "gmock/gmock.h"
27 #define dout_subsys ceph_subsys_
30 using ::testing::Return
;
32 using ::testing::SetArrayArgument
;
33 using ::testing::DoAll
;
34 using ::testing::StrEq
;
36 class DNSResolverTest
: public ::testing::Test
{
38 void SetUp() override
{
39 g_ceph_context
->_conf
->subsys
.set_log_level(dout_subsys
, TEST_DEBUG
);
42 void TearDown() override
{
43 DNSResolver::get_instance(nullptr);
47 TEST_F(DNSResolverTest
, resolve_ip_addr
) {
48 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
50 int lena
= sizeof(ns_query_msg_mon_a_payload
);
51 #ifdef HAVE_RES_NQUERY
52 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
53 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
54 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
56 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
57 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
58 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
62 DNSResolver::get_instance(resolvH
)->resolve_ip_addr(g_ceph_context
,
63 "mon.a.ceph.com", &addr
);
65 std::ostringstream os
;
67 ASSERT_EQ(os
.str(), "v2:192.168.1.11:0/0");
70 TEST_F(DNSResolverTest
, resolve_ip_addr_fail
) {
71 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
73 #ifdef HAVE_RES_NQUERY
74 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("not_exists.com"), C_IN
, T_A
,_
,_
))
77 EXPECT_CALL(*resolvH
, res_query(StrEq("not_exists.com"), C_IN
, T_A
,_
,_
))
82 int ret
= DNSResolver::get_instance(resolvH
)->resolve_ip_addr(g_ceph_context
,
83 "not_exists.com", &addr
);
86 std::ostringstream os
;
88 ASSERT_EQ(os
.str(), "-");
92 TEST_F(DNSResolverTest
, resolve_srv_hosts_empty_domain
) {
93 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
96 int len
= sizeof(ns_search_msg_ok_payload
);
97 int lena
= sizeof(ns_query_msg_mon_a_payload
);
98 int lenb
= sizeof(ns_query_msg_mon_b_payload
);
99 int lenc
= sizeof(ns_query_msg_mon_c_payload
);
101 using ::testing::InSequence
;
105 #ifdef HAVE_RES_NQUERY
106 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_cephmon._tcp"), C_IN
, T_SRV
, _
, _
))
107 .WillOnce(DoAll(SetArrayArgument
<4>(ns_search_msg_ok_payload
,
108 ns_search_msg_ok_payload
+len
), Return(len
)));
110 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
111 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
112 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
114 EXPECT_CALL(*resolvH
, res_nquery(_
, StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
115 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_c_payload
,
116 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
118 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
119 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_b_payload
,
120 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
122 EXPECT_CALL(*resolvH
, res_search(StrEq("_cephmon._tcp"), C_IN
, T_SRV
, _
, _
))
123 .WillOnce(DoAll(SetArrayArgument
<3>(ns_search_msg_ok_payload
,
124 ns_search_msg_ok_payload
+len
), Return(len
)));
126 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
127 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
128 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
130 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
131 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_c_payload
,
132 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
134 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
135 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_b_payload
,
136 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
140 map
<string
, DNSResolver::Record
> records
;
141 DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(g_ceph_context
, "cephmon",
142 DNSResolver::SRV_Protocol::TCP
, &records
);
144 ASSERT_EQ(records
.size(), (unsigned int)3);
145 auto it
= records
.find("mon.a");
146 ASSERT_NE(it
, records
.end());
147 std::ostringstream os
;
148 os
<< it
->second
.addr
;
149 ASSERT_EQ(os
.str(), "v2:192.168.1.11:6789/0");
151 ASSERT_EQ(it
->second
.priority
, 10);
152 ASSERT_EQ(it
->second
.weight
, 40);
153 it
= records
.find("mon.b");
154 ASSERT_NE(it
, records
.end());
155 os
<< it
->second
.addr
;
156 ASSERT_EQ(os
.str(), "v2:192.168.1.12:6789/0");
158 ASSERT_EQ(it
->second
.priority
, 10);
159 ASSERT_EQ(it
->second
.weight
, 35);
160 it
= records
.find("mon.c");
161 ASSERT_NE(it
, records
.end());
162 os
<< it
->second
.addr
;
163 ASSERT_EQ(os
.str(), "v2:192.168.1.13:6789/0");
164 ASSERT_EQ(it
->second
.priority
, 10);
165 ASSERT_EQ(it
->second
.weight
, 25);
168 TEST_F(DNSResolverTest
, resolve_srv_hosts_full_domain
) {
169 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
172 int len
= sizeof(ns_search_msg_ok_payload
);
173 int lena
= sizeof(ns_query_msg_mon_a_payload
);
174 int lenb
= sizeof(ns_query_msg_mon_b_payload
);
175 int lenc
= sizeof(ns_query_msg_mon_c_payload
);
177 using ::testing::InSequence
;
181 #ifdef HAVE_RES_NQUERY
182 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
183 .WillOnce(DoAll(SetArrayArgument
<4>(ns_search_msg_ok_payload
,
184 ns_search_msg_ok_payload
+len
), Return(len
)));
186 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
187 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
188 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
190 EXPECT_CALL(*resolvH
, res_nquery(_
, StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
191 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_c_payload
,
192 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
194 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
195 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_b_payload
,
196 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
198 EXPECT_CALL(*resolvH
, res_search(StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
199 .WillOnce(DoAll(SetArrayArgument
<3>(ns_search_msg_ok_payload
,
200 ns_search_msg_ok_payload
+len
), Return(len
)));
202 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
203 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
204 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
206 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
207 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_c_payload
,
208 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
210 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
211 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_b_payload
,
212 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
216 map
<string
, DNSResolver::Record
> records
;
217 DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(g_ceph_context
, "cephmon",
218 DNSResolver::SRV_Protocol::TCP
, "ceph.com", &records
);
220 ASSERT_EQ(records
.size(), (unsigned int)3);
221 auto it
= records
.find("mon.a");
222 ASSERT_NE(it
, records
.end());
223 std::ostringstream os
;
224 os
<< it
->second
.addr
;
225 ASSERT_EQ(os
.str(), "v2:192.168.1.11:6789/0");
227 it
= records
.find("mon.b");
228 ASSERT_NE(it
, records
.end());
229 os
<< it
->second
.addr
;
230 ASSERT_EQ(os
.str(), "v2:192.168.1.12:6789/0");
232 it
= records
.find("mon.c");
233 ASSERT_NE(it
, records
.end());
234 os
<< it
->second
.addr
;
235 ASSERT_EQ(os
.str(), "v2:192.168.1.13:6789/0");
238 TEST_F(DNSResolverTest
, resolve_srv_hosts_fail
) {
239 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
242 using ::testing::InSequence
;
246 #ifdef HAVE_RES_NQUERY
247 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
248 .WillOnce(Return(0));
250 EXPECT_CALL(*resolvH
, res_search(StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
251 .WillOnce(Return(0));
255 map
<string
, DNSResolver::Record
> records
;
256 int ret
= DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(
257 g_ceph_context
, "noservice", DNSResolver::SRV_Protocol::TCP
, "", &records
);
260 ASSERT_TRUE(records
.empty());