diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 25cd580..cf59b77 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -16,7 +16,7 @@ jobs: - name: prepare run: | sudo apt update - sudo apt install libgtest-dev + sudo apt install libgtest-dev dnsperf - name: make run: | make all -j4 diff --git a/test/cases/test-bind.cc b/test/cases/test-bind.cc index c1aa08a..aab8c59 100644 --- a/test/cases/test-bind.cc +++ b/test/cases/test-bind.cc @@ -1,3 +1,21 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + #include "client.h" #include "include/utils.h" #include "server.h" diff --git a/test/cases/test-cname.cc b/test/cases/test-cname.cc index 6e03c2e..b6df617 100644 --- a/test/cases/test-cname.cc +++ b/test/cases/test-cname.cc @@ -1,35 +1,53 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + #include "client.h" +#include "dns.h" #include "include/utils.h" #include "server.h" #include "gtest/gtest.h" -#include "dns.h" TEST(server, cname) { smartdns::MockServer server_upstream; smartdns::Server server; - server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) { - std::string domain = request->domain; - if (request->domain.length() == 0) { - return smartdns::SERVER_REQUEST_ERROR; - } + server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) { + std::string domain = request->domain; + if (request->domain.length() == 0) { + return smartdns::SERVER_REQUEST_ERROR; + } - if (request->qtype == DNS_T_A) { - unsigned char addr[4] = {1, 2, 3, 4}; - dns_add_A(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); - } else if (request->qtype == DNS_T_AAAA) { - unsigned char addr[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - dns_add_AAAA(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); - } else { - return smartdns::SERVER_REQUEST_ERROR; - } + if (request->qtype == DNS_T_A) { + unsigned char addr[4] = {1, 2, 3, 4}; + dns_add_A(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); + } else if (request->qtype == DNS_T_AAAA) { + unsigned char addr[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + dns_add_AAAA(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); + } else { + return smartdns::SERVER_REQUEST_ERROR; + } - EXPECT_EQ(domain, "e.com"); + EXPECT_EQ(domain, "e.com"); - request->response_packet->head.rcode = DNS_RC_NOERROR; - return smartdns::SERVER_REQUEST_OK; - }); + request->response_packet->head.rcode = DNS_RC_NOERROR; + return smartdns::SERVER_REQUEST_OK; + }); server.Start(R"""(bind [::]:60053 cname /a.com/b.com @@ -43,10 +61,10 @@ log-level debug cache-persist no)"""); smartdns::Client client; ASSERT_TRUE(client.Query("a.com", 60053)); - std::cout << client.GetResult() << std::endl; + std::cout << client.GetResult() << std::endl; ASSERT_EQ(client.GetAnswerNum(), 2); EXPECT_EQ(client.GetStatus(), "NOERROR"); - EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com"); + EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com"); EXPECT_EQ(client.GetAnswer()[0].GetData(), "b.com."); EXPECT_EQ(client.GetAnswer()[1].GetData(), "1.2.3.4"); } diff --git a/test/cases/test-discard-block-ip.cc b/test/cases/test-discard-block-ip.cc index 60510e9..1ac3f5e 100644 --- a/test/cases/test-discard-block-ip.cc +++ b/test/cases/test-discard-block-ip.cc @@ -1,3 +1,21 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + #include "client.h" #include "dns.h" #include "include/utils.h" @@ -6,20 +24,20 @@ TEST(DiscardBlockIP, first_ping) { - smartdns::MockServer server_upstream1; + smartdns::MockServer server_upstream1; smartdns::MockServer server_upstream2; smartdns::Server server; server_upstream1.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) { - unsigned char addr[4] = {0, 0, 0, 0}; + unsigned char addr[4] = {0, 0, 0, 0}; dns_add_A(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 611, addr); request->response_packet->head.rcode = DNS_RC_NOERROR; return smartdns::SERVER_REQUEST_OK; }); - server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) { - unsigned char addr[4] = {1, 2, 3, 4}; - usleep(20000); + server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) { + unsigned char addr[4] = {1, 2, 3, 4}; + usleep(20000); dns_add_A(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 611, addr); request->response_packet->head.rcode = DNS_RC_NOERROR; return smartdns::SERVER_REQUEST_OK; @@ -37,26 +55,26 @@ cache-persist no)"""); std::cout << client.GetResult() << std::endl; ASSERT_EQ(client.GetAnswerNum(), 1); EXPECT_EQ(client.GetStatus(), "NOERROR"); - EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600); + EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600); EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4"); } TEST(DiscardBlockIP, first_response) { - smartdns::MockServer server_upstream1; + smartdns::MockServer server_upstream1; smartdns::MockServer server_upstream2; smartdns::Server server; server_upstream1.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) { - unsigned char addr[4] = {0, 0, 0, 0}; + unsigned char addr[4] = {0, 0, 0, 0}; dns_add_A(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 611, addr); request->response_packet->head.rcode = DNS_RC_NOERROR; return smartdns::SERVER_REQUEST_OK; }); - server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) { - unsigned char addr[4] = {1, 2, 3, 4}; - usleep(20000); + server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) { + unsigned char addr[4] = {1, 2, 3, 4}; + usleep(20000); dns_add_A(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 611, addr); request->response_packet->head.rcode = DNS_RC_NOERROR; return smartdns::SERVER_REQUEST_OK; @@ -75,6 +93,6 @@ cache-persist no)"""); std::cout << client.GetResult() << std::endl; ASSERT_EQ(client.GetAnswerNum(), 1); EXPECT_EQ(client.GetStatus(), "NOERROR"); - EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3); + EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3); EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4"); } \ No newline at end of file diff --git a/test/cases/test-mock-server.cc b/test/cases/test-mock-server.cc index 2201a71..79cba1d 100644 --- a/test/cases/test-mock-server.cc +++ b/test/cases/test-mock-server.cc @@ -1,3 +1,21 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + #include "client.h" #include "include/utils.h" #include "server.h" @@ -21,9 +39,8 @@ TEST(MockServer, soa) { smartdns::MockServer server; smartdns::Client client; - server.Start("udp://0.0.0.0:7053", [](struct smartdns::ServerRequestContext *request) { - return smartdns::SERVER_REQUEST_SOA; - }); + server.Start("udp://0.0.0.0:7053", + [](struct smartdns::ServerRequestContext *request) { return smartdns::SERVER_REQUEST_SOA; }); ASSERT_TRUE(client.Query("example.com", 7053)); std::cout << client.GetResult() << std::endl; @@ -34,9 +51,8 @@ TEST(MockServer, noerror) { smartdns::MockServer server; smartdns::Client client; - server.Start("udp://0.0.0.0:7053", [](struct smartdns::ServerRequestContext *request) { - return smartdns::SERVER_REQUEST_OK; - }); + server.Start("udp://0.0.0.0:7053", + [](struct smartdns::ServerRequestContext *request) { return smartdns::SERVER_REQUEST_OK; }); ASSERT_TRUE(client.Query("example.com", 7053)); std::cout << client.GetResult() << std::endl; diff --git a/test/cases/test-perf.cc b/test/cases/test-perf.cc new file mode 100644 index 0000000..4296096 --- /dev/null +++ b/test/cases/test-perf.cc @@ -0,0 +1,99 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + +#include "client.h" +#include "dns.h" +#include "include/utils.h" +#include "server.h" +#include "gtest/gtest.h" +#include + +class Perf : public ::testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} +}; + +TEST(Perf, no_speed_check) +{ + smartdns::MockServer server_upstream; + smartdns::Server server; + if (smartdns::IsCommandExists("dnsperf") == false) { + printf("dnsperf not found, skip test, please install dnsperf first.\n"); + GTEST_SKIP(); + } + + server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) { + std::string domain = request->domain; + if (request->domain.length() == 0) { + return smartdns::SERVER_REQUEST_ERROR; + } + + if (request->qtype == DNS_T_A) { + unsigned char addr[4] = {1, 2, 3, 4}; + dns_add_A(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); + } else if (request->qtype == DNS_T_AAAA) { + unsigned char addr[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + dns_add_AAAA(request->response_packet, DNS_RRS_AN, domain.c_str(), 61, addr); + } else { + return smartdns::SERVER_REQUEST_ERROR; + } + + request->response_packet->head.rcode = DNS_RC_NOERROR; + return smartdns::SERVER_REQUEST_OK; + }); + + server.Start(R"""(bind [::]:60053 +server 127.0.0.1:61053 +log-num 0 +log-console yes +speed-check-mode none +log-level error +cache-persist no)"""); + std::string file = "/tmp/smartdns-perftest-domain.list" + smartdns::GenerateRandomString(5); + std::string cmd = "dnsperf -p 60053"; + cmd += " -d "; + cmd += file; + std::ofstream ofs(file); + ASSERT_TRUE(ofs.is_open()); + Defer + { + ofs.close(); + unlink(file.c_str()); + }; + + for (int i = 0; i < 100000; i++) { + std::string domain = smartdns::GenerateRandomString(10); + domain += "."; + domain += smartdns::GenerateRandomString(3); + + if (random() % 2 == 0) { + domain += " A"; + } else { + domain += " AAAA"; + } + + domain += "\n"; + + ofs.write(domain.c_str(), domain.length()); + ofs.flush(); + } + + system(cmd.c_str()); +} diff --git a/test/cases/test-ping.cc b/test/cases/test-ping.cc index bf9a947..8f85e1a 100644 --- a/test/cases/test-ping.cc +++ b/test/cases/test-ping.cc @@ -1,9 +1,27 @@ +/************************************************************************* + * + * Copyright (C) 2018-2023 Ruilin Peng (Nick) . + * + * 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 . + */ + #include "client.h" #include "fast_ping.h" #include "include/utils.h" #include "server.h" -#include "gtest/gtest.h" #include "tlog.h" +#include "gtest/gtest.h" class Ping : public ::testing::Test { @@ -11,16 +29,17 @@ class Ping : public ::testing::Test virtual void SetUp() { EXPECT_EQ(fast_ping_init(), 0); - loglevel = tlog_getlevel(); - tlog_setlevel(TLOG_DEBUG); + loglevel = tlog_getlevel(); + tlog_setlevel(TLOG_DEBUG); } virtual void TearDown() { fast_ping_exit(); - tlog_setlevel(loglevel); + tlog_setlevel(loglevel); } - private: - tlog_level loglevel; + + private: + tlog_level loglevel; }; void ping_result_callback(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, @@ -38,8 +57,8 @@ TEST_F(Ping, DISABLED_icmp) ping_host = fast_ping_start(PING_TYPE_ICMP, "127.0.0.1", 1, 1, 200, ping_result_callback, &count); ASSERT_NE(ping_host, nullptr); usleep(10000); - fast_ping_stop(ping_host); - EXPECT_EQ(count, 1); + fast_ping_stop(ping_host); + EXPECT_EQ(count, 1); } TEST_F(Ping, DISABLED_tcp) @@ -49,6 +68,6 @@ TEST_F(Ping, DISABLED_tcp) ping_host = fast_ping_start(PING_TYPE_TCP, "127.0.0.1:1", 1, 1, 200, ping_result_callback, &count); ASSERT_NE(ping_host, nullptr); usleep(10000); - fast_ping_stop(ping_host); - EXPECT_EQ(count, 1); + fast_ping_stop(ping_host); + EXPECT_EQ(count, 1); } diff --git a/test/include/utils.h b/test/include/utils.h index a69c421..d932fa5 100644 --- a/test/include/utils.h +++ b/test/include/utils.h @@ -20,6 +20,7 @@ #define _SMARTDNS_TEST_UTILS_ #include +#include namespace smartdns { @@ -55,5 +56,9 @@ class DeferGuard #define SMARTDNS_CONCAT(a, b) SMARTDNS_CONCAT_(a, b) #define Defer ::smartdns::DeferGuard SMARTDNS_CONCAT(__defer__, __LINE__) = [&]() +bool IsCommandExists(const std::string &cmd); + +std::string GenerateRandomString(int len); + } // namespace smartdns #endif // _SMARTDNS_TEST_UTILS_ diff --git a/test/server.h b/test/server.h index b0a0203..9971708 100644 --- a/test/server.h +++ b/test/server.h @@ -22,9 +22,9 @@ #include "dns.h" #include #include -#include #include #include +#include namespace smartdns { @@ -60,7 +60,7 @@ struct ServerRequestContext { uint8_t *request_data; int request_data_len; uint8_t *response_data; - struct dns_packet *response_packet; + struct dns_packet *response_packet; int response_data_max_len; int response_data_len; }; @@ -83,13 +83,14 @@ class MockServer void Stop(); bool IsRunning(); - static bool AddIP(struct ServerRequestContext *request, const std::string &domain, const std::string &ip, int ttl = 60); + static bool AddIP(struct ServerRequestContext *request, const std::string &domain, const std::string &ip, + int ttl = 60); private: void Run(); - static bool GetAddr(const std::string &host, const std::string port, int type, int protocol, struct sockaddr_storage *addr, - socklen_t *addrlen); + static bool GetAddr(const std::string &host, const std::string port, int type, int protocol, + struct sockaddr_storage *addr, socklen_t *addrlen); int fd_; std::thread thread_; bool run_; diff --git a/test/utils.cc b/test/utils.cc new file mode 100644 index 0000000..69dc9eb --- /dev/null +++ b/test/utils.cc @@ -0,0 +1,58 @@ +#include "include/utils.h" +#include +#include +#include +#include + +namespace smartdns +{ + +bool IsCommandExists(const std::string &cmd) +{ + char *copy_path = NULL; + char cmd_path[4096]; + const char *env_path = getenv("PATH"); + char *save_ptr = NULL; + + if (env_path == NULL) { + env_path = "/bin:/usr/bin:/usr/local/bin"; + } + + copy_path = strdup(env_path); + if (copy_path == NULL) { + return false; + } + + Defer + { + free(copy_path); + }; + + for (char *tok = strtok_r(copy_path, ":", &save_ptr); tok; tok = strtok_r(NULL, ":", &save_ptr)) { + snprintf(cmd_path, sizeof(cmd_path), "%s/%s", tok, cmd.c_str()); + if (access(cmd_path, X_OK) != 0) { + continue; + } + + return true; + } + + return false; +} + +std::string GenerateRandomString(int len) +{ + std::string result; + static const char alphanum[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + result.resize(len); + + for (int i = 0; i < len; ++i) { + result[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + return result; +} + +} // namespace smartdns \ No newline at end of file