From 14f2e9696c6102c0dec444e4009321cda30013e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=A1=D1=82?= =?UTF-8?q?=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Wed, 3 May 2023 20:20:16 +0300 Subject: [PATCH] Add tests for http client --- CMakeLists.txt | 53 +++- client/CMakeLists.txt | 15 + client/cmd/CMakeLists.txt | 0 client/internal/CMakeLists.txt | 8 + client/internal/entities/CMakeLists.txt | 19 ++ client/internal/entities/include/Metric.h | 11 + client/internal/entities/include/Solution.h | 58 ++++ client/internal/entities/include/Task.h | 23 ++ client/internal/entities/include/User.h | 38 +++ client/internal/entities/src/Solution.cpp | 73 +++++ client/internal/entities/src/Task.cpp | 21 ++ client/internal/entities/src/User.cpp | 43 +++ client/internal/httpClient/CMakeLists.txt | 21 ++ .../internal/httpClient/include/ClientTypes.h | 34 +++ .../internal/httpClient/include/HttpClient.h | 41 +++ .../httpClient/include/HttpClientManager.h | 33 +++ .../internal/httpClient/include/Serializer.h | 14 + client/internal/httpClient/src/HttpClient.cpp | 32 +++ .../httpClient/src/HttpClientManager.cpp | 42 +++ .../internal/httpClient/tests/CMakeLists.txt | 16 ++ .../tests/HttpClientManagerSuite.cpp | 64 +++++ .../httpClient/tests/HttpClientSuite.cpp | 11 + client/internal/httpClient/tests/main.cpp | 8 + .../internal/httpClient/virtual/IHttpClient.h | 32 +++ server/CMakeLists.txt | 0 src/main.cpp | 264 ------------------ text-basic-metrics/code1.txt | 29 -- text-basic-metrics/code2.txt | 29 -- text-basic-metrics/tbm_main.cpp | 153 ---------- 29 files changed, 696 insertions(+), 489 deletions(-) create mode 100644 client/CMakeLists.txt create mode 100644 client/cmd/CMakeLists.txt create mode 100644 client/internal/CMakeLists.txt create mode 100644 client/internal/entities/CMakeLists.txt create mode 100644 client/internal/entities/include/Metric.h create mode 100644 client/internal/entities/include/Solution.h create mode 100644 client/internal/entities/include/Task.h create mode 100644 client/internal/entities/include/User.h create mode 100644 client/internal/entities/src/Solution.cpp create mode 100644 client/internal/entities/src/Task.cpp create mode 100644 client/internal/entities/src/User.cpp create mode 100644 client/internal/httpClient/CMakeLists.txt create mode 100644 client/internal/httpClient/include/ClientTypes.h create mode 100644 client/internal/httpClient/include/HttpClient.h create mode 100644 client/internal/httpClient/include/HttpClientManager.h create mode 100644 client/internal/httpClient/include/Serializer.h create mode 100644 client/internal/httpClient/src/HttpClient.cpp create mode 100644 client/internal/httpClient/src/HttpClientManager.cpp create mode 100644 client/internal/httpClient/tests/CMakeLists.txt create mode 100644 client/internal/httpClient/tests/HttpClientManagerSuite.cpp create mode 100644 client/internal/httpClient/tests/HttpClientSuite.cpp create mode 100644 client/internal/httpClient/tests/main.cpp create mode 100644 client/internal/httpClient/virtual/IHttpClient.h create mode 100644 server/CMakeLists.txt delete mode 100644 src/main.cpp delete mode 100644 text-basic-metrics/code1.txt delete mode 100644 text-basic-metrics/code2.txt delete mode 100644 text-basic-metrics/tbm_main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5054100..23aba3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,40 @@ -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) cmake_minimum_required(VERSION 3.16) -set(CMAKE_PREFIX_PATH build) -project(SourcedOut CXX) -# find_package(antlr4-runtime REQUIRED) -find_package(Boost 1.8.1 REQUIRED) -# find_package(libpqxx REQUIRED) -find_package(GTest REQUIRED) -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) -message(STATUS ${Boost_LIBRARIES}) -set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-lpthread -pthread") -add_executable(${PROJECT_NAME} src/main.cpp) -#add_executable(${PROJECT_NAME} text-basic-metrics/tbm_main.cpp text-basic-metrics/tbm_main.cpp) строка для запуска моей части в text-basic-metrics -target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${antlr4-runtime_LIBRARIES} ${libpqxx_LIBRARIES} ${GTest_LIBRARIES}) \ No newline at end of file + +set(PROJECT_NAME "SourcedOut") + +project(${PROJECT_NAME}) + + +set(BUILD_DEV TRUE CACHE BOOL "build dev version") +set(SANITIZE_BUILD TRUE CACHE BOOL "build with sanitizers") + +if(BUILD_DEV) + enable_testing() + message("Building dev version") + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -O0 -fprofile-arcs -ftest-coverage") + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -pedantic -Wformat=2 -Wfloat-equal -Wconversion \ + # -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -lpq -lpqxx") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage -lgcov") + + if(SANITIZE_BUILD) + message("Sanitizers ON") + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=all -fsanitize-undefined-trap-on-error") + endif(SANITIZE_BUILD) +endif(BUILD_DEV) + +set(BUILD_SERVER "BUILD_SERVER") +set(BUILD_CLIENT "BUILD_CLIENT") +set(BUILD_ALL "BUILD_ALL") + + +message("${BUILD_DEV} ${SANITIZE_BUILD} ${CMAKE_EXE_LINKER_FLAGS}") +set(BUILD_MODE ${BUILD_CLIENT}) + +if((BUILD_MODE STREQUAL ${BUILD_CLIENT}) OR (BUILD_MODE STREQUAL ${BUILD_ALL})) + add_subdirectory(client) +endif() + +if((BUILD_MODE STREQUAL ${BUILD_SERVER}) OR (BUILD_MODE STREQUAL ${BUILD_ALL})) + add_subdirectory(server) +endif() \ No newline at end of file diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000..4147519 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,15 @@ +set(CMAKE_PREFIX_PATH build) +project(SourcedOut_client CXX) + +set(CMAKE_CXX_STANDARD 20) + +find_package(Boost 1.8.1 REQUIRED) +find_package(GTest REQUIRED) + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +add_subdirectory(internal) +add_subdirectory(cmd) + +set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-lpthread -pthread") \ No newline at end of file diff --git a/client/cmd/CMakeLists.txt b/client/cmd/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/client/internal/CMakeLists.txt b/client/internal/CMakeLists.txt new file mode 100644 index 0000000..93fbed8 --- /dev/null +++ b/client/internal/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(entities) +add_subdirectory(httpClient) + +set(libClientEntities_LIB ${libClientEntities_LIB} PARENT_SCOPE) +set(libClientEntities_INCLUDE_DIRS ${libClientEntities_INCLUDE_DIRS} PARENT_SCOPE) + +set(HTTPCLIENT_lib_LIB ${HTTPCLIENT_lib_LIB} PARENT_SCOPE) +set(HTTPCLIENT_lib_INCLUDE_DIRS ${HTTPCLIENT_lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/client/internal/entities/CMakeLists.txt b/client/internal/entities/CMakeLists.txt new file mode 100644 index 0000000..4087519 --- /dev/null +++ b/client/internal/entities/CMakeLists.txt @@ -0,0 +1,19 @@ +project("ClientEntitiesLib") + +set(LIB_NAME libClientEntities) + +file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -O2 -pedantic -Wformat=2 -Wfloat-equal -Wconversion \ +-Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lboost_filesystem") + +add_library(${LIB_NAME} ${SOURCES} ${HEADERS}) +target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +set(libClientEntities_LIB ${LIB_NAME}) +set(libClientEntities_LIB ${libClientEntities_LIB} PARENT_SCOPE) +set(libClientEntities_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(libClientEntities_INCLUDE_DIRS ${libClientEntities_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/client/internal/entities/include/Metric.h b/client/internal/entities/include/Metric.h new file mode 100644 index 0000000..3ab8ea7 --- /dev/null +++ b/client/internal/entities/include/Metric.h @@ -0,0 +1,11 @@ +#ifndef SOURCEDOUT_METRIC_H +#define SOURCEDOUT_METRIC_H + +#include + +struct Metric { + std::string name; + unsigned int value; +}; + +#endif //SOURCEDOUT_METRIC_H diff --git a/client/internal/entities/include/Solution.h b/client/internal/entities/include/Solution.h new file mode 100644 index 0000000..6282f47 --- /dev/null +++ b/client/internal/entities/include/Solution.h @@ -0,0 +1,58 @@ +#ifndef SOURCEDOUT_SOLUTION_HPP +#define SOURCEDOUT_SOLUTION_HPP + +#include +#include +#include + +class Solution { +public: + Solution() =default; + Solution(size_t id, std::string sendDate, size_t senderId, std::string source, + std::string tokens, std::string astTree, size_t taskId, std::string result); + + [[nodiscard]] size_t getId() const; + + + [[nodiscard]] const std::string &getSendDate() const; + + void setSendDate(const std::string &sendDate); + + [[nodiscard]] size_t getSenderId() const; + + void setSenderId(size_t senderId); + + [[nodiscard]] const std::string &getSource() const; + + void setSource(const std::string &source); + + [[nodiscard]] const std::string &getTokens() const; + + void setTokens(const std::string &tokens); + + [[nodiscard]] const std::string &getAstTree() const; + + void setAstTree(const std::string &astTree); + + [[nodiscard]] size_t getTaskId() const; + + void setTaskId(size_t taskId); + + [[nodiscard]] const std::string &getResult() const; + + void setResult(const std::string &result); + +private: + size_t id; + std::string send_date; + size_t sender_id; + std::string source; + std::string tokens; + std::string astTree; + size_t task_id; + std::string result; +public: + +}; + +#endif //SOURCEDOUT_SOLUTION_HPP \ No newline at end of file diff --git a/client/internal/entities/include/Task.h b/client/internal/entities/include/Task.h new file mode 100644 index 0000000..d51c17f --- /dev/null +++ b/client/internal/entities/include/Task.h @@ -0,0 +1,23 @@ +#ifndef SOURCEDOUT_TASK_HPP +#define SOURCEDOUT_TASK_HPP +#include +#include +class Task{ +private: + size_t id; + std::string description; + +public: + Task()=default; + ~Task() = default; + Task(size_t id, std::string description); + + explicit Task(std::string description); + + [[nodiscard]] size_t getId() const; + + [[nodiscard]] const std::string &getDescription() const; + + void setDescription(const std::string &description); +}; +#endif //SOURCEDOUT_TASK_HPP \ No newline at end of file diff --git a/client/internal/entities/include/User.h b/client/internal/entities/include/User.h new file mode 100644 index 0000000..5802df2 --- /dev/null +++ b/client/internal/entities/include/User.h @@ -0,0 +1,38 @@ +#ifndef SOURCEDOUT_USER_HPP + +#include +#include + +#define SOURCEDOUT_USER_HPP + +class User { +private: + size_t id; + std::string login; + std::string password; + std::string username; + +public: + User()=default; + User(size_t id_, std::string login_, std::string password_, std::string username_); + + User(std::string login_, std::string password_, std::string username_); + + [[nodiscard]] const std::string &getLogin() const; + + void setLogin(const std::string &login); + + [[nodiscard]] const std::string &getPassword() const; + + void setPassword(const std::string &password); + + [[nodiscard]] const std::string &getUsername() const; + + void setUsername(const std::string &username); + + [[nodiscard]] size_t getId() const; + + friend std::ostream &operator<<(std::ostream &os, const User &user); +}; + +#endif //SOURCEDOUT_USER_HPP \ No newline at end of file diff --git a/client/internal/entities/src/Solution.cpp b/client/internal/entities/src/Solution.cpp new file mode 100644 index 0000000..2e9b1e8 --- /dev/null +++ b/client/internal/entities/src/Solution.cpp @@ -0,0 +1,73 @@ + +#include +#include +#include "Solution.h" + +Solution::Solution(unsigned long id, std::string sendDate, unsigned long senderId, + std::string source, std::string tokens, + std::string astTree, unsigned long taskId, + std::string result) : id(id), send_date(std::move(sendDate)), sender_id(senderId), + source(std::move(source)), tokens(std::move(tokens)), + astTree(std::move(astTree)), + task_id(taskId), result(std::move(result)) {} + +size_t Solution::getId() const { + return id; +} + + +const std::string &Solution::getSendDate() const { + return send_date; +} + +void Solution::setSendDate(const std::string &sendDate) { + send_date = sendDate; +} + +size_t Solution::getSenderId() const { + return sender_id; +} + +void Solution::setSenderId(size_t senderId) { + sender_id = senderId; +} + +const std::string &Solution::getSource() const { + return source; +} + +void Solution::setSource(const std::string &source_) { + Solution::source = source_; +} + +const std::string &Solution::getTokens() const { + return tokens; +} + +void Solution::setTokens(const std::string &tokens_) { + Solution::tokens = tokens_; +} + +const std::string &Solution::getAstTree() const { + return astTree; +} + +void Solution::setAstTree(const std::string &astTree_) { + Solution::astTree = astTree_; +} + +size_t Solution::getTaskId() const { + return task_id; +} + +void Solution::setTaskId(size_t taskId) { + task_id = taskId; +} + +const std::string &Solution::getResult() const { + return result; +} + +void Solution::setResult(const std::string &result_) { + Solution::result = result_; +} \ No newline at end of file diff --git a/client/internal/entities/src/Task.cpp b/client/internal/entities/src/Task.cpp new file mode 100644 index 0000000..7dd9bfe --- /dev/null +++ b/client/internal/entities/src/Task.cpp @@ -0,0 +1,21 @@ +#pragma once + +#include "Task.h" +#include +#include + +unsigned long Task::getId() const { + return id; +} + +Task::Task(size_t id, std::string description) : id(id), description(std::move(description)) {} + +Task::Task(std::string description) : id(0), description(std::move(description)) {} + +const std::string &Task::getDescription() const { + return description; +} + +void Task::setDescription(const std::string &description_) { + Task::description = description_; +} \ No newline at end of file diff --git a/client/internal/entities/src/User.cpp b/client/internal/entities/src/User.cpp new file mode 100644 index 0000000..53706e2 --- /dev/null +++ b/client/internal/entities/src/User.cpp @@ -0,0 +1,43 @@ +#include +#include "User.h" + +User::User(size_t id_, std::string login_, std::string password_, std::string username_) : + id(id_), login(std::move(login_)), password(std::move(password_)), username(std::move(username_)) { +} +User::User(std::string login_, std::string password_, std::string username_) : + id(0), login(std::move(login_)), password(std::move(password_)), username(std::move(username_)) { +} + +const std::string &User::getLogin() const { + return login; +} + +void User::setLogin(const std::string &login_) { + User::login = login_; +} + +const std::string &User::getPassword() const { + return password; +} + +void User::setPassword(const std::string &password_) { + User::password = password_; +} + +const std::string &User::getUsername() const { + return username; +} + +void User::setUsername(const std::string &username_) { + User::username = username_; +} + +size_t User::getId() const { + return id; +} + +std::ostream &operator<<(std::ostream &os, const User &user) { + os << "id: " << user.id << " login: " << user.login << " password: " << user.password << " username: " + << user.username; + return os; +} \ No newline at end of file diff --git a/client/internal/httpClient/CMakeLists.txt b/client/internal/httpClient/CMakeLists.txt new file mode 100644 index 0000000..591e57a --- /dev/null +++ b/client/internal/httpClient/CMakeLists.txt @@ -0,0 +1,21 @@ +project("HttpClientLib") + +set(CMAKE_CXX_STANDARD 20) + +file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/virtual) +file(GLOB INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/virtual/*.h) + +include_directories(${INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${libClientEntities_INCLUDE_DIRS}) + +add_library(${PROJECT_NAME} ${SOURCES} ${INCLUDES}) +target_link_libraries(${PROJECT_NAME} ${libClientEntities_LIB} ${Boost_LIBRARIES}) + +set(HTTPCLIENT_lib_LIB ${PROJECT_NAME}) +set(HTTPCLIENT_lib_LIB ${HTTPCLIENT_lib_LIB} PARENT_SCOPE) + +set(HTTPCLIENT_lib_INCLUDE_DIRS ${INCLUDE_DIRS}) +set(HTTPCLIENT_lib_INCLUDE_DIRS ${HTTPCLIENT_lib_INCLUDE_DIRS} PARENT_SCOPE) + +enable_testing() +add_subdirectory(tests) \ No newline at end of file diff --git a/client/internal/httpClient/include/ClientTypes.h b/client/internal/httpClient/include/ClientTypes.h new file mode 100644 index 0000000..9ba6e87 --- /dev/null +++ b/client/internal/httpClient/include/ClientTypes.h @@ -0,0 +1,34 @@ +#ifndef APP_HTTPCLIENT_HTTPCLIENT_CLIENTTYPES_H_ +#define APP_HTTPCLIENT_HTTPCLIENT_CLIENTTYPES_H_ + +#include +#include +#include +#include +#include + +using Response = boost::beast::http::response; +using Request = boost::beast::http::request; + +using Params = std::map; + +struct Header { + std::string name; + std::string values; +}; + +struct ResponseStruct { + unsigned int status; + std::string body; + std::vector
headers; +}; + +struct Host { + std::string domain; + std::string ip; + unsigned short port; + Host(std::string domain, std::string ip, unsigned short port) + : domain(std::move(domain)), ip(std::move(ip)), port(port) {} +}; + +#endif // APP_HTTPCLIENT_HTTPCLIENT_CLIENTTYPES_H_ diff --git a/client/internal/httpClient/include/HttpClient.h b/client/internal/httpClient/include/HttpClient.h new file mode 100644 index 0000000..99e7fb0 --- /dev/null +++ b/client/internal/httpClient/include/HttpClient.h @@ -0,0 +1,41 @@ +#ifndef APP_HTTPCLIENT_HTTPCLIENT_HTTPCLIENT_H_ +#define APP_HTTPCLIENT_HTTPCLIENT_HTTPCLIENT_H_ + +#include +#include +#include +#include + +#include "ClientTypes.h" +#include "Serializer.h" +#include "IHttpClient.h" + +class HttpClient : public IHttpClient { + public: + HttpClient(); + ResponseStruct makeGetRequest(const Host& host, const std::string& target, + const std::shared_ptr& params = nullptr, + const std::shared_ptr& headers = nullptr) override; + ResponseStruct makePostRequest(const Host& host, const std::string& target, + const std::shared_ptr& body, + const std::shared_ptr& headers = nullptr) override; + + private: + ResponseStruct parseResponse(Response response) override; + std::string createURL(const std::string& target, const std::shared_ptr& params = nullptr) override; + bool connect(unsigned short port) override; + ResponseStruct makeRequest(const Host& host, const std::string& target, boost::beast::http::verb method, + const std::shared_ptr& params = nullptr, + const std::shared_ptr& body = nullptr, + const std::shared_ptr& headers = nullptr) override; + + boost::asio::io_context context; + boost::asio::ip::tcp::resolver resolver; + boost::asio::ip::tcp::socket socket; + std::string ip; + boost::beast::flat_buffer flat_buffer; + Serializer serializer; +}; + + +#endif // APP_HTTPCLIENT_HTTPCLIENT_HTTPCLIENT_H_ diff --git a/client/internal/httpClient/include/HttpClientManager.h b/client/internal/httpClient/include/HttpClientManager.h new file mode 100644 index 0000000..1d31ce3 --- /dev/null +++ b/client/internal/httpClient/include/HttpClientManager.h @@ -0,0 +1,33 @@ +#ifndef APP_HTTPCLIENT_HTTPCLIENTMANAGER_HTTPCLIENTMANAGER_H_ +#define APP_HTTPCLIENT_HTTPCLIENTMANAGER_HTTPCLIENTMANAGER_H_ + +#include +#include +#include + +#include "IHttpClient.h" +#include "User.h" +#include "Solution.h" +#include "Task.h" +#include "Metric.h" + +class HttpClientManager { + public: + HttpClientManager(const std::string &domain, const std::string &ip, const unsigned short &port, + std::string saved_path_); + unsigned int loginUser(const std::string &login, const std::string &password); + unsigned int registerUser(const std::string &login, const std::string &username, const std::string &password); + unsigned int submitSolution(const int& user_id, const std::string &path_to_sound); + unsigned int getAllSolutionsForTask(const int& user_id, const int& task_id); + std::vector getAllTasks(); + std::vector getMetrics(const int& sol_id); + void setHttpClient(std::shared_ptr client_); + private: + std::string saved_path; + Host host; + std::shared_ptr client; + Serializer serializer; +}; + + +#endif // APP_HTTPCLIENT_HTTPCLIENTMANAGER_HTTPCLIENTMANAGER_H_ diff --git a/client/internal/httpClient/include/Serializer.h b/client/internal/httpClient/include/Serializer.h new file mode 100644 index 0000000..31d4468 --- /dev/null +++ b/client/internal/httpClient/include/Serializer.h @@ -0,0 +1,14 @@ +#ifndef APP_HTTPCLIENT_HTTPCLIENT_SERIALIZER_H_ +#define APP_HTTPCLIENT_HTTPCLIENT_SERIALIZER_H_ + +#include +#include +#include + +#include "ClientTypes.h" + +class Serializer {}; + + + +#endif // APP_HTTPCLIENT_HTTPCLIENT_SERIALIZER_H_ diff --git a/client/internal/httpClient/src/HttpClient.cpp b/client/internal/httpClient/src/HttpClient.cpp new file mode 100644 index 0000000..93881ff --- /dev/null +++ b/client/internal/httpClient/src/HttpClient.cpp @@ -0,0 +1,32 @@ +#include "httpClient.h" + +#include +#include +#include +#include +#include +#include + +using Error = boost::system::system_error; + +std::string HttpClient::createURL(const std::string& target, const std::shared_ptr& params) {} + +bool HttpClient::connect(unsigned short port = 80) {} + +HttpClient::HttpClient() : socket(context), resolver(context) {} + +ResponseStruct HttpClient::makeRequest(const Host &host, const std::string &target, + const boost::beast::http::verb method, + const std::shared_ptr& params, + const std::shared_ptr& body, + const std::shared_ptr& headers) {} + +ResponseStruct HttpClient::parseResponse(Response response) {} + +ResponseStruct HttpClient::makeGetRequest(const Host &host, const std::string &target, + const std::shared_ptr& params, + const std::shared_ptr& headers) {} + +ResponseStruct HttpClient::makePostRequest(const Host &host, const std::string &target, + const std::shared_ptr& body, + const std::shared_ptr& headers) {} diff --git a/client/internal/httpClient/src/HttpClientManager.cpp b/client/internal/httpClient/src/HttpClientManager.cpp new file mode 100644 index 0000000..57e1a88 --- /dev/null +++ b/client/internal/httpClient/src/HttpClientManager.cpp @@ -0,0 +1,42 @@ +#include "httpClientManager.h" + +#include +#include +#include +#include +#include + +HttpClientManager::HttpClientManager(const std::string &domain, + const std::string &ip, + const unsigned short &port, + std::string saved_path_) + : host(domain, ip, port), client(), serializer(), saved_path(std::move(saved_path_)) {} + +unsigned int HttpClientManager::loginUser(const std::string &login, const std::string &password) { + return 0; +} + +unsigned int HttpClientManager::registerUser(const std::string &login, const std::string &username, + const std::string &password) { + return 0; +} + +unsigned int HttpClientManager::submitSolution(const int &user_id, const std::string &path_to_sound) { + return 0; +} + +unsigned int HttpClientManager::getAllSolutionsForTask(const int &user_id, const int &task_id) { + return 0; +} + +std::vector HttpClientManager::getMetrics(const int &sol_id) { + return std::vector(); +} + +void HttpClientManager::setHttpClient(std::shared_ptr client_) { + client = client_; +} + +std::vector HttpClientManager::getAllTasks() { + return std::vector(); +} diff --git a/client/internal/httpClient/tests/CMakeLists.txt b/client/internal/httpClient/tests/CMakeLists.txt new file mode 100644 index 0000000..7b0e0c7 --- /dev/null +++ b/client/internal/httpClient/tests/CMakeLists.txt @@ -0,0 +1,16 @@ +project(test_httpclient) + +set(CMAKE_CXX_STANDARD 20) +add_compile_options(-coverage) + +file(GLOB SOURCES *.cpp) + +enable_testing() +find_package(GTest REQUIRED) + +add_executable(${PROJECT_NAME} ${SOURCES}) + +target_link_libraries(${PROJECT_NAME} ${HTTPCLIENT_lib_LIB} GTest::GTest GTest::gmock) +target_include_directories(${PROJECT_NAME} PUBLIC ${HTTPCLIENT_lib_INCLUDE_DIRS}) + +add_test(test_httpclient test_httpclient) \ No newline at end of file diff --git a/client/internal/httpClient/tests/HttpClientManagerSuite.cpp b/client/internal/httpClient/tests/HttpClientManagerSuite.cpp new file mode 100644 index 0000000..44de182 --- /dev/null +++ b/client/internal/httpClient/tests/HttpClientManagerSuite.cpp @@ -0,0 +1,64 @@ +#include +#include + +#include "IHttpClient.h" +#include "HttpClientManager.h" + +class HttpClientMock : public IHttpClient { +public: + HttpClientMock() = default; + MOCK_METHOD(ResponseStruct, makeGetRequest, (const Host& host, const std::string& target, + const std::shared_ptr& params, + const std::shared_ptr& headers), (override)); + MOCK_METHOD(ResponseStruct, makePostRequest, (const Host& host, const std::string& target, + const std::shared_ptr& body, + const std::shared_ptr& headers), (override)); + MOCK_METHOD(ResponseStruct, parseResponse, (Response response), (override)); + MOCK_METHOD(std::string, createURL, (const std::string& target, const std::shared_ptr& params), + (override)); + MOCK_METHOD(bool, connect, (unsigned short port), (override)); + MOCK_METHOD(ResponseStruct, makeRequest, (const Host& host, const std::string& target, boost::beast::http::verb method, + const std::shared_ptr& params, + const std::shared_ptr& body, + const std::shared_ptr& headers), (override)); +}; + +class HttpClientManagerSuite : public ::testing::Test { +protected: + void SetUp() override { + manager.setHttpClient(client); + } + + std::shared_ptr client = std::make_shared(); + HttpClientManager manager = HttpClientManager("1", "1.1.1.1", 1, "."); +}; + +TEST_F(HttpClientManagerSuite, LoginUserTest){ + EXPECT_CALL(*client, makeGetRequest); + manager.loginUser("1", "2"); +} + +TEST_F(HttpClientManagerSuite, RegisterUserTest){ + EXPECT_CALL(*client, makePostRequest); + manager.registerUser("1", "2", "3"); +} + +TEST_F(HttpClientManagerSuite, SubmitSolutionTest){ + EXPECT_CALL(*client, makePostRequest); + manager.submitSolution(1, "2234"); +} + +TEST_F(HttpClientManagerSuite, GetAllSolutionsForTaskTest){ + EXPECT_CALL(*client, makeGetRequest); + manager.getAllSolutionsForTask(1, 2); +} + +TEST_F(HttpClientManagerSuite, GetAllTasksTest){ + EXPECT_CALL(*client, makeGetRequest); + manager.getAllTasks(); +} + +TEST_F(HttpClientManagerSuite, GetMetricsTest){ + EXPECT_CALL(*client, makeGetRequest); + manager.getMetrics(1); +} diff --git a/client/internal/httpClient/tests/HttpClientSuite.cpp b/client/internal/httpClient/tests/HttpClientSuite.cpp new file mode 100644 index 0000000..7ff26c2 --- /dev/null +++ b/client/internal/httpClient/tests/HttpClientSuite.cpp @@ -0,0 +1,11 @@ +#include +#include + +#include "HttpClient.h" + +TEST(HttpClientSuite, WrongGetTest) { + HttpClient client; + Host h("1", "1.1.1.1", 80); + ResponseStruct res = client.makeGetRequest(h, "/ser/login"); + EXPECT_EQ(res.status, 500); +} \ No newline at end of file diff --git a/client/internal/httpClient/tests/main.cpp b/client/internal/httpClient/tests/main.cpp new file mode 100644 index 0000000..21bd133 --- /dev/null +++ b/client/internal/httpClient/tests/main.cpp @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char** argv) { + ::testing::InitGoogleMock(&argc, argv); + + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/client/internal/httpClient/virtual/IHttpClient.h b/client/internal/httpClient/virtual/IHttpClient.h new file mode 100644 index 0000000..e24e15d --- /dev/null +++ b/client/internal/httpClient/virtual/IHttpClient.h @@ -0,0 +1,32 @@ +#ifndef APP_HTTPCLIENT_HTTPCLIENT_IHTTPCLIENT_H_ +#define APP_HTTPCLIENT_HTTPCLIENT_IHTTPCLIENT_H_ + +#include +#include +#include +#include + +#include "clientTypes.h" +#include "serializer.h" + +class IHttpClient { +public: + virtual ResponseStruct makeGetRequest(const Host& host, const std::string& target, + const std::shared_ptr& params = nullptr, + const std::shared_ptr& headers = nullptr) = 0; + virtual ResponseStruct makePostRequest(const Host& host, const std::string& target, + const std::shared_ptr& body, + const std::shared_ptr& headers = nullptr) = 0; + +protected: + virtual ResponseStruct parseResponse(Response response) = 0; + virtual std::string createURL(const std::string& target, const std::shared_ptr& params = nullptr) = 0; + virtual bool connect(unsigned short port) = 0; + virtual ResponseStruct makeRequest(const Host& host, const std::string& target, boost::beast::http::verb method, + const std::shared_ptr& params = nullptr, + const std::shared_ptr& body = nullptr, + const std::shared_ptr& headers = nullptr) = 0; +}; + + +#endif // APP_HTTPCLIENT_HTTPCLIENT_HTTPCLIENT_H_ diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index cbd2bd5..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,264 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -using tcp = boost::asio::ip::tcp; // from - -//------------------------------------------------------------------------------ - -// Return a reasonable mime type based on the extension of a file. -beast::string_view mime_type(beast::string_view path) { - using beast::iequals; - auto const ext = [&path] { - auto const pos = path.rfind("."); - if (pos == beast::string_view::npos) return beast::string_view{}; - return path.substr(pos); - }(); - if (iequals(ext, ".htm")) return "text/html"; - if (iequals(ext, ".html")) return "text/html"; - if (iequals(ext, ".php")) return "text/html"; - if (iequals(ext, ".css")) return "text/css"; - if (iequals(ext, ".txt")) return "text/plain"; - if (iequals(ext, ".js")) return "application/javascript"; - if (iequals(ext, ".json")) return "application/json"; - if (iequals(ext, ".xml")) return "application/xml"; - if (iequals(ext, ".swf")) return "application/x-shockwave-flash"; - if (iequals(ext, ".flv")) return "video/x-flv"; - if (iequals(ext, ".png")) return "image/png"; - if (iequals(ext, ".jpe")) return "image/jpeg"; - if (iequals(ext, ".jpeg")) return "image/jpeg"; - if (iequals(ext, ".jpg")) return "image/jpeg"; - if (iequals(ext, ".gif")) return "image/gif"; - if (iequals(ext, ".bmp")) return "image/bmp"; - if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; - if (iequals(ext, ".tiff")) return "image/tiff"; - if (iequals(ext, ".tif")) return "image/tiff"; - if (iequals(ext, ".svg")) return "image/svg+xml"; - if (iequals(ext, ".svgz")) return "image/svg+xml"; - return "application/text"; -} - -// Append an HTTP rel-path to a local filesystem path. -// The returned path is normalized for the platform. -std::string path_cat(beast::string_view base, beast::string_view path) { - if (base.empty()) return std::string(path); - std::string result(base); -#ifdef BOOST_MSVC - char constexpr path_separator = '\\'; - if (result.back() == path_separator) result.resize(result.size() - 1); - result.append(path.data(), path.size()); - for (auto& c : result) - if (c == '/') c = path_separator; -#else - char constexpr path_separator = '/'; - if (result.back() == path_separator) result.resize(result.size() - 1); - result.append(path.data(), path.size()); -#endif - return result; -} - -// This function produces an HTTP response for the given -// request. The type of the response object depends on the -// contents of the request, so the interface requires the -// caller to pass a generic lambda for receiving the response. -template -void handle_request(beast::string_view doc_root, - http::request>&& req, - Send&& send) { - // Returns a bad request response - auto const bad_request = [&req](beast::string_view why) { - http::response res{http::status::bad_request, - req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, "text/html"); - res.keep_alive(req.keep_alive()); - res.body() = std::string(why); - res.prepare_payload(); - return res; - }; - - // Returns a not found response - auto const not_found = [&req](beast::string_view target) { - http::response res{http::status::not_found, - req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, "text/html"); - res.keep_alive(req.keep_alive()); - res.body() = "The resource '" + std::string(target) + "' was not found."; - res.prepare_payload(); - return res; - }; - - // Returns a server error response - auto const server_error = [&req](beast::string_view what) { - http::response res{http::status::internal_server_error, - req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, "text/html"); - res.keep_alive(req.keep_alive()); - res.body() = "An error occurred: '" + std::string(what) + "'"; - res.prepare_payload(); - return res; - }; - - // Make sure we can handle the method - if (req.method() != http::verb::get && req.method() != http::verb::head) - return send(bad_request("Unknown HTTP-method")); - - // Request path must be absolute and not contain "..". - if (req.target().empty() || req.target()[0] != '/' || - req.target().find("..") != beast::string_view::npos) - return send(bad_request("Illegal request-target")); - - // Build the path to the requested file - std::string path = path_cat(doc_root, req.target()); - if (req.target().back() == '/') path.append("index.html"); - - // Attempt to open the file - beast::error_code ec; - http::file_body::value_type body; - body.open(path.c_str(), beast::file_mode::scan, ec); - - // Handle the case where the file doesn't exist - if (ec == beast::errc::no_such_file_or_directory) - return send(not_found(req.target())); - - // Handle an unknown error - if (ec) return send(server_error(ec.message())); - - // Cache the size since we need it after the move - auto const size = body.size(); - - // Respond to HEAD request - if (req.method() == http::verb::head) { - http::response res{http::status::ok, req.version()}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); - res.keep_alive(req.keep_alive()); - return send(std::move(res)); - } - - // Respond to GET request - http::response res{ - std::piecewise_construct, std::make_tuple(std::move(body)), - std::make_tuple(http::status::ok, req.version())}; - res.set(http::field::server, BOOST_BEAST_VERSION_STRING); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); - res.keep_alive(req.keep_alive()); - return send(std::move(res)); -} - -//------------------------------------------------------------------------------ - -// Report a failure -void fail(beast::error_code ec, char const* what) { - std::cerr << what << ": " << ec.message() << "\n"; -} - -// This is the C++11 equivalent of a generic lambda. -// The function object is used to send an HTTP message. -template -struct send_lambda { - Stream& stream_; - bool& close_; - beast::error_code& ec_; - - explicit send_lambda(Stream& stream, bool& close, beast::error_code& ec) - : stream_(stream), close_(close), ec_(ec) {} - - template - void operator()(http::message&& msg) const { - // Determine if we should close the connection after - close_ = msg.need_eof(); - - // We need the serializer here because the serializer requires - // a non-const file_body, and the message oriented version of - // http::write only works with const messages. - http::serializer sr{msg}; - http::write(stream_, sr, ec_); - } -}; - -// Handles an HTTP server connection -void do_session(tcp::socket& socket, - std::shared_ptr const& doc_root) { - bool close = false; - beast::error_code ec; - - // This buffer is required to persist across reads - beast::flat_buffer buffer; - - // This lambda is used to send messages - send_lambda lambda{socket, close, ec}; - - for (;;) { - // Read a request - http::request req; - http::read(socket, buffer, req, ec); - if (ec == http::error::end_of_stream) break; - if (ec) return fail(ec, "read"); - - // Send the response - handle_request(*doc_root, std::move(req), lambda); - if (ec) return fail(ec, "write"); - if (close) { - // This means we should close the connection, usually because - // the response indicated the "Connection: close" semantic. - break; - } - } - - // Send a TCP shutdown - socket.shutdown(tcp::socket::shutdown_send, ec); - - // At this point the connection is closed gracefully -} - -//------------------------------------------------------------------------------ - -int main(int argc, char* argv[]) { - try { - // Check command line arguments. - if (argc != 4) { - std::cerr << "Usage: http-server-sync
\n" - << "Example:\n" - << " http-server-sync 0.0.0.0 8080 .\n"; - return EXIT_FAILURE; - } - auto const address = net::ip::make_address(argv[1]); - auto const port = static_cast(std::atoi(argv[2])); - auto const doc_root = std::make_shared(argv[3]); - - // The io_context is required for all I/O - net::io_context ioc{1}; - - // The acceptor receives incoming connections - tcp::acceptor acceptor{ioc, {address, port}}; - for (;;) { - // This will receive the new connection - tcp::socket socket{ioc}; - - // Block until we get a connection - acceptor.accept(socket); - - // Launch the session, transferring ownership of the socket - std::thread{std::bind(&do_session, std::move(socket), doc_root)}.detach(); - } - } catch (const std::exception& e) { - std::cerr << "Error: " << e.what() << std::endl; - return EXIT_FAILURE; - } -} diff --git a/text-basic-metrics/code1.txt b/text-basic-metrics/code1.txt deleted file mode 100644 index 5fa95b8..0000000 --- a/text-basic-metrics/code1.txt +++ /dev/null @@ -1,29 +0,0 @@ -// однострочный комментарий -// еще один -// вау еще один - -#include -#include -#include - -using namespace std; - -/* многострочный комм - * // внутри него однострочный - * - */ - - -int main() { - stringstream ss; - string res; - // ещё в код напихаю комментов - ss << "a bwfw ce "; - while(getline(ss, res, ' ')){ //комментарий после строки с кодом - /* - * летс гоу - * худшее место для многострочного коммента - */ - cout << res << endl; /* многострочный однострочно */ - } -} diff --git a/text-basic-metrics/code2.txt b/text-basic-metrics/code2.txt deleted file mode 100644 index 2115b76..0000000 --- a/text-basic-metrics/code2.txt +++ /dev/null @@ -1,29 +0,0 @@ -// однострочный комментарий -// еще один -// вау еще один - -#include -#include -#include - -using namespace std; - -/* многострочный комм - * // внутри него однострочный - * - */ - - -int main() { - stringstream ss1; - string res1; - // ещё в код напихаю комментов - ss1 << "a bwfw ce "; - while(getline(ss, res1, ' ')){ //комментарий после строки с кодом - /* - * летс гоу - * худшее место для многострочного коммента - */ - cout << res1 << endl; /* многострочный однострочно */ - } -} \ No newline at end of file diff --git a/text-basic-metrics/tbm_main.cpp b/text-basic-metrics/tbm_main.cpp deleted file mode 100644 index fdd4253..0000000 --- a/text-basic-metrics/tbm_main.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Created by march on 21.04.2023. -// - -#include -#include -#include -#include -#include -#include -#include - -#include - - -std::string deleteComms(const std::string& text){ - std::string modif; - std::string res; - - std::stringstream ss; - std::string line; - - ss << text; - - while(getline(ss, line)){ - line.pop_back(); - line.push_back('\0'); - modif += line; - } - - bool s_comm = false; - bool m_comm = false; - - for (int i = 0; i < modif.size(); i++){ - if (s_comm && modif[i] == '\0') - s_comm = false; - else if (m_comm && modif[i] == '*' && modif[i + 1] == '/') - m_comm = false, i++; - else if (s_comm || m_comm) - continue; - else if (modif[i] == '/' && modif[i+1] == '/') - s_comm = true, i++; - else if (modif[i] == '/' && modif[i+1] == '*') - m_comm = true, i++; - - else if (modif[i] != '\0') - res += modif[i]; - else{ - res += '\n'; - } - } - return res; -} - -std::vector tbm_tokenizer(const std::string &text){ - boost::char_separator sep(" {}();,\"\0\'"); - std::vector res; - boost::tokenizer < boost::char_separator > tokens(text, sep); - - for (const std::string &s: tokens) { - if (!s.empty() && s[0] != '\n' && s[0] != '\0'){ - res.push_back(s); - } - } - return res; -} - -// % = intersection(A, B) / union(A, B) -double Jaccard_metric(const std::vector & tokens1, const std::vector & tokens2){ - std::set s1; - std::set s2; - - for (auto &i : tokens1) s1.insert(i); - for (auto &i : tokens2) s2.insert(i); - - - std::set intersect_sets; - set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), - std::inserter(intersect_sets, intersect_sets.begin())); - - std::set union_sets; - set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), - std::inserter(union_sets, union_sets.begin())); - - std::cout << intersect_sets.size() << " " << union_sets.size() << std::endl; - - return static_cast (intersect_sets.size()) / static_cast (union_sets.size()); -} - -double Livenstain_dist(std::vector tokens1, std::vector tokens2){ - unsigned long n = tokens1.size(); - unsigned long m = tokens2.size(); - int x, y, z; - - std::vector > lev (n, std::vector (m, 0)); - - for (int i = 0; i < n; i++){ - for (int j = 0; j < m; j++){ - if (std::min(i, j) == 0){ - lev[i][j] = std::max(i, j); - } - else{ - x = lev[i-1][j]; - y = lev[i][j-1]; - z = lev[i-1][j-1]; - lev[i][j] = std::min(x, std::min(y, z)); - if (tokens1[i] != tokens2[j]){ - lev[i][j]++; - } - } - } - } - - return lev[n-1][m-1]; -} - -std::pair textCompare(std::istream& fin1, std::istream& fin2){ - std::string line; - - std::string text1( (std::istreambuf_iterator(fin1) ), - (std::istreambuf_iterator() ) ); - - std::string text2( (std::istreambuf_iterator(fin2) ), - (std::istreambuf_iterator() ) ); - - std::string non_comm_text1 = deleteComms(text1); - std::string non_comm_text2 = deleteComms(text2); - - std::vector tokens1 = tbm_tokenizer(non_comm_text1); - std::vector tokens2 = tbm_tokenizer(non_comm_text2); - - double res1 = Jaccard_metric(tokens1, tokens2); - double res2 = 1 - Livenstain_dist(tokens1, tokens2) / std::max(tokens1.size(), tokens2.size()); - - return {res1, res2}; -} - -int main(){ - - std::ifstream fin1; - fin1.open("text-basic-metrics/code1.txt"); - assert(fin1.is_open()); - - std::ifstream fin2; - fin2.open("text-basic-metrics/code2.txt"); - assert(fin2.is_open()); - - std::pair metrics_res = textCompare(fin1, fin2); - - std::cout << "Jaccard metric "<< metrics_res.first << "\nLivenstein distance: " << metrics_res.second; - fin1.close(); - fin2.close(); -} \ No newline at end of file -- GitLab