Browse Source

torrents resources should now be available

master
Jørgen Lien Sellæg 9 years ago
parent
commit
0c0c40703a
  1. 16
      toREST/CMakeLists.txt
  2. 82
      toREST/src/main.cxx
  3. 23
      toREST/tests/http_test.cpp
  4. 116
      toREST/tests/session_test.cpp

16
toREST/CMakeLists.txt

@ -33,12 +33,12 @@ set(global_libraries
add_library(project_shared OBJECT ${source_files})
add_executable(${project_name} ./src/main.cxx $<TARGET_OBJECTS:project_shared>)
target_link_libraries(${project_name} ${global_libraries})
# add_executable(${project_name} ./src/main.cxx $<TARGET_OBJECTS:project_shared>)
# target_link_libraries(${project_name} ${global_libraries})
# enable_testing()
enable_testing()
# file(GLOB test_files "./tests/*.cpp")
file(GLOB test_files "./tests/*.cpp")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -Wall -fprofile-arcs -ftest-coverage ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -Wall -fprofile-arcs -ftest-coverage ")
@ -46,10 +46,10 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage ")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage ")
set(test test${project_name})
# add_executable(${test} ${test_files} $<TARGET_OBJECTS:project_shared>)
#target_include_directories(${test} PUBLIC ../lib/Catch)
#target_link_libraries(${test} ${global_libraries})
#add_test(${test} ${test})
add_executable(${test} ${test_files} $<TARGET_OBJECTS:project_shared>)
target_include_directories(${test} PUBLIC ../lib/Catch)
target_link_libraries(${test} ${global_libraries})
add_test(${test} ${test})
find_package(Doxygen)

82
toREST/src/main.cxx

