Commit 0d9cf747 authored by Ian Roddis's avatar Ian Roddis

Using forks to avoid shared global state between endpoints and clients

parent 65c3ce4a
...@@ -28,20 +28,16 @@ struct TestSet { ...@@ -28,20 +28,16 @@ struct TestSet {
typedef std::vector<TestSet> PayloadTestSets; typedef std::vector<TestSet> PayloadTestSets;
void testPayloads(std::string url, PayloadTestSets & testPayloads) { static const uint16_t PORT = 9080;
void testPayloads(Http::Client & client, std::string url, PayloadTestSets & testPayloads) {
// Client tests to make sure the payload is enforced // Client tests to make sure the payload is enforced
std::mutex resultsetMutex; std::mutex resultsetMutex;
PayloadTestSets test_results; PayloadTestSets test_results;
Http::Client client; std::vector<Async::Promise<Http::Response> > responses;
auto client_opts = Http::Client::options()
.threads(1)
.maxConnectionsPerHost(1);
client.init(client_opts);
auto rb = client.post(url);
for (auto & t : testPayloads) { for (auto & t : testPayloads) {
std::string payload(t.bytes, 'A'); std::string payload(t.bytes, 'A');
std::vector<Async::Promise<Http::Response> > responses; auto response = client.post(url).body(payload).send();
auto response = rb.body(payload).send();
response.then([t,&test_results,&resultsetMutex](Http::Response rsp) { response.then([t,&test_results,&resultsetMutex](Http::Response rsp) {
TestSet res(t); TestSet res(t);
res.actualCode = rsp.code(); res.actualCode = rsp.code();
...@@ -51,11 +47,11 @@ void testPayloads(std::string url, PayloadTestSets & testPayloads) { ...@@ -51,11 +47,11 @@ void testPayloads(std::string url, PayloadTestSets & testPayloads) {
} }
}, Async::IgnoreException); }, Async::IgnoreException);
responses.push_back(std::move(response)); responses.push_back(std::move(response));
}
auto sync = Async::whenAll(responses.begin(), responses.end()); auto sync = Async::whenAll(responses.begin(), responses.end());
Async::Barrier<std::vector<Http::Response>> barrier(sync); Async::Barrier<std::vector<Http::Response>> barrier(sync);
barrier.wait_for(std::chrono::seconds(5)); barrier.wait_for(std::chrono::milliseconds(500));
}
client.shutdown();
for (auto & result : test_results) { for (auto & result : test_results) {
ASSERT_EQ(result.expectedCode, result.actualCode); ASSERT_EQ(result.expectedCode, result.actualCode);
...@@ -63,21 +59,30 @@ void testPayloads(std::string url, PayloadTestSets & testPayloads) { ...@@ -63,21 +59,30 @@ void testPayloads(std::string url, PayloadTestSets & testPayloads) {
} }
void handleEcho(const Rest::Request&req, Http::ResponseWriter response) { void handleEcho(const Rest::Request&req, Http::ResponseWriter response) {
response.send(Http::Code::Ok, req.body(), MIME(Text, Plain)); UNUSED(req);
response.send(Http::Code::Ok, "", MIME(Text, Plain));
} }
TEST(payload_test, from_description) TEST(payload, from_description)
{ {
Address addr(Ipv4::any(), 9084); Http::Client client;
auto client_opts = Http::Client::options()
.threads(3)
.maxConnectionsPerHost(3);
client.init(client_opts);
Address addr(Ipv4::any(), 9080);
const size_t threads = 20; const size_t threads = 20;
const size_t maxPayload = 1024; // very small const size_t maxPayload = 1024; // very small
auto pid = fork();
if ( pid == 0) {
std::shared_ptr<Http::Endpoint> endpoint; std::shared_ptr<Http::Endpoint> endpoint;
Rest::Description desc("Rest Description Test", "v1"); Rest::Description desc("Rest Description Test", "v1");
Rest::Router router; Rest::Router router;
desc desc
.route(desc.post("/echo")) .route(desc.post("/"))
.bind(&handleEcho) .bind(&handleEcho)
.response(Http::Code::Ok, "Response to the /ready call"); .response(Http::Code::Ok, "Response to the /ready call");
...@@ -94,56 +99,67 @@ TEST(payload_test, from_description) ...@@ -94,56 +99,67 @@ TEST(payload_test, from_description)
endpoint = std::make_shared<Pistache::Http::Endpoint>(addr); endpoint = std::make_shared<Pistache::Http::Endpoint>(addr);
endpoint->init(opts); endpoint->init(opts);
endpoint->setHandler(router.handler()); endpoint->setHandler(router.handler());
endpoint->serve();
endpoint->serveThreaded(); endpoint->shutdown();
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(150));
PayloadTestSets payloads{ PayloadTestSets payloads{
{800, Http::Code::Ok} {800, Http::Code::Ok}
, {1024, Http::Code::Request_Entity_Too_Large} , {1024, Http::Code::Request_Entity_Too_Large}
,{2048, Http::Code::Request_Entity_Too_Large} ,{2048, Http::Code::Request_Entity_Too_Large}
}; };
testPayloads("127.0.0.1:9084/echo", payloads); testPayloads(client, "127.0.0.1:" + std::to_string(PORT), payloads);
endpoint->shutdown(); kill(pid, SIGTERM);
int r;
waitpid(pid, &r, 0);
client.shutdown();
} }
TEST(payload_test, manual_construction) { TEST(payload, manual_construction) {
class MyHandler : public Http::Handler { class MyHandler : public Http::Handler {
public:
HTTP_PROTOTYPE(MyHandler) HTTP_PROTOTYPE(MyHandler)
void onRequest( void onRequest(
const Http::Request& req, const Http::Request& req,
Http::ResponseWriter response) Http::ResponseWriter response)
{ {
if (req.resource() == "/echo") { UNUSED(req);
if (req.method() == Http::Method::Post) { response.send(Http::Code::Ok, "All good");
response.send(Http::Code::Ok, req.body(), MIME(Text, Plain));
} else {
response.send(Http::Code::Method_Not_Allowed);
}
} else {
response.send(Http::Code::Not_Found);
}
} }
private: private:
tag placeholder; tag placeholder;
}; };
Port port(9080); Http::Client client;
int thr = 20; auto client_opts = Http::Client::options()
.threads(3)
.maxConnectionsPerHost(3);
client.init(client_opts);
Port port(PORT);
Address addr(Ipv4::any(), port); Address addr(Ipv4::any(), port);
auto endpoint = std::make_shared<Http::Endpoint>(addr); int threads = 20;
auto flags = Tcp::Options::InstallSignalHandler | Tcp::Options::ReuseAddr;
size_t maxPayload = 2048; size_t maxPayload = 2048;
auto pid = fork();
if (pid == 0) {
auto endpoint = std::make_shared<Http::Endpoint>(addr);
auto opts = Http::Endpoint::options() auto opts = Http::Endpoint::options()
.threads(thr) .threads(threads)
.flags(Tcp::Options::InstallSignalHandler) .flags(flags)
.maxPayload(maxPayload); .maxPayload(maxPayload);
;
endpoint->init(opts); endpoint->init(opts);
endpoint->setHandler(Http::make_handler<MyHandler>()); endpoint->setHandler(Http::make_handler<MyHandler>());
endpoint->serveThreaded(); endpoint->serve();
endpoint->shutdown();
return;
}
PayloadTestSets payloads{ PayloadTestSets payloads{
{1024, Http::Code::Ok} {1024, Http::Code::Ok}
...@@ -151,9 +167,11 @@ TEST(payload_test, manual_construction) { ...@@ -151,9 +167,11 @@ TEST(payload_test, manual_construction) {
, {2048, Http::Code::Request_Entity_Too_Large} , {2048, Http::Code::Request_Entity_Too_Large}
, {4096, Http::Code::Request_Entity_Too_Large} , {4096, Http::Code::Request_Entity_Too_Large}
}; };
testPayloads(client, "127.0.0.1:" + std::to_string(PORT), payloads);
testPayloads("127.0.0.1:9080/echo", payloads); // Cleanup
kill(pid, SIGTERM);
int r;
waitpid(pid, &r, 0);
client.shutdown();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment