test: add test cases
This commit is contained in:
@@ -20,6 +20,7 @@ CFLAGS += -DTEST
|
||||
CFLAGS += -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough
|
||||
|
||||
CXXFLAGS += -g
|
||||
CXXFLAGS += -DTEST
|
||||
CXXFLAGS += -I./ -I../src -I../src/include
|
||||
|
||||
SMARTDNS_OBJS = lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o lib/nftset.o
|
||||
|
||||
@@ -61,7 +61,7 @@ cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com A", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 0);
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 30);
|
||||
|
||||
@@ -160,4 +160,35 @@ cache-persist no)""");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Bind, device)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.Start(R"""(
|
||||
bind [::]:60053@lo
|
||||
server 127.0.0.1:62053
|
||||
log-num 0
|
||||
log-console yes
|
||||
log-level info
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 100);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
}
|
||||
|
||||
71
test/cases/test-bootstrap.cc
Normal file
71
test/cases/test-bootstrap.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
*
|
||||
* smartdns is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* smartdns is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "dns.h"
|
||||
#include "include/utils.h"
|
||||
#include "server.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class BootStrap : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(BootStrap, bootstrap)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::MockServer server_upstream2;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype != DNS_T_A) {
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype != DNS_T_A) {
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "127.0.0.1", 611);
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server udp://127.0.0.1:62053 -bootstrap-dns
|
||||
server udp://example.com:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
usleep(2500000);
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
}
|
||||
@@ -21,6 +21,11 @@
|
||||
#include "include/utils.h"
|
||||
#include "server.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <fstream>
|
||||
|
||||
/* clang-format off */
|
||||
#include "dns_cache.h"
|
||||
/* clang-format on */
|
||||
|
||||
class Cache : public ::testing::Test
|
||||
{
|
||||
@@ -228,3 +233,56 @@ cache-persist no)""");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
}
|
||||
|
||||
TEST_F(Cache, save_file)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
auto cache_file = "/tmp/smartdns_cache." + smartdns::GenerateRandomString(10);
|
||||
std::string conf = R"""(
|
||||
bind [::]:60053@lo
|
||||
server 127.0.0.1:62053
|
||||
log-num 0
|
||||
log-console yes
|
||||
log-level debug
|
||||
cache-persist yes
|
||||
dualstack-ip-selection no
|
||||
)""";
|
||||
|
||||
conf += "cache-file " + cache_file;
|
||||
Defer
|
||||
{
|
||||
unlink(cache_file.c_str());
|
||||
};
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
{
|
||||
smartdns::Server server;
|
||||
server.Start(conf);
|
||||
smartdns::Client client;
|
||||
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 100);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
server.Stop();
|
||||
usleep(200 * 1000);
|
||||
}
|
||||
|
||||
ASSERT_EQ(access(cache_file.c_str(), F_OK), 0);
|
||||
|
||||
std::fstream fs(cache_file, std::ios::in);
|
||||
struct dns_cache_file head;
|
||||
memset(&head, 0, sizeof(head));
|
||||
fs.read((char *)&head, sizeof(head));
|
||||
EXPECT_EQ(head.magic, MAGIC_NUMBER);
|
||||
EXPECT_EQ(head.cache_number, 1);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,14 @@
|
||||
#include "server.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(server, cname)
|
||||
class Cname : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(Cname, cname)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
@@ -32,11 +39,8 @@ TEST(server, cname)
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
unsigned char addr[4] = {1, 2, 3, 4};
|
||||
dns_add_A(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 611, addr);
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||
EXPECT_EQ(request->domain, "e.com");
|
||||
|
||||
request->response_packet->head.rcode = DNS_RC_NOERROR;
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
|
||||
187
test/cases/test-dualstack.cc
Normal file
187
test/cases/test-dualstack.cc
Normal file
@@ -0,0 +1,187 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
*
|
||||
* smartdns is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* smartdns is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "dns.h"
|
||||
#include "include/utils.h"
|
||||
#include "server.h"
|
||||
#include "util.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <fstream>
|
||||
|
||||
class DualStack : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(DualStack, ipv4_prefer)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
std::map<int, int> qid_map;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
|
||||
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 150);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 150);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
|
||||
|
||||
usleep(220 * 1000);
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 20);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
EXPECT_EQ(client.GetAnswer()[1].GetData(), "5.6.7.8");
|
||||
}
|
||||
|
||||
TEST_F(DualStack, ipv6_prefer_allow_force_AAAA)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
|
||||
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 70);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 75);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
dualstack-ip-allow-force-AAAA yes
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com A", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
|
||||
|
||||
usleep(220 * 1000);
|
||||
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 20);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
|
||||
EXPECT_EQ(client.GetAnswer()[1].GetData(), "2001:db8::2");
|
||||
}
|
||||
|
||||
TEST_F(DualStack, ipv6_prefer_must_exist_ipv4)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
|
||||
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 70);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 100);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
dualstack-ip-allow-force-AAAA yes
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com A", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
|
||||
|
||||
usleep(220 * 1000);
|
||||
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 20);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
|
||||
}
|
||||
97
test/cases/test-nameserver.cc
Normal file
97
test/cases/test-nameserver.cc
Normal file
@@ -0,0 +1,97 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
*
|
||||
* smartdns is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* smartdns is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "dns.h"
|
||||
#include "include/utils.h"
|
||||
#include "server.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class NameServer : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(NameServer, cname)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::MockServer server_upstream1;
|
||||
smartdns::MockServer server_upstream2;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype != DNS_T_A) {
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "9.10.11.12", 611);
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
server_upstream1.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype != DNS_T_A) {
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
server_upstream2.Start("udp://0.0.0.0:63053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype != DNS_T_A) {
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
}
|
||||
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8", 611);
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
});
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
server 127.0.0.1:62053 -group g1 -exclude-default-group
|
||||
server 127.0.0.1:63053 -group g2 -exclude-default-group
|
||||
nameserver /a.com/g1
|
||||
nameserver /b.com/g2
|
||||
log-num 0
|
||||
log-console yes
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
|
||||
ASSERT_TRUE(client.Query("b.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "5.6.7.8");
|
||||
|
||||
ASSERT_TRUE(client.Query("c.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "c.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "9.10.11.12");
|
||||
}
|
||||
@@ -71,3 +71,27 @@ TEST_F(Ping, tcp)
|
||||
fast_ping_stop(ping_host);
|
||||
EXPECT_EQ(count, 1);
|
||||
}
|
||||
|
||||
void fake_ping_result_callback(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result,
|
||||
struct sockaddr *addr, socklen_t addr_len, int seqno, int ttl, struct timeval *tv,
|
||||
int error, void *userptr)
|
||||
{
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
int *count = (int *)userptr;
|
||||
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d ttl=%d time=%.3f\n", host, seqno, ttl, rtt);
|
||||
*count = (int)rtt;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Ping, fake_icmp)
|
||||
{
|
||||
struct ping_host_struct *ping_host;
|
||||
int count = 0;
|
||||
fast_ping_fake_ip_add(PING_TYPE_ICMP, "1.2.3.4", 60, 5);
|
||||
ping_host = fast_ping_start(PING_TYPE_ICMP, "1.2.3.4", 1, 1000, 200, fake_ping_result_callback, &count);
|
||||
ASSERT_NE(ping_host, nullptr);
|
||||
usleep(100000);
|
||||
fast_ping_stop(ping_host);
|
||||
EXPECT_GE(count, 5);
|
||||
}
|
||||
|
||||
78
test/cases/test-qtype-soa.cc
Normal file
78
test/cases/test-qtype-soa.cc
Normal file
@@ -0,0 +1,78 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
*
|
||||
* smartdns is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* smartdns is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "dns.h"
|
||||
#include "include/utils.h"
|
||||
#include "server.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class QtypeSOA : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(QtypeSOA, AAAA_HTTPS)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
log-level debug
|
||||
force-qtype-SOA 28 65
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 30);
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
|
||||
|
||||
ASSERT_TRUE(client.Query("a.com -t HTTPS", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAuthorityNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 30);
|
||||
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
|
||||
|
||||
ASSERT_TRUE(client.Query("a.com A", 60053));
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
}
|
||||
@@ -189,3 +189,146 @@ cache-persist no)""");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
|
||||
}
|
||||
|
||||
TEST_F(SpeedCheck, fastest_ip)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
|
||||
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
dualstack-ip-selection no
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("b.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 200);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.com");
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
|
||||
usleep(220 * 1000);
|
||||
ASSERT_TRUE(client.Query("b.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 2);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 20);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
EXPECT_EQ(client.GetAnswer()[1].GetData(), "5.6.7.8");
|
||||
}
|
||||
|
||||
TEST_F(SpeedCheck, unreach_best_ipv4)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::MockServer server_upstream2;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server_upstream2.Start("udp://0.0.0.0:62053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_A) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "9.10.11.12");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10000);
|
||||
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 10000);
|
||||
server.MockPing(PING_TYPE_ICMP, "9.10.11.12", 60, 10000);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
server 127.0.0.1:62053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
dualstack-ip-selection no
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 1200);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
|
||||
}
|
||||
|
||||
TEST_F(SpeedCheck, unreach_best_ipv6)
|
||||
{
|
||||
smartdns::MockServer server_upstream;
|
||||
smartdns::MockServer server_upstream2;
|
||||
smartdns::Server server;
|
||||
|
||||
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server_upstream2.Start("udp://0.0.0.0:62053", [&](struct smartdns::ServerRequestContext *request) {
|
||||
if (request->qtype == DNS_T_AAAA) {
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
|
||||
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::3");
|
||||
return smartdns::SERVER_REQUEST_OK;
|
||||
}
|
||||
return smartdns::SERVER_REQUEST_SOA;
|
||||
});
|
||||
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 10000);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 10000);
|
||||
server.MockPing(PING_TYPE_ICMP, "2001:db8::3", 60, 10000);
|
||||
|
||||
server.Start(R"""(bind [::]:60053
|
||||
server 127.0.0.1:61053
|
||||
server 127.0.0.1:62053
|
||||
log-num 0
|
||||
log-console yes
|
||||
speed-check-mode ping
|
||||
dualstack-ip-selection no
|
||||
log-level debug
|
||||
cache-persist no)""");
|
||||
smartdns::Client client;
|
||||
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
|
||||
std::cout << client.GetResult() << std::endl;
|
||||
ASSERT_EQ(client.GetAnswerNum(), 1);
|
||||
EXPECT_EQ(client.GetStatus(), "NOERROR");
|
||||
EXPECT_LT(client.GetQueryTime(), 1200);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
|
||||
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
|
||||
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::2");
|
||||
}
|
||||
|
||||
@@ -173,6 +173,11 @@ int Client::GetAnswerNum()
|
||||
return answer_num_;
|
||||
}
|
||||
|
||||
int Client::GetAuthorityNum()
|
||||
{
|
||||
return authority_num_;
|
||||
}
|
||||
|
||||
std::string Client::GetStatus()
|
||||
{
|
||||
return status_;
|
||||
@@ -257,7 +262,7 @@ bool Client::ParserResult()
|
||||
|
||||
std::regex reg_authority_num(", AUTHORITY: ([0-9]+),");
|
||||
if (std::regex_search(result_, match, reg_authority_num)) {
|
||||
records_authority_num_ = std::stoi(match[1]);
|
||||
authority_num_ = std::stoi(match[1]);
|
||||
}
|
||||
|
||||
std::regex reg_status(", status: ([A-Z]+),");
|
||||
@@ -313,7 +318,7 @@ bool Client::ParserResult()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (records_authority_num_ != records_authority_.size()) {
|
||||
if (authority_num_ != records_authority_.size()) {
|
||||
std::cout << "DIG FAILED: Num Not Match\n" << result_ << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ class Client
|
||||
|
||||
int GetAnswerNum();
|
||||
|
||||
int GetAuthorityNum();
|
||||
|
||||
std::string GetStatus();
|
||||
|
||||
std::string GetServer();
|
||||
@@ -90,7 +92,7 @@ class Client
|
||||
bool ParserRecord(const std::string &record_str, std::vector<DNSRecord> &record);
|
||||
std::string result_;
|
||||
int answer_num_{0};
|
||||
int records_authority_num_{0};
|
||||
int authority_num_{0};
|
||||
std::string status_;
|
||||
std::string server_;
|
||||
int query_time_{0};
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include "server.h"
|
||||
#include "dns_server.h"
|
||||
#include "fast_ping.h"
|
||||
#include "include/utils.h"
|
||||
#include "smartdns.h"
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
@@ -36,8 +38,6 @@
|
||||
namespace smartdns
|
||||
{
|
||||
|
||||
extern "C" int smartdns_main(int argc, char *argv[], int fd_notify);
|
||||
|
||||
MockServer::MockServer() {}
|
||||
|
||||
MockServer::~MockServer()
|
||||
@@ -293,6 +293,34 @@ Server::Server(enum Server::CREATE_MODE mode)
|
||||
mode_ = mode;
|
||||
}
|
||||
|
||||
void Server::MockPing(PING_TYPE type, const std::string &host, int ttl, float time)
|
||||
{
|
||||
struct MockPingIP ping_ip;
|
||||
ping_ip.type = type;
|
||||
ping_ip.host = host;
|
||||
ping_ip.ttl = ttl;
|
||||
ping_ip.time = time;
|
||||
mock_ping_ips_.push_back(ping_ip);
|
||||
}
|
||||
|
||||
void Server::StartPost(void *arg)
|
||||
{
|
||||
Server *server = (Server *)arg;
|
||||
bool has_ipv6 = false;
|
||||
for (auto &it : server->mock_ping_ips_) {
|
||||
if (has_ipv6 == false && check_is_ipv6(it.host.c_str()) == 0) {
|
||||
has_ipv6 = true;
|
||||
}
|
||||
|
||||
fast_ping_fake_ip_add(it.type, it.host.c_str(), it.ttl, it.time);
|
||||
}
|
||||
|
||||
if (has_ipv6 == true) {
|
||||
fast_ping_fake_ip_add(PING_TYPE_ICMP, "2001::", 64, 10);
|
||||
dns_server_check_ipv6_ready();
|
||||
}
|
||||
}
|
||||
|
||||
bool Server::Start(const std::string &conf, enum CONF_TYPE type)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
@@ -343,6 +371,7 @@ bool Server::Start(const std::string &conf, enum CONF_TYPE type)
|
||||
argv[i] = (char *)args[i].c_str();
|
||||
}
|
||||
|
||||
smartdns_reg_post_func(Server::StartPost, this);
|
||||
smartdns_main(args.size(), argv, fds[1]);
|
||||
_exit(1);
|
||||
} else if (pid < 0) {
|
||||
@@ -358,7 +387,9 @@ bool Server::Start(const std::string &conf, enum CONF_TYPE type)
|
||||
argv[i] = (char *)args[i].c_str();
|
||||
}
|
||||
|
||||
smartdns_reg_post_func(Server::StartPost, this);
|
||||
smartdns_main(args.size(), argv, fds[1]);
|
||||
smartdns_reg_post_func(nullptr, nullptr);
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
#define _SMARTDNS_SERVER_
|
||||
|
||||
#include "dns.h"
|
||||
#include "fast_ping.h"
|
||||
#include "include/utils.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace smartdns
|
||||
{
|
||||
@@ -33,6 +35,12 @@ namespace smartdns
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
struct MockPingIP {
|
||||
PING_TYPE type;
|
||||
std::string host;
|
||||
int ttl;
|
||||
float time;
|
||||
};
|
||||
enum CONF_TYPE {
|
||||
CONF_TYPE_STRING,
|
||||
CONF_TYPE_FILE,
|
||||
@@ -45,17 +53,19 @@ class Server
|
||||
Server(enum CREATE_MODE mode);
|
||||
virtual ~Server();
|
||||
|
||||
void MockPing(PING_TYPE type, const std::string &host, int ttl, float time);
|
||||
bool Start(const std::string &conf, enum CONF_TYPE type = CONF_TYPE_STRING);
|
||||
void Stop(bool graceful = true);
|
||||
bool IsRunning();
|
||||
|
||||
private:
|
||||
static void StartPost(void *arg);
|
||||
pid_t pid_;
|
||||
std::thread thread_;
|
||||
int fd_;
|
||||
std::string conf_file_;
|
||||
TempFile conf_temp_file_;
|
||||
|
||||
std::vector<MockPingIP> mock_ping_ips_;
|
||||
enum CREATE_MODE mode_;
|
||||
};
|
||||
|
||||
@@ -100,10 +110,10 @@ class MockServer
|
||||
|
||||
static bool GetAddr(const std::string &host, const std::string port, int type, int protocol,
|
||||
struct sockaddr_storage *addr, socklen_t *addrlen);
|
||||
int fd_;
|
||||
int fd_{0};
|
||||
std::thread thread_;
|
||||
bool run_;
|
||||
ServerRequest callback_;
|
||||
bool run_{false};
|
||||
ServerRequest callback_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace smartdns
|
||||
|
||||
Reference in New Issue
Block a user