fix on_init crash (#3)
All checks were successful
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Debug) (push) Successful in 1m28s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Release) (push) Successful in 1m56s
linux-arm-gcc / linux-gcc-arm (Debug) (push) Successful in 1m43s
linux-arm-gcc / linux-gcc-arm (Release) (push) Successful in 1m40s
linux-arm-gcc / linux-gcc-armhf (Debug) (push) Successful in 1m59s
linux-arm-gcc / linux-gcc-armhf (Release) (push) Successful in 1m51s
linux-mips-gcc / linux-gcc-mipsel (Debug) (push) Successful in 1m32s
linux-mips-gcc / linux-gcc-mipsel (Release) (push) Successful in 1m38s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m27s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 1m41s
linux-riscv64-gcc / linux-gcc-riscv64 (Debug) (push) Successful in 3m17s
linux-riscv64-gcc / linux-gcc-riscv64 (Release) (push) Successful in 1m45s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m10s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m26s
linux-x86-gcc / linux-gcc (Debug) (push) Successful in 2m35s
linux-x86-gcc / linux-gcc (Release) (push) Successful in 2m29s
All checks were successful
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Debug) (push) Successful in 1m28s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (Release) (push) Successful in 1m56s
linux-arm-gcc / linux-gcc-arm (Debug) (push) Successful in 1m43s
linux-arm-gcc / linux-gcc-arm (Release) (push) Successful in 1m40s
linux-arm-gcc / linux-gcc-armhf (Debug) (push) Successful in 1m59s
linux-arm-gcc / linux-gcc-armhf (Release) (push) Successful in 1m51s
linux-mips-gcc / linux-gcc-mipsel (Debug) (push) Successful in 1m32s
linux-mips-gcc / linux-gcc-mipsel (Release) (push) Successful in 1m38s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m27s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 1m41s
linux-riscv64-gcc / linux-gcc-riscv64 (Debug) (push) Successful in 3m17s
linux-riscv64-gcc / linux-gcc-riscv64 (Release) (push) Successful in 1m45s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m10s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m26s
linux-x86-gcc / linux-gcc (Debug) (push) Successful in 2m35s
linux-x86-gcc / linux-gcc (Release) (push) Successful in 2m29s
Reviewed-on: #3
This commit is contained in:
parent
e20809aacc
commit
9453a7cc55
@ -268,17 +268,21 @@ if(TILE_BUILD_TESTS)
|
||||
|
||||
add_executable(tile_test_all "tile/testing/main.cc")
|
||||
target_link_libraries(tile_test_all PRIVATE gtest gmock tile::tile)
|
||||
|
||||
macro(tile_add_test test_name test_file)
|
||||
|
||||
macro(tile_add_custom_test test_name test_file)
|
||||
add_executable(${test_name} ${test_file} "tile/testing/main.cc")
|
||||
target_link_libraries(
|
||||
${test_name} PUBLIC gtest gmock ${WHOLE_ARCHIVE_PREFIX} tile::tile
|
||||
${WHOLE_ARCHIVE_SUFFIX})
|
||||
add_test(NAME ${test_name} COMMAND ${test_name})
|
||||
|
||||
target_sources(${PROJECT_NAME}_test_all PRIVATE ${test_file})
|
||||
endmacro()
|
||||
|
||||
macro(tile_add_test test_name test_file)
|
||||
tile_add_custom_test(${test_name} ${test_file})
|
||||
add_test(NAME ${test_name} COMMAND ${test_name})
|
||||
endmacro()
|
||||
|
||||
tile_add_test(fiber_detail_scheduler_test "tile/fiber/detail/scheduler_test.cc")
|
||||
tile_add_test(base_internal_meta_test "tile/base/internal/meta_test.cc")
|
||||
# tile_add_test(net_internal_http_engine_test
|
||||
@ -348,6 +352,7 @@ tile_add_test(fiber_detail_scheduler_test "tile/fiber/detail/scheduler_test.cc")
|
||||
tile_add_test(base_internal_logging_test "tile/base/internal/logging_test.cc")
|
||||
tile_add_test(base_chrono_test "tile/base/chrono_test.cc")
|
||||
tile_add_test(init_override_flag_test "tile/init/override_flag_test.cc")
|
||||
tile_add_custom_test("custom_http_client_test" "tests/http_client_test.cc")
|
||||
# tile_add_test(base_internal_time_keeper_test
|
||||
# "tile/base/internal/time_keeper_test.cc")
|
||||
endif(TILE_BUILD_TESTS)
|
||||
|
85
tests/http_client_test.cc
Normal file
85
tests/http_client_test.cc
Normal file
@ -0,0 +1,85 @@
|
||||
#include "tile/net/http/http_client.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "tile/base/thread/latch.h"
|
||||
|
||||
const std::string url = "http://127.0.0.1:8000/";
|
||||
|
||||
TEST(HttpClient, Request) {
|
||||
tile::HttpClient client;
|
||||
std::vector<tile::Future<
|
||||
std::expected<tile::HttpResponse, tile::HttpClient::ErrorCode>>>
|
||||
v;
|
||||
tile::HttpClient::RequestOptions options;
|
||||
options.timeout = std::chrono::seconds(20);
|
||||
|
||||
std::atomic<int> count{0};
|
||||
|
||||
for (int i = 0; i != 1000; ++i) {
|
||||
for (auto code : tile::AllHttpStatus) {
|
||||
if (static_cast<int>(code) < 200) {
|
||||
continue;
|
||||
}
|
||||
|
||||
v.emplace_back(
|
||||
client.AsyncGet(url + std::to_string(static_cast<int>(code)), options)
|
||||
.Then([&](std::expected<tile::HttpResponse,
|
||||
tile::HttpClient::ErrorCode> &&res) {
|
||||
int cnt = count.fetch_add(1) + 1;
|
||||
TILE_LOG_INFO_EVERY_SECOND("complete {}", cnt);
|
||||
return res;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i != 1000; ++i) {
|
||||
for (auto &code : tile::AllHttpStatus) {
|
||||
if (static_cast<int>(code) < 200) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto resp = tile::future::BlockingGet(std::move(v[j++]));
|
||||
|
||||
EXPECT_TRUE(resp) << tile::HttpClient::ErrorCodeToString(resp.error());
|
||||
EXPECT_EQ(resp->status(), code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HttpClient, RequestNoWait) {
|
||||
tile::HttpClient client;
|
||||
tile::HttpClient::RequestOptions options;
|
||||
options.timeout = std::chrono::seconds(20);
|
||||
int cnt = 0;
|
||||
|
||||
for (int i = 0; i != 1000; ++i) {
|
||||
for (auto code : tile::AllHttpStatus) {
|
||||
if (static_cast<int>(code) < 200) {
|
||||
continue;
|
||||
}
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
tile::Latch latch(cnt);
|
||||
std::atomic<int> count{0};
|
||||
|
||||
for (int i = 0; i != 1000; ++i) {
|
||||
for (auto code : tile::AllHttpStatus) {
|
||||
if (static_cast<int>(code) < 200) {
|
||||
continue;
|
||||
}
|
||||
|
||||
client.AsyncGet(url + std::to_string(static_cast<int>(code)), options)
|
||||
.Then([&](std::expected<tile::HttpResponse,
|
||||
tile::HttpClient::ErrorCode> &&) {
|
||||
int cnt = count.fetch_add(1) + 1;
|
||||
TILE_LOG_INFO_EVERY_SECOND("complete {}", cnt);
|
||||
latch.CountDown();
|
||||
});
|
||||
}
|
||||
}
|
||||
latch.Wait();
|
||||
}
|
24
tests/http_server.py
Normal file
24
tests/http_server.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python3
|
||||
import http.server
|
||||
import socket
|
||||
import socketserver
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
PORT = 8000
|
||||
|
||||
class Request(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
code = int(self.path.split("/")[1])
|
||||
|
||||
self.send_response(code)
|
||||
self.send_header('Content-type', 'text/plain')
|
||||
self.end_headers()
|
||||
|
||||
class HTTPServer(socketserver.TCPServer):
|
||||
def server_bind(self):
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.socket.bind(self.server_address)
|
||||
|
||||
Handler = http.server.SimpleHTTPRequestHandler
|
||||
with HTTPServer(("", PORT), Request) as httpd:
|
||||
httpd.serve_forever()
|
@ -21,7 +21,7 @@ make_unique(Args &&...args) {
|
||||
template <typename T>
|
||||
inline enable_if_t<std::is_array<T>::value && std::extent<T>::value == 0,
|
||||
std::unique_ptr<T>>
|
||||
make_unique(size_t size) {
|
||||
make_unique(std::size_t size) {
|
||||
TILE_DCHECK(size > 0);
|
||||
using U = typename std::remove_extent<T>::type;
|
||||
return std::unique_ptr<T>(new U[size]());
|
||||
@ -34,6 +34,29 @@ enable_if_t<std::is_array<T>::value && std::extent<T>::value != 0,
|
||||
std::unique_ptr<T>>
|
||||
make_unique(Args &&...) = delete;
|
||||
|
||||
// == With Deleter
|
||||
|
||||
template <typename T, typename D, typename... Args>
|
||||
inline enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, D>>
|
||||
make_unique_with_deleter(D &&deleter, Args &&...args) {
|
||||
return std::unique_ptr<T, D>(new T(std::forward<Args>(args)...),
|
||||
std::forward<D>(deleter));
|
||||
}
|
||||
|
||||
template <typename T, typename D>
|
||||
inline enable_if_t<std::is_array<T>::value && std::extent<T>::value == 0,
|
||||
std::unique_ptr<T, D>>
|
||||
make_unique_with_deleter(D &&deleter, std::size_t size) {
|
||||
TILE_DCHECK(size > 0);
|
||||
using U = typename std::remove_extent<T>::type;
|
||||
return std::unique_ptr<T, D>(new U[size](), std::forward<D>(deleter));
|
||||
}
|
||||
|
||||
template <typename T, typename D, typename... Args>
|
||||
enable_if_t<std::is_array<T>::value && std::extent<T>::value != 0,
|
||||
std::unique_ptr<T, D>>
|
||||
make_unique_with_deleter(D &&deleter, Args &&...) = delete;
|
||||
|
||||
} // namespace tile
|
||||
|
||||
#endif // TILE_BASE_MAKE_UNIQUE_H
|
||||
|
@ -83,6 +83,7 @@ void RegisterOnInitCallback(std::int32_t priority, std::function<void()> init,
|
||||
!registry_prepared.load(std::memory_order_relaxed),
|
||||
"Callbacks may only be registered before `tile::Start()` is called");
|
||||
auto &®istry = *GetStagingRegistry();
|
||||
TILE_CHECK(init != nullptr, "Initializer must be provided");
|
||||
registry[priority].push_back({std::move(init), std::move(fini)});
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,15 @@ HttpClient::ErrorCode GetErrorCodeFromCurlCode(int c) {
|
||||
return HttpClient::ERROR_IO;
|
||||
case CURLE_TOO_MANY_REDIRECTS:
|
||||
return HttpClient::ERROR_TOO_MANY_REDIRECTS;
|
||||
default:
|
||||
TILE_LOG_WARNING_EVERY_SECOND("ERROR_UNKNOWN CURLcode {}", c);
|
||||
case CURLE_GOT_NOTHING:
|
||||
return HttpClient::ERROR_GET_NOTHING;
|
||||
|
||||
default: {
|
||||
TILE_LOG_WARNING_EVERY_SECOND("ERROR_UNKNOWN CURLcode {}, curl msg: ", c,
|
||||
curl_easy_strerror(static_cast<CURLcode>(c)));
|
||||
return HttpClient::ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long TileHttpVersionToCurlHttpVersion(HttpVersion v,
|
||||
@ -446,6 +451,8 @@ const char *HttpClient::ErrorCodeToString(int error_code) {
|
||||
return "ERROR_INTERNAL_ERROR";
|
||||
case ERROR_DRY_RUN:
|
||||
return "ERROR_DRY_RUN";
|
||||
case ERROR_GET_NOTHING:
|
||||
return "ERROR_GET_NOTHING";
|
||||
case ERROR_UNKNOWN:
|
||||
return "<Unknown>";
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "gflags/gflags_declare.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
DECLARE_int32(tile_http_client_default_timeout_ms);
|
||||
|
||||
namespace tile {
|
||||
@ -45,6 +47,7 @@ public:
|
||||
ERROR_IO,
|
||||
ERROR_INTERNAL_ERROR,
|
||||
ERROR_DRY_RUN,
|
||||
ERROR_GET_NOTHING,
|
||||
ERROR_UNKNOWN = 100,
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,7 @@ Get(const std::string &url, std::chrono::nanoseconds timeout = 20 * one_s) {
|
||||
bool IsWanAccessible() {
|
||||
static const auto kResult = /*!!Get("http://baidu.com") &&
|
||||
!!Get("http://qq.com") &&*/
|
||||
!!Get("http://example.com");
|
||||
!!Get("http://www.baidu.com");
|
||||
return kResult;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ TEST(HttpClient, TestDomain) {
|
||||
TILE_LOG_INFO("WAN is not accessible, skip this test");
|
||||
return;
|
||||
}
|
||||
auto resp = Get("http://example.com");
|
||||
auto resp = Get("http://www.baidu.com");
|
||||
ASSERT_TRUE(resp);
|
||||
EXPECT_EQ(HttpStatus(200), resp->status());
|
||||
}
|
||||
@ -53,7 +53,7 @@ TEST(HttpClient, TestNotFound) {
|
||||
TILE_LOG_INFO("WAN is not accessible, skip this test");
|
||||
return;
|
||||
}
|
||||
auto resp = Get("http://example.com/404");
|
||||
auto resp = Get("http://www.baidu.com/404");
|
||||
ASSERT_TRUE(resp);
|
||||
EXPECT_EQ(HttpStatus(404), resp->status());
|
||||
}
|
||||
|
@ -79,6 +79,28 @@ enum class HttpStatus { // `HttpStatusCode`?
|
||||
NetworkAuthenticationRequired = 511
|
||||
};
|
||||
|
||||
// AllHttpStatus for for_each
|
||||
static HttpStatus AllHttpStatus[] = {
|
||||
HttpStatus::Continue,
|
||||
HttpStatus::SwitchingProtocols,
|
||||
HttpStatus::EarlyHints,
|
||||
HttpStatus::OK,
|
||||
HttpStatus::Created,
|
||||
HttpStatus::Accepted,
|
||||
HttpStatus::NonAuthoritativeInformation,
|
||||
HttpStatus::NoContent,
|
||||
HttpStatus::ResetContent,
|
||||
HttpStatus::PartialContent,
|
||||
HttpStatus::MultipleChoices,
|
||||
HttpStatus::MovedPermanently,
|
||||
HttpStatus::Found,
|
||||
HttpStatus::SeeOther,
|
||||
HttpStatus::NotModified,
|
||||
HttpStatus::TemporaryRedirect,
|
||||
HttpStatus::PermanentRedirect,
|
||||
HttpStatus::BadRequest,
|
||||
};
|
||||
|
||||
Slice ToSlice(HttpVersion method) noexcept;
|
||||
Slice ToSlice(HttpMethod) noexcept;
|
||||
Slice ToSlice(HttpStatus status) noexcept;
|
||||
|
@ -267,6 +267,10 @@ public:
|
||||
for (auto &&c : clients_) {
|
||||
c->Stop();
|
||||
}
|
||||
|
||||
for (auto &&c : clients_) {
|
||||
c.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user