Skip to content

Commit

Permalink
[WIP] Implement more tests
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Nov 21, 2023
1 parent 14889ae commit 9d1e12b
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/http/include/sourcemeta/hydra/http_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class SOURCEMETA_HYDRA_HTTP_EXPORT Request {
auto capture(std::string header) -> void;
auto capture(std::initializer_list<std::string> headers) -> void;
auto header(std::string_view key, std::string_view value) -> void;
auto header(std::string_view key, int value) -> void;

auto send() -> std::future<Response>;

private:
Expand Down
1 change: 1 addition & 0 deletions src/http/include/sourcemeta/hydra/http_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class SOURCEMETA_HYDRA_HTTP_EXPORT Response {

auto status() const noexcept -> Status;
auto header(const std::string &key) const -> std::optional<std::string>;
auto empty() noexcept -> bool;
auto body() -> std::istringstream &;

private:
Expand Down
4 changes: 4 additions & 0 deletions src/http/request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ auto Request::header(std::string_view key, std::string_view value) -> void {
this->stream.header(key, value);
}

auto Request::header(std::string_view key, int value) -> void {
this->stream.header(key, std::to_string(value));
}

auto Request::send() -> std::future<Response> {
std::ostringstream output;
this->stream.on_data(
Expand Down
8 changes: 7 additions & 1 deletion src/http/response.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <sourcemeta/hydra/http_response.h>
#include <sourcemeta/hydra/http_status.h>

#include <cassert> // assert
#include <map> // std::map
#include <optional> // std::optional, std::nullopt
#include <sstream> // std::ostringstream, std::istringstream
Expand All @@ -26,6 +27,11 @@ auto Response::header(const std::string &key) const
return this->headers_.at(key);
}

auto Response::body() -> std::istringstream & { return this->stream_; }
auto Response::empty() noexcept -> bool { return this->stream_.peek() == -1; }

auto Response::body() -> std::istringstream & {
assert(!this->empty());
return this->stream_;
}

} // namespace sourcemeta::hydra::http
115 changes: 114 additions & 1 deletion test/http/request_1_1_test.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,124 @@
#include <algorithm>
#include <iterator>
#include <sstream>
#include <string>

#include <gtest/gtest.h>
#include <sourcemeta/hydra/http.h>

// TODO: Add more tests
// - Request body
// - Response body
// - Request header
// - Response header with capture
// - Response header without capture
// - Response header with partial intersection capture

static auto body(sourcemeta::hydra::http::Response &response) -> std::string {
std::ostringstream result;
std::copy(
std::istreambuf_iterator<std::ostringstream::char_type>(response.body()),
std::istreambuf_iterator<std::ostringstream::char_type>(),
std::ostreambuf_iterator<std::ostringstream::char_type>(result));
return result.str();
}

TEST(HTTP_Request_1_1, XXX) {
TEST(HTTP_Request_1_1, GET_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::GET);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED GET /");
}

TEST(HTTP_Request_1_1, HEAD_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::HEAD);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_TRUE(response.empty());
}

TEST(HTTP_Request_1_1, POST_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::POST);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED POST /");
}

TEST(HTTP_Request_1_1, PUT_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::PUT);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED PUT /");
}

TEST(HTTP_Request_1_1, DELETE_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::DELETE);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED DELETE /");
}

TEST(HTTP_Request_1_1, OPTIONS_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::OPTIONS);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED OPTIONS /");
}

TEST(HTTP_Request_1_1, TRACE_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::TRACE);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED TRACE /");
}

TEST(HTTP_Request_1_1, PATCH_root) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::PATCH);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED PATCH /");
}

TEST(HTTP_Request_1_1, GET_root_foo_bar) {
sourcemeta::hydra::http::Request request{std::string{BASE_URL} + "/foo/bar"};
request.method(sourcemeta::hydra::http::Method::GET);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::OK);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED GET /foo/bar");
}

TEST(HTTP_Request_1_1, GET_root_custom_code_string) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::GET);
request.header("X-Code", "400");
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::BAD_REQUEST);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED GET /");
}

TEST(HTTP_Request_1_1, GET_root_custom_code_integer) {
sourcemeta::hydra::http::Request request{BASE_URL};
request.method(sourcemeta::hydra::http::Method::GET);
request.header("X-Code", 400);
sourcemeta::hydra::http::Response response{request.send().get()};
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::BAD_REQUEST);
EXPECT_FALSE(response.empty());
EXPECT_EQ(body(response), "RECEIVED GET /");
}
25 changes: 11 additions & 14 deletions test/http/stub.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
const http = require('http');
const PORT = 9999;

const server = http.createServer((req, res) => {
// Set the response header to indicate JSON content
res.setHeader('Content-Type', 'application/json');

// Define a simple JSON response
const jsonResponse = {
message: 'Hello, JSON World!',
timestamp: new Date().toISOString(),
};
http.createServer((request, response) => {
for (const [key, value] of Object.entries(request.headers)) {
response.setHeader(`X-${key}`, value);
}

// Send the JSON response
res.end(JSON.stringify(jsonResponse));
});
if (request.headers['x-code']) {
response.statusCode = parseInt(request.headers['x-code'], 10);
}

const PORT = 9999;
server.listen(PORT, () => {
response.setHeader('Content-Type', 'text/plain');
response.end(`RECEIVED ${request.method} ${request.url}`);
}).listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});

0 comments on commit 9d1e12b

Please sign in to comment.