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 it
= records
.find("mon.b");
152 ASSERT_NE(it
, records
.end());
153 os
<< it
->second
.addr
;
154 ASSERT_EQ(os
.str(), "v2:192.168.1.12:6789/0");
156 it
= records
.find("mon.c");
157 ASSERT_NE(it
, records
.end());
158 os
<< it
->second
.addr
;
159 ASSERT_EQ(os
.str(), "v2:192.168.1.13:6789/0");
162 TEST_F(DNSResolverTest
, resolve_srv_hosts_full_domain
) {
163 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
166 int len
= sizeof(ns_search_msg_ok_payload
);
167 int lena
= sizeof(ns_query_msg_mon_a_payload
);
168 int lenb
= sizeof(ns_query_msg_mon_b_payload
);
169 int lenc
= sizeof(ns_query_msg_mon_c_payload
);
171 using ::testing::InSequence
;
175 #ifdef HAVE_RES_NQUERY
176 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
177 .WillOnce(DoAll(SetArrayArgument
<4>(ns_search_msg_ok_payload
,
178 ns_search_msg_ok_payload
+len
), Return(len
)));
180 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
181 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_a_payload
,
182 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
184 EXPECT_CALL(*resolvH
, res_nquery(_
, StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
185 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_c_payload
,
186 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
188 EXPECT_CALL(*resolvH
, res_nquery(_
,StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
189 .WillOnce(DoAll(SetArrayArgument
<4>(ns_query_msg_mon_b_payload
,
190 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
192 EXPECT_CALL(*resolvH
, res_search(StrEq("_cephmon._tcp.ceph.com"), C_IN
, T_SRV
, _
, _
))
193 .WillOnce(DoAll(SetArrayArgument
<3>(ns_search_msg_ok_payload
,
194 ns_search_msg_ok_payload
+len
), Return(len
)));
196 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.a.ceph.com"), C_IN
, T_A
,_
,_
))
197 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_a_payload
,
198 ns_query_msg_mon_a_payload
+lena
), Return(lena
)));
200 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.c.ceph.com"), C_IN
, T_A
,_
,_
))
201 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_c_payload
,
202 ns_query_msg_mon_c_payload
+lenc
), Return(lenc
)));
204 EXPECT_CALL(*resolvH
, res_query(StrEq("mon.b.ceph.com"), C_IN
, T_A
, _
,_
))
205 .WillOnce(DoAll(SetArrayArgument
<3>(ns_query_msg_mon_b_payload
,
206 ns_query_msg_mon_b_payload
+lenb
), Return(lenb
)));
210 map
<string
, DNSResolver::Record
> records
;
211 DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(g_ceph_context
, "cephmon",
212 DNSResolver::SRV_Protocol::TCP
, "ceph.com", &records
);
214 ASSERT_EQ(records
.size(), (unsigned int)3);
215 auto it
= records
.find("mon.a");
216 ASSERT_NE(it
, records
.end());
217 std::ostringstream os
;
218 os
<< it
->second
.addr
;
219 ASSERT_EQ(os
.str(), "v2:192.168.1.11:6789/0");
221 it
= records
.find("mon.b");
222 ASSERT_NE(it
, records
.end());
223 os
<< it
->second
.addr
;
224 ASSERT_EQ(os
.str(), "v2:192.168.1.12:6789/0");
226 it
= records
.find("mon.c");
227 ASSERT_NE(it
, records
.end());
228 os
<< it
->second
.addr
;
229 ASSERT_EQ(os
.str(), "v2:192.168.1.13:6789/0");
232 TEST_F(DNSResolverTest
, resolve_srv_hosts_fail
) {
233 MockResolvHWrapper
*resolvH
= new MockResolvHWrapper();
236 using ::testing::InSequence
;
240 #ifdef HAVE_RES_NQUERY
241 EXPECT_CALL(*resolvH
, res_nsearch(_
, StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
242 .WillOnce(Return(0));
244 EXPECT_CALL(*resolvH
, res_search(StrEq("_noservice._tcp"), C_IN
, T_SRV
, _
, _
))
245 .WillOnce(Return(0));
249 map
<string
, DNSResolver::Record
> records
;
250 int ret
= DNSResolver::get_instance(resolvH
)->resolve_srv_hosts(
251 g_ceph_context
, "noservice", DNSResolver::SRV_Protocol::TCP
, "", &records
);
254 ASSERT_TRUE(records
.empty());