forked from vesoft-inc/nebula
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add fake http server * add http client ut * remove some useless code Co-authored-by: Sophie <[email protected]>
- Loading branch information
1 parent
c3048bc
commit 4f1fe76
Showing
5 changed files
with
220 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,95 +1,54 @@ | ||
/* Copyright (c) 2019 vesoft inc. All rights reserved. | ||
/* Copyright (c) 2022 vesoft inc. All rights reserved. | ||
* | ||
* This source code is licensed under Apache 2.0 License. | ||
*/ | ||
|
||
#include <gtest/gtest.h> | ||
#include <proxygen/httpserver/RequestHandler.h> | ||
#include <proxygen/httpserver/ResponseBuilder.h> | ||
|
||
#include "common/http/HttpClient.h" | ||
#include "webservice/Common.h" | ||
#include "webservice/Router.h" | ||
#include "webservice/WebService.h" | ||
#include "gtest/gtest.h" | ||
#include "mock/FakeHttpServer.h" | ||
|
||
namespace nebula { | ||
namespace http { | ||
|
||
class HttpClientHandler : public proxygen::RequestHandler { | ||
public: | ||
HttpClientHandler() = default; | ||
|
||
void onRequest(std::unique_ptr<proxygen::HTTPMessage>) noexcept override {} | ||
|
||
void onBody(std::unique_ptr<folly::IOBuf>) noexcept override {} | ||
|
||
void onEOM() noexcept override { | ||
proxygen::ResponseBuilder(downstream_) | ||
.status(WebServiceUtils::to(HttpStatusCode::OK), | ||
WebServiceUtils::toString(HttpStatusCode::OK)) | ||
.body("HttpClientHandler successfully") | ||
.sendWithEOM(); | ||
} | ||
|
||
void onUpgrade(proxygen::UpgradeProtocol) noexcept override {} | ||
|
||
void requestComplete() noexcept override { | ||
delete this; | ||
} | ||
|
||
void onError(proxygen::ProxygenError error) noexcept override { | ||
LOG(ERROR) << "HttpClientHandler Error: " << proxygen::getErrorString(error); | ||
} | ||
}; | ||
class HttpClientTestEnv : public ::testing::Environment { | ||
public: | ||
void SetUp() override { | ||
FLAGS_ws_ip = "127.0.0.1"; | ||
FLAGS_ws_http_port = 0; | ||
LOG(INFO) << "Starting web service..."; | ||
webSvc_ = std::make_unique<WebService>(); | ||
class HTTPClientTest : public ::testing::Test {}; | ||
|
||
auto& router = webSvc_->router(); | ||
router.get("/path").handler([](auto&&) { return new HttpClientHandler(); }); | ||
|
||
auto status = webSvc_->start(); | ||
ASSERT_TRUE(status.ok()) << status; | ||
} | ||
TEST_F(HTTPClientTest, GET) { | ||
FakeHttpServer server(3659); | ||
server.start(); | ||
auto resp = HttpClient::get("http://localhost:3659"); | ||
ASSERT_EQ(resp.curlCode, 0) << resp.curlMessage; | ||
ASSERT_EQ(resp.body, "GET"); | ||
server.stop(); | ||
server.join(); | ||
} | ||
|
||
void TearDown() override { | ||
webSvc_.reset(); | ||
VLOG(1) << "Web service stopped"; | ||
} | ||
TEST_F(HTTPClientTest, POST) { | ||
FakeHttpServer server(3660); | ||
server.start(); | ||
auto resp = HttpClient::post("http://localhost:3660", {}, ""); | ||
ASSERT_EQ(resp.curlCode, 0) << resp.curlMessage; | ||
ASSERT_EQ(resp.body, "POST"); | ||
server.stop(); | ||
server.join(); | ||
} | ||
|
||
private: | ||
std::unique_ptr<WebService> webSvc_; | ||
}; | ||
TEST_F(HTTPClientTest, DELETE) { | ||
FakeHttpServer server(3661); | ||
server.start(); | ||
auto resp = HttpClient::delete_("http://localhost:3661", {}); | ||
ASSERT_EQ(resp.curlCode, 0) << resp.curlMessage; | ||
ASSERT_EQ(resp.body, "DELETE"); | ||
server.stop(); | ||
server.join(); | ||
} | ||
|
||
TEST(HttpClient, get) { | ||
{ | ||
auto url = | ||
folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), FLAGS_ws_http_port, "/path"); | ||
auto httpResp = HttpClient::get(url); | ||
ASSERT_EQ(httpResp.curlCode, 0); | ||
ASSERT_EQ("HttpClientHandler successfully", httpResp.body); | ||
} | ||
{ | ||
auto url = folly::stringPrintf( | ||
"http://%s:%d%s", FLAGS_ws_ip.c_str(), FLAGS_ws_http_port, "/not_exist"); | ||
auto httpResp = HttpClient::get(url); | ||
ASSERT_EQ(httpResp.curlCode, 0); | ||
ASSERT_TRUE(httpResp.body.empty()); | ||
} | ||
TEST_F(HTTPClientTest, PUT) { | ||
FakeHttpServer server(3662); | ||
server.start(); | ||
auto resp = HttpClient::put("http://localhost:3662", {}, ""); | ||
ASSERT_EQ(resp.curlCode, 0) << resp.curlMessage; | ||
ASSERT_EQ(resp.body, "PUT"); | ||
server.stop(); | ||
server.join(); | ||
} | ||
|
||
} // namespace http | ||
} // namespace nebula | ||
|
||
int main(int argc, char** argv) { | ||
testing::InitGoogleTest(&argc, argv); | ||
folly::init(&argc, &argv, true); | ||
google::SetStderrLogging(google::INFO); | ||
|
||
::testing::AddGlobalTestEnvironment(new nebula::http::HttpClientTestEnv()); | ||
return RUN_ALL_TESTS(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,7 @@ nebula_add_library( | |
) | ||
|
||
|
||
nebula_add_library( | ||
fake_http_server_obj OBJECT | ||
FakeHttpServer.cpp | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* Copyright (c) 2022 vesoft inc. All rights reserved. | ||
* | ||
* This source code is licensed under Apache 2.0 License. | ||
*/ | ||
#include "mock/FakeHttpServer.h" | ||
|
||
#include "folly/synchronization/Baton.h" | ||
#include "glog/logging.h" | ||
#include "proxygen/httpserver/HTTPServer.h" | ||
#include "proxygen/httpserver/HTTPServerOptions.h" | ||
#include "proxygen/httpserver/ResponseBuilder.h" | ||
|
||
namespace nebula { | ||
|
||
void FakeHttpHandler::onRequest(std::unique_ptr<proxygen::HTTPMessage> message) noexcept { | ||
CHECK(message->getMethod()); | ||
method_ = message->getMethod().value(); | ||
auto headers = message->extractHeaders(); | ||
headers.forEach( | ||
[this](std::string name, std::string value) { this->headers_.emplace_back(name, value); }); | ||
} | ||
|
||
void FakeHttpHandler::onBody(std::unique_ptr<folly::IOBuf> buf) noexcept { | ||
if (body_) { | ||
body_->appendChain(std::move(buf)); | ||
} else { | ||
body_ = std::move(buf); | ||
} | ||
} | ||
|
||
void FakeHttpHandler::onEOM() noexcept { | ||
std::tuple<int, std::map<std::string, std::string>, std::string> result; | ||
switch (method_) { | ||
case ::proxygen::HTTPMethod::PUT: | ||
result = onPut(); | ||
break; | ||
case ::proxygen::HTTPMethod::GET: | ||
result = onGet(); | ||
break; | ||
case ::proxygen::HTTPMethod::POST: | ||
result = onPost(); | ||
break; | ||
case ::proxygen::HTTPMethod::DELETE: | ||
result = onDelete(); | ||
break; | ||
default: | ||
CHECK(false); | ||
break; | ||
} | ||
auto builder = ::proxygen::ResponseBuilder(downstream_); | ||
builder.status(std::get<0>(result), ""); | ||
for (auto& [name, value] : std::get<1>(result)) { | ||
builder.header(name, value); | ||
} | ||
builder.body(std::get<2>(result)); | ||
builder.sendWithEOM(); | ||
} | ||
|
||
void FakeHttpHandler::onUpgrade(proxygen::UpgradeProtocol) noexcept { | ||
// Do nothing | ||
} | ||
|
||
void FakeHttpHandler::requestComplete() noexcept { | ||
delete this; | ||
} | ||
|
||
void FakeHttpHandler::onError(proxygen::ProxygenError err) noexcept { | ||
LOG(FATAL) << ::proxygen::getErrorString(err); | ||
} | ||
|
||
FakeHttpServer::FakeHttpServer(int port) : port_(port) {} | ||
|
||
void FakeHttpServer::start() { | ||
::proxygen::HTTPServerOptions options; | ||
options.threads = 2; | ||
options.idleTimeout = std::chrono::milliseconds(60000); | ||
options.enableContentCompression = false; | ||
options.handlerFactories = | ||
proxygen::RequestHandlerChain().addThen<FakeHttpHandlerFactory>().build(); | ||
options.h2cEnabled = true; | ||
|
||
server_ = std::make_unique<::proxygen::HTTPServer>(std::move(options)); | ||
std::vector<::proxygen::HTTPServer::IPConfig> ipconfig = { | ||
{folly::SocketAddress("127.0.0.1", port_, true), ::proxygen::HTTPServer::Protocol::HTTP}}; | ||
|
||
server_->bind(ipconfig); | ||
folly::Baton baton; | ||
t_ = std::thread([this, &baton]() { this->server_->start([&baton]() { baton.post(); }); }); | ||
baton.wait(); | ||
} | ||
|
||
void FakeHttpServer::stop() { | ||
server_->stop(); | ||
} | ||
|
||
void FakeHttpServer::join() { | ||
t_.join(); | ||
} | ||
|
||
} // namespace nebula |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* Copyright (c) 2022 vesoft inc. All rights reserved. | ||
* | ||
* This source code is licensed under Apache 2.0 License. | ||
*/ | ||
|
||
#ifndef MOCK_FAKEHTTPSERVER_H_ | ||
#define MOCK_FAKEHTTPSERVER_H_ | ||
#include <vector> | ||
|
||
#include "proxygen/httpserver/HTTPServer.h" | ||
#include "proxygen/httpserver/RequestHandler.h" | ||
#include "proxygen/httpserver/RequestHandlerFactory.h" | ||
namespace nebula { | ||
|
||
class FakeHttpHandler : public proxygen::RequestHandler { | ||
public: | ||
void onRequest(std::unique_ptr<proxygen::HTTPMessage> headers) noexcept override; | ||
|
||
void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override; | ||
|
||
void onEOM() noexcept override; | ||
|
||
void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override; | ||
|
||
void requestComplete() noexcept override; | ||
|
||
void onError(proxygen::ProxygenError err) noexcept override; | ||
|
||
private: | ||
std::vector<std::pair<std::string, std::string>> headers_; | ||
std::unique_ptr<folly::IOBuf> body_; | ||
::proxygen::HTTPMethod method_; | ||
|
||
virtual std::tuple<int, std::map<std::string, std::string>, std::string> onPut() { | ||
return {200, {}, "PUT"}; | ||
} | ||
virtual std::tuple<int, std::map<std::string, std::string>, std::string> onGet() { | ||
return {200, {}, "GET"}; | ||
} | ||
virtual std::tuple<int, std::map<std::string, std::string>, std::string> onDelete() { | ||
return {200, {}, "DELETE"}; | ||
} | ||
virtual std::tuple<int, std::map<std::string, std::string>, std::string> onPost() { | ||
return {200, {}, "POST"}; | ||
} | ||
}; | ||
|
||
class FakeHttpHandlerFactory : public ::proxygen::RequestHandlerFactory { | ||
public: | ||
void onServerStart(folly::EventBase*) noexcept override {} | ||
|
||
void onServerStop() noexcept override {} | ||
|
||
::proxygen::RequestHandler* onRequest(::proxygen::RequestHandler*, | ||
::proxygen::HTTPMessage*) noexcept override { | ||
return new FakeHttpHandler(); | ||
} | ||
}; | ||
|
||
class FakeHttpServer { | ||
public: | ||
explicit FakeHttpServer(int port); | ||
void start(); | ||
void stop(); | ||
void join(); | ||
|
||
private: | ||
int port_; | ||
std::thread t_; | ||
std::unique_ptr<::proxygen::HTTPServer> server_ = nullptr; | ||
}; | ||
|
||
} // namespace nebula | ||
|
||
#endif |