@ -2,6 +2,7 @@
#include <http.hpp>
#include <session.hpp>
#include <libtorrent/session_stats.hpp>
#include <libtorrent/session_status.hpp>
#include <boost/filesystem.hpp>
typedef SimpleWeb::Server<SimpleWeb::HTTP> HttpServer;
@ -57,42 +58,65 @@ int main(int argc, char *argv[]) {
auto response_code = http::code(http::service_unavailable);
response.set_body({{response_code.first, response_code.second}});
response.set_status(response_code.first);
return;
}
const auto json=util::json::parse(req->content);
if(json.is_object() && !json.is_null()) {
if(util::json::get("paused",json,session.is_paused()))
session.pause();
else
session.resume();
auto settings = session.get_settings();
const auto new_listen_port=util::json::get("port",json,session.listen_port());
if(new_listen_port!=session.listen_port())
settings.set_str(settings.listen_interfaces,"0.0.0.0:"+std::to_string(new_listen_port));
const auto new_dht_enabled=util::json::get("dht_enabled",json,session.is_dht_running());
if(new_dht_enabled!=session.is_dht_running())
settings.set_bool(settings.enable_dht,new_dht_enabled);
auto old_limit=settings.get_int(settings.download_rate_limit);
auto new_limit=util::json::get("down_limit",json,old_limit);
if(new_limit!=old_limit)
settings.set_int(settings.download_rate_limit,new_limit);
old_limit=settings.get_int(settings.upload_rate_limit);
new_limit=util::json::get("up_limit",json,old_limit);
if(new_limit!=old_limit)
settings.set_int(settings.upload_rate_limit,new_limit);
session.apply_settings(settings);
} else {
auto response_code = http::code(http::bad_request);
response.set_body({{response_code.first,response_code.second}});
response.set_status(response_code.first);
const auto json=util::json::parse(req->content);
if(json.is_object() && !json.is_null()) {
if(util::json::get("paused",json,session.is_paused()))
session.pause();
else
session.resume();
auto settings = session.get_settings();
const auto new_listen_port=util::json::get("port",json,session.listen_port());
if(new_listen_port!=session.listen_port())
settings.set_str(settings.listen_interfaces,"0.0.0.0:"+std::to_string(new_listen_port));
const auto new_dht_enabled=util::json::get("dht_enabled",json,session.is_dht_running());
if(new_dht_enabled!=session.is_dht_running())
settings.set_bool(settings.enable_dht,new_dht_enabled);
auto old_limit=settings.get_int(settings.download_rate_limit);
auto new_limit=util::json::get("down_limit",json,old_limit);
if(new_limit!=old_limit)
settings.set_int(settings.download_rate_limit,new_limit);
old_limit=settings.get_int(settings.upload_rate_limit);
new_limit=util::json::get("up_limit",json,old_limit);
if(new_limit!=old_limit)
settings.set_int(settings.upload_rate_limit,new_limit);
session.apply_settings(settings);
response.set_body({{200,"OK"}});
} else {
auto response_code = http::code(http::bad_request);
response.set_body({{response_code.first,response_code.second}});
response.set_status(response_code.first);
}
}
*resp << response;
};
http_server.resource["^/session/torrents(\\?.*)?\\/?$"]["GET"]=[&session](std::shared_ptr<HttpServer::Response> resp, std::shared_ptr<HttpServer::Request> req) {
auto response = http::response();
if (session.is_valid()) {
response.set_body(nlohmann::json::object({{"torrents",nlohmann::json::array()}}));
if(session.is_valid()) {
auto torrents = session.get_torrents();
auto response_object = nlohmann::json::object();
auto torrents_json = nlohmann::json::array();
for(auto &torrent:torrents){
if(torrent.is_valid()){
const auto hash=torrent.info_hash().to_string();
const auto status=torrent.status(
libtorrent::torrent_handle::query_name |
libtorrent::torrent_handle::query_save_path
);
torrents_json.push_back({
{ "hash", hash },
{ "paused", status.paused },
{ "seeding", status.is_seeding },
{ "state", status.state },
{ "priority", status.priority },
{ "name",status.name }
});
}
}
response_object["torrents"] = torrents_json;
response.set_status(http::ok);
response.set_body(response_object);
} else {
auto response_code = http::code(http::service_unavailable);
response.set_body({{response_code.first, response_code.second}});

23
toREST/tests/http_test.cpp

@ -32,33 +32,30 @@ SCENARIO("http response"){
REQUIRE(ss.str()=="HTTP/1.1 204 No Content\r\n\r\n"s);
}
GIVEN("we stream our response with the body set"){
response.set_body("Easter eggs, everywhere! <a href=\"http://stream1.gifsoup.com/view4/4086928/x-x-everywhere-o.gif\">ye</a>");
response.set_body("Easter eggs, everywhere! <a href=\"http://stream1.gifsoup.com/view4/4086928/x-x-everywhere-o.gif\">ye</a>"s);
ss << response;
THEN("our response contains the appropriate headers")
REQUIRE(ss.str()=="HTTP/1.1 200 OK\r\nContent-Length: 103\r\n\r\nEaster eggs, everywhere! <a href=\"http://stream1.gifsoup.com/view4/4086928/x-x-everywhere-o.gif\">ye</a>"s);
}
GIVEN("we add a header to the resource"){
response.set_body("Nothing"s);
response.add_header(http::header("Strict-Error"s,"on"s));
ss << response;
THEN("our response contains the appropriate headers")
REQUIRE(ss.str()=="HTTP/1.1 200 OK\r\nStrict-Error: on\r\nContent-Length: 7\r\n\r\nNothing"s);
}
}
SCENARIO("Stream http responses with a json response"){
auto response=http::json_response();
auto response=http::response();
std::stringstream ss;
GIVEN("we stream our response without setting any options"){
ss << response;
THEN("our response is valid json and the response code is 200")
REQUIRE(ss.str()=="HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 26\r\n\r\n{\"code\":200,\"status\":\"OK\"}"s);
}
GIVEN("we set the response code to 404 and stream our response"){
response.set_status(http::not_found);
response.set_body({{"code",404},{"status","Not Found"}});
ss << response;
THEN("our response is valid json and the resoinse code is 404")
REQUIRE(ss.str()=="HTTP/1.1 404 Not Found\r\nContent-Type: application/json\r\nContent-Length: 33\r\n\r\n{\"code\":404,\"status\":\"Not Found\"}"s);
}
GIVEN("we stream our response with the status set to 204 No Content"){
response.set_status(http::no_content);
ss << response;
THEN("the response has no content header set")
REQUIRE(ss.str()=="HTTP/1.1 204 No Content\r\nContent-Type: application/json\r\n\r\n"s);
}
GIVEN("we stream our response with the body set"){
response.set_body(nlohmann::json::object());
ss << response;

116
toREST/tests/session_test.cpp

@ -1,116 +0,0 @@
#include <Catch/fakeit.hpp>
#include <session.hpp>
using namespace fakeit;
const std::string method_not_allowed_json ="HTTP/1.1 405 Method Not Allowed\r\nContent-Type: application/json\r\nContent-Length: 42\r\n\r\n{\"code\":405,\"status\":\"Method Not Allowed\"}";
const std::string service_unavailable_json="HTTP/1.1 503 Service Unavailable\r\nContent-Type: application/json\r\nContent-Length: 43\r\n\r\n{\"code\":503,\"status\":\"Service Unavailable\"}";
const std::string internal_server_error_json="HTTP/1.1 500 Internal Server Error\r\nContent-Type: application/json\r\nContent-Length: 45\r\n\r\n{\"code\":500,\"status\":\"Internal Server Error\"}";
const std::string not_found ="HTTP/1.1 404 Not Found\r\nContent-Type: application/json\r\nContent-Length: 36\r\n\r\n{\"code\":404,\"status\":\"Not Found\"}";
const std::string ok_nullptr_json ="HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 4\r\n\r\nnull";
const std::string bad_request ="HTTP/1.1 400 Bad Request\r\nContent-Type: application/json\r\nContent-Length: 35\r\n\r\n{\"code\":400,\"status\":\"Bad Request\"}";
using namespace session;
SCENARIO("test of responses by session_manager on /v1/session"){
session::resource sut;
std::stringstream ss;
GIVEN("the session is invalid"){
WHEN("we receive a GET request"){
sut.get();
ss << sut;
THEN("the response is a 503 Service Unavailable JSON object")
REQUIRE(ss.str()==service_unavailable_json);
}
WHEN("we receive a PATCH request"){
sut.patch();
ss << sut;
THEN("the response is a 503 Service Unavailable JSON object")
REQUIRE(ss.str()==service_unavailable_json);
}
WHEN("we receive a POST request"){
sut.post();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
WHEN("we receive a DELETE request"){
sut.del();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
WHEN("we receive a PUT request"){
sut.put();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
}
GIVEN("the session is valid"){
Mock<basic_manager> mock_session;
When(Method(mock_session,basic_manager::is_valid)).AlwaysReturn(true);
When(Method(mock_session,basic_manager::get_json)).AlwaysReturn(nullptr);
auto session=std::shared_ptr<basic_manager>(&(mock_session.get()),[](...){});
sut.set_session(session);
WHEN("we receive a GET request"){
sut.get();
ss << sut;
THEN("the response is a 200 OK JSON object ")
REQUIRE(ss.str()==ok_nullptr_json);
}
WHEN("we receive a PATCH request with invalid data"){
GIVEN("the JSON is invalid"){
sut.patch(nullptr);
ss << sut;
THEN("the response is a 400 Bad Request JSON object")
REQUIRE(ss.str()==bad_request);
}
GIVEN("the JSON is valid, but contains no data"){
sut.patch({});
ss << sut;
THEN("the response is a 400 Bad Request JSON object")
REQUIRE(ss.str()==bad_request);
}
GIVEN("the JSON is valid, but the port number is to low"){
When(Method(mock_session,basic_manager::patch)).AlwaysReturn(false);
sut.patch({{"listen_port",1}});
ss << sut;
THEN("the response is a 500 Internal Server Error JSON object")
REQUIRE(ss.str()==internal_server_error_json);
}
GIVEN("the JSON is valid, but listen_port is a string"){
sut.patch({{"listen_port","1"}});
ss << sut;
THEN("the response is a 400 Bad Request JSON object")
REQUIRE(ss.str()==bad_request);
}
GIVEN("the JSON is valid, but is_paused is a string"){
sut.patch({{"is_paused","1"}});
ss << sut;
THEN("the response is a 400 Bad Request JSON object")
REQUIRE(ss.str()==bad_request);
}
WHEN("we receive a POST request"){
sut.post();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
WHEN("we receive a DELETE request"){
sut.del();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
WHEN("we receive a PUT request"){
sut.put();
ss << sut;
THEN("the response is a 405 Method Not Allowed JSON object")
REQUIRE(ss.str()==method_not_allowed_json);
}
}
}
}
Loading…
Cancel
Save