Project

General

Profile

Bug #7093 » HttpClientServerTest.C

Marco Kinski, 07/03/2020 12:11 PM

 
/*
* Copyright (C) 2011 Emweb bv, Herent, Belgium.
*
* See the LICENSE file for terms of use.
*/
#include <Wt/WConfig.h>

#ifdef WT_THREADED

#include <boost/test/unit_test.hpp>

#include <Wt/WResource.h>
#include <Wt/WServer.h>
#include <Wt/WIOService.h>
#include <Wt/Http/Client.h>
#include <Wt/Http/Response.h>
#include <Wt/Http/ResponseContinuation.h>
#include <Wt/Http/Request.h>

#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>

using namespace Wt;

namespace {

class TestRecursive : public WResource {
public:
TestRecursive ()
{ }

virtual ~TestRecursive () {
beingDeleted();
}

virtual void handleRequest(const Http::Request& request,
Http::Response& response) override;

std::function<std::string(void)> address_;
};

class TestResource : public WResource
{
public:
TestResource()
: continuation_(false),
delaySendingBody_(false),
haveEverMoreData_(false),
haveRandomMoreData_(false),
aborted_(0)
{ }

virtual ~TestResource() {
beingDeleted();
}

void useContinuation() {
continuation_ = true;
}

void delaySendingBody() {
delaySendingBody_ = true;
}

void haveEverMoreData() {
haveEverMoreData_ = true;
}

void haveRandomMoreData() {
haveRandomMoreData_ = true;
}

int abortedCount() const {
return aborted_;
}

virtual void handleRequest(const Http::Request& request,
Http::Response& response) override
{
if (continuation_)
handleWithContinuation(request, response);
else
handleSimple(request, response);
}

virtual void handleAbort(const Http::Request& request) override
{
++aborted_;
}

private:
bool continuation_;
bool delaySendingBody_;
bool haveEverMoreData_;
bool haveRandomMoreData_;
int aborted_;

void handleSimple(const Http::Request& request,
Http::Response& response)
{
response.setStatus(200);
response.out() << "Hello";
}

void handleWithContinuation(const Http::Request& request,
Http::Response& response)
{
if (request.continuation()) {
response.out() << "Hello";
if (haveEverMoreData_ ||
(haveRandomMoreData_ && (rand() % 10 != 0)))
response.createContinuation();
} else {
response.setStatus(200);
Http::ResponseContinuation *c = response.createContinuation();
if (delaySendingBody_)
c->waitForMoreData();
}
}
};

class Server : public WServer
{
public:
Server() {
int argc = 7;
const char *argv[]
= { "test",
"--http-address", "127.0.0.1",
"--http-port", "0",
"--docroot", "."
};
setServerConfiguration(argc, (char **)argv);
addResource(&resource_, "/test");
addResource(&recursive_, "/recursive");

recursive_.address_ = std::bind(&Server::address, this);
}

std::string address()
{
return "127.0.0.1:" + std::to_string(httpPort());
}

TestResource& resource() { return resource_; }

private:
TestResource resource_;
TestRecursive recursive_;
};

class Client : public Http::Client
{
public:
Client()
: done_(false),
abortAfterHeaders_(false)
{
done().connect(this, &Client::onDone);
headersReceived().connect(this, &Client::onHeadersReceived);
bodyDataReceived().connect(this, &Client::onDataReceived);
}

void abortAfterHeaders()
{
abortAfterHeaders_ = true;
}

void waitDone()
{
std::unique_lock<std::mutex> guard(doneMutex_);

while (!done_)
doneCondition_.wait(guard);
}

void reset()
{
done_ = false;
}

bool isDone()
{
return done_;
}

void onDone(Wt::AsioWrapper::error_code err, const Http::Message& m)
{
std::unique_lock<std::mutex> guard(doneMutex_);

err_ = err;
message_ = m;

done_ = true;
doneCondition_.notify_one();
}

void onHeadersReceived(const Http::Message& m)
{
if (abortAfterHeaders_)
abort();
}

void onDataReceived(const std::string& d)
{
}

Wt::AsioWrapper::error_code err() { return err_; }
const Http::Message& message() { return message_; }

private:
bool done_;
bool abortAfterHeaders_;
std::condition_variable doneCondition_;
std::mutex doneMutex_;

Wt::AsioWrapper::error_code err_;
Http::Message message_;
};


void TestRecursive::handleRequest(const Http::Request& request,
Http::Response& response) {

Client client;
client.get("http://" + address_() + "/test");
client.waitDone();

response.out() << client.message().body();
}

}


BOOST_AUTO_TEST_CASE( http_client_server_recursive )
{
Server server;

if (server.start()) {
for (int i = 0; i < 1000; ++i) {
Client client;
client.get("http://" + server.address() + "/recursive");
client.waitDone();

BOOST_REQUIRE(!client.err());
BOOST_REQUIRE(client.message().status() == 200);
BOOST_REQUIRE(client.message().body() == "Hello");
}
}

}

#endif // WT_THREADED







(6-6/6)