From dd5c97d633da95609e2950a47492ccae2af5a536 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 15:16:13 +0300 Subject: [PATCH 01/19] add minimal ci --- .github/workflows/ci.yml | 53 ++++++++++++++++++++++++++++++++++++++++ .gitignore | 1 + 2 files changed, 54 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7a67001 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: Cpp + +on: + push: + branches: [ "dev", "main" ] + pull_request: + branches: [ "dev", "main" ] + +defaults: + run: + shell: bash + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Installing + run: | + sudo apt update + git clone https://github.com/google/googletest.git -b release-1.11.0 + cd googletest + mkdir build + cd build + cmake .. -DBUILD_GMOCK=OFF + make + sudo make install + cd ../.. + - name: Building + run: | + mkdir build + cd build + cmake .. + make + # - name: Testing + # run: | + # ./build/tests/test_parser + linters: + runs-on: ubuntu-latest + needs: [build] + steps: + - uses: actions/checkout@v3 + - name: Installing + run: | + sudo apt update + sudo apt install cppcheck + pip install cpplint + - name: Cppcheck + run: | + cppcheck --language=c++ ./src/main.cpp + - name: Cpplint + run: | + cpplint --filter=-legal/copyright,-readability/casting,-whitespace/tab,-build/include_subdir --linelength=110 ./src/main.cpp \ No newline at end of file diff --git a/.gitignore b/.gitignore index 29e77ea..870ca9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /cmake-build-debug/ /build/ +.vscode .idea CMakeUserPresets.json -- GitLab From 00a32a991a414ce6ec5360c3b00f29621a517f63 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 16:07:35 +0300 Subject: [PATCH 02/19] add boost to ci --- .github/workflows/ci.yml | 7 +++++++ CMakeLists.txt | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a67001..2e069cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,13 @@ jobs: - name: Installing run: | sudo apt update + wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz + tar xvf boost_1_82_0.tar.gz + cd boost_1_82_0 + ./bootstrap.sh --prefix=/usr/ + sudo ./b2 install + cd .. + git clone https://github.com/google/googletest.git -b release-1.11.0 cd googletest mkdir build diff --git a/CMakeLists.txt b/CMakeLists.txt index bdb1810..41ba7c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ set(CMAKE_CXX_STANDARD 17) -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.7) set(CMAKE_PREFIX_PATH build) project(SourcedOut CXX) -find_package(antlr4-runtime REQUIRED) +# find_package(antlr4-runtime REQUIRED) find_package(Boost 1.8.1 REQUIRED) -find_package(libpqxx REQUIRED) +# find_package(libpqxx REQUIRED) find_package(GTest REQUIRED) message(STATUS ${Boost_LIBRARIES}) add_executable(${PROJECT_NAME} src/main.cpp) -- GitLab From 5027b34d192fb5391b62ff105590b158081fb837 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 16:47:26 +0300 Subject: [PATCH 03/19] init service --- .gitignore | 1 + server/internal/CMakeLists.txt | 4 ++++ server/internal/service/CMakeLists.txt | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 server/internal/service/CMakeLists.txt diff --git a/.gitignore b/.gitignore index ff16b4f..341fd67 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /cmake-build-debug/ /build/ .idea +.vscode server/build/ log.txt CMakeUserPresets.json diff --git a/server/internal/CMakeLists.txt b/server/internal/CMakeLists.txt index 87ba964..4d65978 100644 --- a/server/internal/CMakeLists.txt +++ b/server/internal/CMakeLists.txt @@ -1,9 +1,13 @@ set(CMAKE_CXX_STANDARD 20) cmake_minimum_required(VERSION 3.19) + add_subdirectory(src) add_subdirectory(entities) add_subdirectory(repository) add_subdirectory(dbManager) +add_subdirectory(service) + + set(libEntities_LIB ${libEntities_LIB} PARENT_SCOPE) set(libEntities_INCLUDE_DIRS ${libEntities_INCLUDE_DIRS} PARENT_SCOPE) diff --git a/server/internal/service/CMakeLists.txt b/server/internal/service/CMakeLists.txt new file mode 100644 index 0000000..969968e --- /dev/null +++ b/server/internal/service/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.19) + +project("ServiceLib") + +file(GLOB SOURCES ./src/*.cpp) +file(GLOB INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include /home/denis/2023_1_DDT/antlr/virtual) + + +include_directories(${INCLUDE_DIRS}) +add_library(${PROJECT_NAME} ${SOURCES}) + +# target_link_libraries(${LIB_NAME}) + +set(SERVICE_LIBRARY ${PROJECT_NAME} PARENT_SCOPE) +set(SERVICE_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) + + +enable_testing() +add_subdirectory(tests) \ No newline at end of file -- GitLab From a3fecdaadf6293e166032ed8671a70af76c934b6 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 18:25:08 +0300 Subject: [PATCH 04/19] create docker container --- .github/workflows/ci.yml | 26 +-- Dockerfile | 28 +++ src/main.cpp | 477 +++++++++++++++++---------------------- 3 files changed, 240 insertions(+), 291 deletions(-) create mode 100644 Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e069cd..3859e29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,26 +13,9 @@ defaults: jobs: build: runs-on: ubuntu-latest + container: raiden454/sourced-out steps: - uses: actions/checkout@v3 - - name: Installing - run: | - sudo apt update - wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz - tar xvf boost_1_82_0.tar.gz - cd boost_1_82_0 - ./bootstrap.sh --prefix=/usr/ - sudo ./b2 install - cd .. - - git clone https://github.com/google/googletest.git -b release-1.11.0 - cd googletest - mkdir build - cd build - cmake .. -DBUILD_GMOCK=OFF - make - sudo make install - cd ../.. - name: Building run: | mkdir build @@ -44,14 +27,9 @@ jobs: # ./build/tests/test_parser linters: runs-on: ubuntu-latest + container: raiden454/sourced-out needs: [build] steps: - - uses: actions/checkout@v3 - - name: Installing - run: | - sudo apt update - sudo apt install cppcheck - pip install cpplint - name: Cppcheck run: | cppcheck --language=c++ ./src/main.cpp diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cdea2e8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:20.04 AS base + +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt update -y +RUN apt install -y gcc +RUN apt install -y libpqxx-dev +RUN apt install -y clang-tidy +RUN apt install -y python3-pip +RUN apt install -y cppcheck +RUN apt install -y cmake +RUN apt install -y libboost-all-dev +RUN apt install -y git +RUN apt-get update -y +RUN apt install -y xvfb +RUN pip install gcovr +RUN pip install cpplint + +RUN git clone https://github.com/google/googletest.git -b release-1.11.0 +WORKDIR googletest/build +RUN cmake .. -DBUILD_GMOCK=OFF +RUN make +RUN make install + +WORKDIR /project + +COPY . . \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a222488..cbd2bd5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,8 @@ +#include #include #include #include -#include #include #include #include @@ -10,312 +10,255 @@ #include #include -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -using tcp = boost::asio::ip::tcp; // from +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"; +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); +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; + 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()); + char constexpr path_separator = '/'; + if (result.back() == path_separator) result.resize(result.size() - 1); + result.append(path.data(), path.size()); #endif - return result; + 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< - class Body, class Allocator, - class Send> -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())}; +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"; +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_); - } +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; - } +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); + // Send a TCP shutdown + socket.shutdown(tcp::socket::shutdown_send, ec); - // At this point the connection is closed gracefully + // 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(); - } +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; } - catch (const std::exception& e) - { - std::cerr << "Error: " << e.what() << std::endl; - 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(); } -} \ No newline at end of file + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; + } +} -- GitLab From d727decc36204efc32051962c05927944d7f94ee Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 19:23:06 +0300 Subject: [PATCH 05/19] fix boost --- Dockerfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cdea2e8..16fed7e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,13 +10,19 @@ RUN apt install -y clang-tidy RUN apt install -y python3-pip RUN apt install -y cppcheck RUN apt install -y cmake -RUN apt install -y libboost-all-dev RUN apt install -y git RUN apt-get update -y RUN apt install -y xvfb RUN pip install gcovr RUN pip install cpplint +RUN apt-get install wget +RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz +RUN tar xvf boost_1_82_0.tar.gz +WORKDIR boost_1_82_0 +RUN ./bootstrap.sh --prefix=/usr/ +RUN ./b2 install + RUN git clone https://github.com/google/googletest.git -b release-1.11.0 WORKDIR googletest/build RUN cmake .. -DBUILD_GMOCK=OFF -- GitLab From e5daf13f5a155c26baf722cea52e5db48a365c02 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 19:40:35 +0300 Subject: [PATCH 06/19] add compile flags --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41ba7c6..7efaa4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ set(CMAKE_CXX_STANDARD 17) -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.19) set(CMAKE_PREFIX_PATH build) project(SourcedOut CXX) # find_package(antlr4-runtime REQUIRED) @@ -7,6 +7,7 @@ find_package(Boost 1.8.1 REQUIRED) # find_package(libpqxx REQUIRED) find_package(GTest REQUIRED) message(STATUS ${Boost_LIBRARIES}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lboost_system -lboost_thread -lpthread") 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 -- GitLab From bc349bb2464f2fdd0db299ec923b161b30381400 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 20:12:42 +0300 Subject: [PATCH 07/19] change cmakelists --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7efaa4a..5054100 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,15 @@ set(CMAKE_CXX_STANDARD 17) -cmake_minimum_required(VERSION 3.19) +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} -lboost_system -lboost_thread -lpthread") +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 -- GitLab From 7409880f0e1a665867c9f71efba9e982d7e698d5 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2023 21:56:03 +0300 Subject: [PATCH 08/19] fix ci --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3859e29..debe623 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: linters: runs-on: ubuntu-latest container: raiden454/sourced-out - needs: [build] steps: + - uses: actions/checkout@v3 - name: Cppcheck run: | - cppcheck --language=c++ ./src/main.cpp + cppcheck src --std=c++17 --enable=all - name: Cpplint run: | - cpplint --filter=-legal/copyright,-readability/casting,-whitespace/tab,-build/include_subdir --linelength=110 ./src/main.cpp \ No newline at end of file + cpplint --extensions=cpp,hpp --recursive ./src/* \ No newline at end of file -- GitLab From 484bc172a622d6788f8f446f34d475e8f67bc8a5 Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 11:33:20 +0300 Subject: [PATCH 09/19] make service structure --- .github/workflows/ci.yml | 4 ++-- server/CMakeLists.txt | 15 +++++++++---- server/internal/CMakeLists.txt | 5 ++++- server/internal/entities/include/Solution.hpp | 1 + server/internal/entities/include/Task.hpp | 1 + server/internal/entities/include/User.hpp | 1 + .../repository/include/SolutionRepository.hpp | 2 +- .../repository/src/SolutionRepository.cpp | 12 +++++------ .../repository/src/TaskRepository.cpp | 8 +++---- .../repository/src/UserRepository.cpp | 10 ++++----- server/internal/service/CMakeLists.txt | 14 ++++++++----- .../service/include/SolutionService.h | 20 ++++++++++++++++++ server/internal/service/include/TaskService.h | 17 +++++++++++++++ server/internal/service/include/UserService.h | 18 ++++++++++++++++ .../internal/service/include/UserValidator.h | 16 ++++++++++++++ .../internal/service/src/SolutionService.cpp | 21 +++++++++++++++++++ server/internal/service/src/TaskService.cpp | 12 +++++++++++ server/internal/service/src/UserService.cpp | 13 ++++++++++++ server/internal/service/src/UserValidator.cpp | 11 ++++++++++ server/internal/service/tests/CMakeLists.txt | 16 ++++++++++++++ .../service/tests/UserService_test.cpp | 1 + .../service/virtual/ISolutionService.h | 16 ++++++++++++++ .../internal/service/virtual/ITaskService.h | 11 ++++++++++ .../internal/service/virtual/IUserService.h | 13 ++++++++++++ 24 files changed, 230 insertions(+), 28 deletions(-) create mode 100644 server/internal/service/include/SolutionService.h create mode 100644 server/internal/service/include/TaskService.h create mode 100644 server/internal/service/include/UserService.h create mode 100644 server/internal/service/include/UserValidator.h create mode 100644 server/internal/service/src/SolutionService.cpp create mode 100644 server/internal/service/src/TaskService.cpp create mode 100644 server/internal/service/src/UserService.cpp create mode 100644 server/internal/service/src/UserValidator.cpp create mode 100644 server/internal/service/tests/CMakeLists.txt create mode 100644 server/internal/service/tests/UserService_test.cpp create mode 100644 server/internal/service/virtual/ISolutionService.h create mode 100644 server/internal/service/virtual/ITaskService.h create mode 100644 server/internal/service/virtual/IUserService.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index debe623..8c816f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3 - name: Cppcheck run: | - cppcheck src --std=c++17 --enable=all + cppcheck server --std=c++17 --enable=all - name: Cpplint run: | - cpplint --extensions=cpp,hpp --recursive ./src/* \ No newline at end of file + cpplint --extensions=cpp,hpp,h --recursive ./server/* \ No newline at end of file diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 5054100..2b07502 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -1,15 +1,22 @@ -set(CMAKE_CXX_STANDARD 17) -cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 20) +cmake_minimum_required(VERSION 3.19) 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) +find_package(nlohmann_json REQUIRED) +message(STATUS ${nlohmann_json_LIBRARIES}) + set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) + +add_subdirectory(internal) +add_subdirectory(cmd) + 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 +# target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES} ${antlr4-runtime_LIBRARIES} ${libpqxx_LIBRARIES} ${GTest_LIBRARIES}) \ No newline at end of file diff --git a/server/internal/CMakeLists.txt b/server/internal/CMakeLists.txt index 4d65978..e1397ef 100644 --- a/server/internal/CMakeLists.txt +++ b/server/internal/CMakeLists.txt @@ -15,4 +15,7 @@ set(libRepository_LIB ${libRepository_LIB} PARENT_SCOPE) set(libRepository_INCLUDE_DIRS ${libRepository_INCLUDE_DIRS} PARENT_SCOPE) set(DB_Lib_LIB ${DB_Lib_LIB} PARENT_SCOPE) -set(DB_Lib_INCLUDE_DIRS ${DB_Lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file +set(DB_Lib_INCLUDE_DIRS ${DB_Lib_INCLUDE_DIRS} PARENT_SCOPE) + +set(SERVICE_LIB ${SERVICE_lib_LIB} PARENT_SCOPE) +set(SERVICE_INCLUDE_DIRS ${SERVICE_lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/server/internal/entities/include/Solution.hpp b/server/internal/entities/include/Solution.hpp index dcfa255..5c39ef5 100644 --- a/server/internal/entities/include/Solution.hpp +++ b/server/internal/entities/include/Solution.hpp @@ -7,6 +7,7 @@ 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); diff --git a/server/internal/entities/include/Task.hpp b/server/internal/entities/include/Task.hpp index a9832ec..af8fad9 100644 --- a/server/internal/entities/include/Task.hpp +++ b/server/internal/entities/include/Task.hpp @@ -8,6 +8,7 @@ private: std::string description; public: + Task()=default; Task(size_t id, std::string description); explicit Task(std::string description); diff --git a/server/internal/entities/include/User.hpp b/server/internal/entities/include/User.hpp index b4dba92..20b3f88 100644 --- a/server/internal/entities/include/User.hpp +++ b/server/internal/entities/include/User.hpp @@ -13,6 +13,7 @@ private: 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_); diff --git a/server/internal/repository/include/SolutionRepository.hpp b/server/internal/repository/include/SolutionRepository.hpp index 2642624..31a1845 100644 --- a/server/internal/repository/include/SolutionRepository.hpp +++ b/server/internal/repository/include/SolutionRepository.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "../virtual/ISolutionRepository.hpp" +#include "ISolutionRepository.hpp" using namespace pqxx; diff --git a/server/internal/repository/src/SolutionRepository.cpp b/server/internal/repository/src/SolutionRepository.cpp index 05e200f..215d7ed 100644 --- a/server/internal/repository/src/SolutionRepository.cpp +++ b/server/internal/repository/src/SolutionRepository.cpp @@ -23,7 +23,7 @@ Solution SolutionRepository::getSolutionById(size_t id) { result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); return makeSolution(r.begin()); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; @@ -46,7 +46,7 @@ std::vector SolutionRepository::getSolutionsBySenderId(size_t sender_i result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); std::vector solutions; for(result::const_iterator k = r.begin(); k != r.end(); ++k) solutions.push_back(makeSolution(k)); @@ -72,7 +72,7 @@ std::vector SolutionRepository::getSolutionsByTaskId(size_t task_id) result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); std::vector solutions; for(result::const_iterator k = r.begin(); k != r.end(); ++k) solutions.push_back(makeSolution(k)); @@ -100,7 +100,7 @@ void SolutionRepository::storeSolution(Solution solution) { w.commit(); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; @@ -123,7 +123,7 @@ void SolutionRepository::updateSolution(Solution solution) { w.exec(sql); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; @@ -145,7 +145,7 @@ void SolutionRepository::deleteSolutionById(size_t id) { w.commit(); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; diff --git a/server/internal/repository/src/TaskRepository.cpp b/server/internal/repository/src/TaskRepository.cpp index a90b3b6..98b2007 100644 --- a/server/internal/repository/src/TaskRepository.cpp +++ b/server/internal/repository/src/TaskRepository.cpp @@ -20,7 +20,7 @@ Task TaskRepository::getTaskById(size_t id) { result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); return makeTask(r.begin()); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; @@ -43,7 +43,7 @@ void TaskRepository::updateTask(Task task) { w.exec(sql); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; @@ -67,7 +67,7 @@ void TaskRepository::storeTask(Task task) { w.commit(); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; @@ -93,7 +93,7 @@ void TaskRepository::deleteTaskById(size_t task_id) { w.commit(); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; diff --git a/server/internal/repository/src/UserRepository.cpp b/server/internal/repository/src/UserRepository.cpp index 835402f..fcbe486 100644 --- a/server/internal/repository/src/UserRepository.cpp +++ b/server/internal/repository/src/UserRepository.cpp @@ -22,7 +22,7 @@ User UserRepository::getUserById(size_t id) { result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); return makeUser(r.begin()); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; @@ -45,7 +45,7 @@ User UserRepository::getUserByLogin(std::string login) { result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); return makeUser(r.begin()); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; @@ -71,7 +71,7 @@ size_t UserRepository::makeUser(User user) { log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); return getUserByLogin(user.getLogin()).getId(); } catch (const std::exception &e) { @@ -95,7 +95,7 @@ void UserRepository::deleteByUserId(size_t user_id) { w.commit(); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; throw e; @@ -122,7 +122,7 @@ std::vector UserRepository::getAllUsers() { result r(n.exec(sql)); log << "OK" << std::endl; log.close(); - c.close(); + //c.close(); std::vector users; for (result::const_iterator k = r.begin(); k != r.end(); ++k) users.push_back(makeUser(k)); diff --git a/server/internal/service/CMakeLists.txt b/server/internal/service/CMakeLists.txt index 969968e..31cf7fa 100644 --- a/server/internal/service/CMakeLists.txt +++ b/server/internal/service/CMakeLists.txt @@ -2,17 +2,21 @@ cmake_minimum_required(VERSION 3.19) project("ServiceLib") -file(GLOB SOURCES ./src/*.cpp) -file(GLOB INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include /home/denis/2023_1_DDT/antlr/virtual) +file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/virtual) include_directories(${INCLUDE_DIRS}) add_library(${PROJECT_NAME} ${SOURCES}) -# target_link_libraries(${LIB_NAME}) +message("libRepository_LIB = ${libRepository_LIB}") +message("libRepository_INCLUDE_DIRS = ${libRepository_INCLUDE_DIRS}") -set(SERVICE_LIBRARY ${PROJECT_NAME} PARENT_SCOPE) -set(SERVICE_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) +# target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIRS} ${libEntities_INCLUDE_DIRS} ${libRepository_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} ${libRepository_LIB} ${ibEntities_LIB}) + +set(SERVICE_lib_LIBRARY ${PROJECT_NAME} PARENT_SCOPE) +set(SERVICE_lib_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) enable_testing() diff --git a/server/internal/service/include/SolutionService.h b/server/internal/service/include/SolutionService.h new file mode 100644 index 0000000..5b0a38d --- /dev/null +++ b/server/internal/service/include/SolutionService.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "ISolutionRepository.h" +#include "ISolutionService.h" + +class SolutionService : ISolutionService { + private: + std::unique_ptr solutionRepo; + // std::unique_ptr antlr + public: + explicit SolutionService(std::unique_ptr solutionRepo); + Solution createSolution(size_t userId, size_t taskId, + std::string source) override; + std::vector getSolutionsByUserAndTaskId(size_t userId, + size_t taskId) override; + void deleteSolutionById(size_t solId) override; + std::pair getMetrics(size_t solId) override; +}; diff --git a/server/internal/service/include/TaskService.h b/server/internal/service/include/TaskService.h new file mode 100644 index 0000000..e03917f --- /dev/null +++ b/server/internal/service/include/TaskService.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "ITaskRepository.h" +#include "ITaskService.h" + +class TaskService : ITaskService { + private: + std::unique_ptr taskRepo; + + public: + explicit TaskService(std::unique_ptr taskRepo); + Task createTask(std::string desc) override; + std::vector getAllTasks(size_t id) override; + void deleteTask(size_t id) override; +}; diff --git a/server/internal/service/include/UserService.h b/server/internal/service/include/UserService.h new file mode 100644 index 0000000..b27a645 --- /dev/null +++ b/server/internal/service/include/UserService.h @@ -0,0 +1,18 @@ +#pragma once +#include + +#include "IUserRepository.h" +#include "IUserService.h" +#include "UserValidation.h" + +class UserService : IUserService { + private: + std::unique_ptr userRepo; + + public: + explicit UserService(std::unique_ptr userRepo); + User createUser(std::string login, std::string username, + std::string password) override; + User getUserById(size_t id) override; + void deleteUser(size_t id) override; +}; diff --git a/server/internal/service/include/UserValidator.h b/server/internal/service/include/UserValidator.h new file mode 100644 index 0000000..8a7b155 --- /dev/null +++ b/server/internal/service/include/UserValidator.h @@ -0,0 +1,16 @@ +#pragma once + +#include "User.h" + +class UserValidator { + private: + User user; + bool validateLogin(); + bool validatePassword(); + bool validateUsername(); + + public: + explicit UserValidator(User user); + bool validateUser(); + ~UserValidator(); +}; diff --git a/server/internal/service/src/SolutionService.cpp b/server/internal/service/src/SolutionService.cpp new file mode 100644 index 0000000..bc01136 --- /dev/null +++ b/server/internal/service/src/SolutionService.cpp @@ -0,0 +1,21 @@ +#include "SolutionService.h" + +SolutionService::SolutionService( + std::unique_ptr solutionRepo) + : solutionRepo(std::move(solutionRepo)) {} + +Solution SolutionService::createSolution(size_t userId, size_t taskId, + std::string source) { + return Solution(); +} + +std::vector SolutionService::getSolutionsByUserAndTaskId( + size_t userId, size_t taskId) { + return std::vector(); +} + +SolutionService::deleteSolutionById(size_t solId) {} + +std::pair Solution::getMetrics(size_t solId) { + return std::make_pair("", ""); +} diff --git a/server/internal/service/src/TaskService.cpp b/server/internal/service/src/TaskService.cpp new file mode 100644 index 0000000..3c2b89b --- /dev/null +++ b/server/internal/service/src/TaskService.cpp @@ -0,0 +1,12 @@ +#include "TaskService.h" + +TaskService::TaskService(std::unique_ptr taskRepo) + : taskRepo(std::move(taskRepo)) {} + +Task TaskService::createTask(std::string desc) { return Task(); } + +std::vector TaskService::getAllTasks(size_t id) { + return std::vector(); +} + +void TaskService::deleteTask(size_t id) {} diff --git a/server/internal/service/src/UserService.cpp b/server/internal/service/src/UserService.cpp new file mode 100644 index 0000000..8cbd084 --- /dev/null +++ b/server/internal/service/src/UserService.cpp @@ -0,0 +1,13 @@ +#include "UserService.h" + +UserService::UserService(std::unique_ptr userRepo) + : userRepo(std::move(userRepo)) {} + +User UserService::createUser(std::string login, std::string username, + std::string password) { + return User(); +} + +User UserService::getUserById(size_t id) { return User(); } + +void UserService::deleteUser(size_t id) {} diff --git a/server/internal/service/src/UserValidator.cpp b/server/internal/service/src/UserValidator.cpp new file mode 100644 index 0000000..da64212 --- /dev/null +++ b/server/internal/service/src/UserValidator.cpp @@ -0,0 +1,11 @@ +#include "UserValidator.h" + +UserValidator::UserValidator(User user) : user(user) {} + +bool UserValidator::validateUser() { return true; } + +bool UserValidator::validateLogin() { return true; } + +bool UserValidator::validatePassword() { return true; } + +bool UserValidator::validateUsername() { return true; } diff --git a/server/internal/service/tests/CMakeLists.txt b/server/internal/service/tests/CMakeLists.txt new file mode 100644 index 0000000..95d96c7 --- /dev/null +++ b/server/internal/service/tests/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.16) +project(test_service) + +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_include_directories(${PROJECT_NAME} PUBLIC ${SERVICE_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} ${SERVICE_LIBRARY} GTest::GTest) + +add_test(test_service test_service) \ No newline at end of file diff --git a/server/internal/service/tests/UserService_test.cpp b/server/internal/service/tests/UserService_test.cpp new file mode 100644 index 0000000..7b243ad --- /dev/null +++ b/server/internal/service/tests/UserService_test.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/server/internal/service/virtual/ISolutionService.h b/server/internal/service/virtual/ISolutionService.h new file mode 100644 index 0000000..0c37337 --- /dev/null +++ b/server/internal/service/virtual/ISolutionService.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "Solution.hpp" + +class ISolutionService { + public: + virtual Solution createSolution(size_t userId, size_t taskId, + std::string source) = 0; + virtual std::vector getSolutionByUserAndTaskId(size_t userId, + size_t taskId) = 0; + virtual deleteSolutionById(size_t solId) = 0; + + virtual std::pair getMetrics(size_t solId) = 0; +}; diff --git a/server/internal/service/virtual/ITaskService.h b/server/internal/service/virtual/ITaskService.h new file mode 100644 index 0000000..2a1029d --- /dev/null +++ b/server/internal/service/virtual/ITaskService.h @@ -0,0 +1,11 @@ +#pragma once +#include "Task.hpp" +#include + + +class ITaskService { + public: + virtual Task createTask(std::string desc) = 0; + virtual std::vector getAllTasks(size_t id) = 0; + virtual void deleteTask(size_t id) = 0; +}; diff --git a/server/internal/service/virtual/IUserService.h b/server/internal/service/virtual/IUserService.h new file mode 100644 index 0000000..1b02932 --- /dev/null +++ b/server/internal/service/virtual/IUserService.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "User.hpp" + +class IUserService { + public: + virtual User createUser(std::string login, std::string username, + std::string password) = 0; + virtual User getUserById(size_t id) = 0; + virtual deleteUser(size_t id) = 0; +}; -- GitLab From 4af898fbc4ab51320fb2628121f90d48f48da85d Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 12:11:11 +0300 Subject: [PATCH 10/19] local bild passed --- server/internal/CMakeLists.txt | 2 +- server/internal/repository/CMakeLists.txt | 6 +++--- server/internal/service/include/SolutionService.h | 2 +- server/internal/service/include/TaskService.h | 2 +- server/internal/service/include/UserService.h | 4 ++-- server/internal/service/include/UserValidator.h | 2 +- server/internal/service/src/SolutionService.cpp | 4 ++-- server/internal/service/tests/UserService_test.cpp | 8 +++++++- server/internal/service/virtual/ISolutionService.h | 7 ++++--- server/internal/service/virtual/IUserService.h | 2 +- 10 files changed, 23 insertions(+), 16 deletions(-) diff --git a/server/internal/CMakeLists.txt b/server/internal/CMakeLists.txt index ff8b7cb..c3d79ef 100644 --- a/server/internal/CMakeLists.txt +++ b/server/internal/CMakeLists.txt @@ -4,8 +4,8 @@ cmake_minimum_required(VERSION 3.19) add_subdirectory(src) add_subdirectory(entities) add_subdirectory(dbManager) -add_subdirectory(service) add_subdirectory(repository) +add_subdirectory(service) set(libEntities_LIB ${libEntities_LIB} PARENT_SCOPE) set(libEntities_INCLUDE_DIRS ${libEntities_INCLUDE_DIRS} PARENT_SCOPE) diff --git a/server/internal/repository/CMakeLists.txt b/server/internal/repository/CMakeLists.txt index c3eeeee..872a4fa 100644 --- a/server/internal/repository/CMakeLists.txt +++ b/server/internal/repository/CMakeLists.txt @@ -5,7 +5,7 @@ project("RepositoryLib") set(LIB_NAME libRepository) 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) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/virtual/*.hpp) message("SOURCES = ${SOURCES}") message("HEADERS = ${HEADERS}") @@ -18,13 +18,13 @@ 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) +target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/virtual) target_link_libraries(${LIB_NAME} ${Boost_LIBRARIES} ${libpqxx_LIBRARIES} ${libEntities_LIB} ${libDbManager_LIB}) set(libRepository_LIB ${LIB_NAME}) set(libRepository_LIB ${libRepository_LIB} PARENT_SCOPE) -set(libRepository_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(libRepository_INCLUDE_DIRS ${LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/virtual) set(libRepository_INCLUDE_DIRS ${libRepository_INCLUDE_DIRS} PARENT_SCOPE) diff --git a/server/internal/service/include/SolutionService.h b/server/internal/service/include/SolutionService.h index 5b0a38d..86e432b 100644 --- a/server/internal/service/include/SolutionService.h +++ b/server/internal/service/include/SolutionService.h @@ -2,7 +2,7 @@ #include -#include "ISolutionRepository.h" +#include "ISolutionRepository.hpp" #include "ISolutionService.h" class SolutionService : ISolutionService { diff --git a/server/internal/service/include/TaskService.h b/server/internal/service/include/TaskService.h index e03917f..5723fd0 100644 --- a/server/internal/service/include/TaskService.h +++ b/server/internal/service/include/TaskService.h @@ -2,7 +2,7 @@ #include -#include "ITaskRepository.h" +#include "ITaskRepository.hpp" #include "ITaskService.h" class TaskService : ITaskService { diff --git a/server/internal/service/include/UserService.h b/server/internal/service/include/UserService.h index b27a645..aa0de45 100644 --- a/server/internal/service/include/UserService.h +++ b/server/internal/service/include/UserService.h @@ -1,9 +1,9 @@ #pragma once #include -#include "IUserRepository.h" +#include "IUserRepository.hpp" #include "IUserService.h" -#include "UserValidation.h" +#include "UserValidator.h" class UserService : IUserService { private: diff --git a/server/internal/service/include/UserValidator.h b/server/internal/service/include/UserValidator.h index 8a7b155..77f1a50 100644 --- a/server/internal/service/include/UserValidator.h +++ b/server/internal/service/include/UserValidator.h @@ -1,6 +1,6 @@ #pragma once -#include "User.h" +#include "User.hpp" class UserValidator { private: diff --git a/server/internal/service/src/SolutionService.cpp b/server/internal/service/src/SolutionService.cpp index bc01136..ba707c3 100644 --- a/server/internal/service/src/SolutionService.cpp +++ b/server/internal/service/src/SolutionService.cpp @@ -14,8 +14,8 @@ std::vector SolutionService::getSolutionsByUserAndTaskId( return std::vector(); } -SolutionService::deleteSolutionById(size_t solId) {} +void SolutionService::deleteSolutionById(size_t solId) {} -std::pair Solution::getMetrics(size_t solId) { +std::pair SolutionService::getMetrics(size_t solId) { return std::make_pair("", ""); } diff --git a/server/internal/service/tests/UserService_test.cpp b/server/internal/service/tests/UserService_test.cpp index 7b243ad..63abcf0 100644 --- a/server/internal/service/tests/UserService_test.cpp +++ b/server/internal/service/tests/UserService_test.cpp @@ -1 +1,7 @@ -#include \ No newline at end of file +#include + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/server/internal/service/virtual/ISolutionService.h b/server/internal/service/virtual/ISolutionService.h index 0c37337..e7fb0e1 100644 --- a/server/internal/service/virtual/ISolutionService.h +++ b/server/internal/service/virtual/ISolutionService.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "Solution.hpp" @@ -8,9 +9,9 @@ class ISolutionService { public: virtual Solution createSolution(size_t userId, size_t taskId, std::string source) = 0; - virtual std::vector getSolutionByUserAndTaskId(size_t userId, - size_t taskId) = 0; - virtual deleteSolutionById(size_t solId) = 0; + virtual std::vector getSolutionsByUserAndTaskId(size_t userId, + size_t taskId) = 0; + virtual void deleteSolutionById(size_t solId) = 0; virtual std::pair getMetrics(size_t solId) = 0; }; diff --git a/server/internal/service/virtual/IUserService.h b/server/internal/service/virtual/IUserService.h index 1b02932..ad74eff 100644 --- a/server/internal/service/virtual/IUserService.h +++ b/server/internal/service/virtual/IUserService.h @@ -9,5 +9,5 @@ class IUserService { virtual User createUser(std::string login, std::string username, std::string password) = 0; virtual User getUserById(size_t id) = 0; - virtual deleteUser(size_t id) = 0; + virtual void deleteUser(size_t id) = 0; }; -- GitLab From 0a2468e4ec4ed89a650ba42c18d5861126c2a11a Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 20:43:00 +0300 Subject: [PATCH 11/19] test init --- server/CMakeLists.txt | 1 + server/internal/entities/include/Task.hpp | 1 + .../repository/include/TaskRepository.hpp | 2 +- .../repository/virtual/ITaskRepository.hpp | 2 + server/internal/service/CMakeLists.txt | 6 ++- server/internal/service/include/TaskService.h | 8 ++-- server/internal/service/src/TaskService.cpp | 8 ++-- server/internal/service/tests/CMakeLists.txt | 6 ++- .../internal/service/tests/Service_test.cpp | 46 +++++++++++++++++++ .../service/tests/UserService_test.cpp | 7 --- .../internal/service/virtual/ITaskService.h | 6 ++- 11 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 server/internal/service/tests/Service_test.cpp delete mode 100644 server/internal/service/tests/UserService_test.cpp diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 52a7e1c..53ca1ea 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -5,6 +5,7 @@ project(SourcedOut CXX) # find_package(antlr4-runtime REQUIRED) find_package(Boost 1.8.1 REQUIRED) # find_package(libpqxx REQUIRED) +find_library(PQXX_LIB pqxx) find_package(GTest REQUIRED) find_package(nlohmann_json REQUIRED) message(STATUS ${nlohmann_json_LIBRARIES}) diff --git a/server/internal/entities/include/Task.hpp b/server/internal/entities/include/Task.hpp index af8fad9..6ad362f 100644 --- a/server/internal/entities/include/Task.hpp +++ b/server/internal/entities/include/Task.hpp @@ -9,6 +9,7 @@ private: public: Task()=default; + ~Task() = default; Task(size_t id, std::string description); explicit Task(std::string description); diff --git a/server/internal/repository/include/TaskRepository.hpp b/server/internal/repository/include/TaskRepository.hpp index 793ea2f..6780c36 100644 --- a/server/internal/repository/include/TaskRepository.hpp +++ b/server/internal/repository/include/TaskRepository.hpp @@ -9,7 +9,7 @@ using namespace pqxx; -class TaskRepository : ITaskRepository { +class TaskRepository : public ITaskRepository { public: Task getTaskById(size_t id) override; diff --git a/server/internal/repository/virtual/ITaskRepository.hpp b/server/internal/repository/virtual/ITaskRepository.hpp index 26d32d2..1ba3292 100644 --- a/server/internal/repository/virtual/ITaskRepository.hpp +++ b/server/internal/repository/virtual/ITaskRepository.hpp @@ -5,6 +5,8 @@ #include "../../entities/include/Task.hpp" class ITaskRepository { + public: + virtual ~ITaskRepository() = default; virtual Task getTaskById(size_t id) = 0; virtual void updateTask(Task task) = 0; diff --git a/server/internal/service/CMakeLists.txt b/server/internal/service/CMakeLists.txt index 31cf7fa..f405d37 100644 --- a/server/internal/service/CMakeLists.txt +++ b/server/internal/service/CMakeLists.txt @@ -15,9 +15,11 @@ message("libRepository_INCLUDE_DIRS = ${libRepository_INCLUDE_DIRS}") # target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIRS} ${libEntities_INCLUDE_DIRS} ${libRepository_INCLUDE_DIRS}) target_link_libraries(${PROJECT_NAME} ${libRepository_LIB} ${ibEntities_LIB}) -set(SERVICE_lib_LIBRARY ${PROJECT_NAME} PARENT_SCOPE) -set(SERVICE_lib_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) +set(SERVICE_lib_LIBRARY ${PROJECT_NAME}) +set(SERVICE_lib_LIBRARY ${SERVICE_lib_LIBRARY} PARENT_SCOPE) +set(SERVICE_lib_INCLUDE_DIRS ${INCLUDE_DIRS}) +set(SERVICE_lib_INCLUDE_DIRS ${SERVICE_lib_INCLUDE_DIRS} PARENT_SCOPE) enable_testing() add_subdirectory(tests) \ No newline at end of file diff --git a/server/internal/service/include/TaskService.h b/server/internal/service/include/TaskService.h index 5723fd0..bf04d3e 100644 --- a/server/internal/service/include/TaskService.h +++ b/server/internal/service/include/TaskService.h @@ -5,13 +5,15 @@ #include "ITaskRepository.hpp" #include "ITaskService.h" -class TaskService : ITaskService { +class TaskService : public ITaskService { private: std::unique_ptr taskRepo; public: - explicit TaskService(std::unique_ptr taskRepo); + TaskService(std::unique_ptr taskRepo); + ~TaskService() override = default; Task createTask(std::string desc) override; - std::vector getAllTasks(size_t id) override; + Task getTask(size_t id) override; + std::vector getAllTasks() override; void deleteTask(size_t id) override; }; diff --git a/server/internal/service/src/TaskService.cpp b/server/internal/service/src/TaskService.cpp index 3c2b89b..92452f3 100644 --- a/server/internal/service/src/TaskService.cpp +++ b/server/internal/service/src/TaskService.cpp @@ -5,8 +5,8 @@ TaskService::TaskService(std::unique_ptr taskRepo) Task TaskService::createTask(std::string desc) { return Task(); } -std::vector TaskService::getAllTasks(size_t id) { - return std::vector(); -} +std::vector TaskService::getAllTasks() { return std::vector(); } -void TaskService::deleteTask(size_t id) {} +Task TaskService::getTask(size_t id) { return taskRepo->getTaskById(id); } + +void TaskService::deleteTask(size_t id) { taskRepo->deleteTaskById(id); } diff --git a/server/internal/service/tests/CMakeLists.txt b/server/internal/service/tests/CMakeLists.txt index 95d96c7..1b81101 100644 --- a/server/internal/service/tests/CMakeLists.txt +++ b/server/internal/service/tests/CMakeLists.txt @@ -10,7 +10,9 @@ enable_testing() find_package(GTest REQUIRED) add_executable(${PROJECT_NAME} ${SOURCES}) -target_include_directories(${PROJECT_NAME} PUBLIC ${SERVICE_INCLUDE_DIRS}) -target_link_libraries(${PROJECT_NAME} ${SERVICE_LIBRARY} GTest::GTest) + +target_link_libraries(${PROJECT_NAME} ${SERVICE_lib_LIBRARY} GTest::GTest gmock pthread) +target_include_directories(${PROJECT_NAME} PUBLIC ${SERVICE_lib_INCLUDE_DIRS}) + add_test(test_service test_service) \ No newline at end of file diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp new file mode 100644 index 0000000..2210fd3 --- /dev/null +++ b/server/internal/service/tests/Service_test.cpp @@ -0,0 +1,46 @@ +#include +#include + +#include + +#include "TaskService.h" + +class TaskRepositoryMock : public ITaskRepository { + public: + ~TaskRepositoryMock() override = default; + MOCK_METHOD(Task, getTaskById, (size_t id), (override)); + MOCK_METHOD(void, updateTask, (Task task), (override)); + MOCK_METHOD(void, storeTask, (Task task), (override)); + MOCK_METHOD(void, deleteTask, (Task task), (override)); + MOCK_METHOD(void, deleteTaskById, (size_t id), (override)); +}; + +struct TaskServiceTest : public testing::Test { + TaskService* ts; + TaskRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + ts = new TaskService(std::move(mock)); + } + void TearDown() { + delete ts; + } +}; + +TEST_F(TaskServiceTest, GetTask) { + EXPECT_CALL(*mock_ptr, deleteTaskById(1)); + ts->deleteTask(1); +} + +TEST_F(TaskServiceTest, Test) { + int a = 2; + EXPECT_EQ(a, 2); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleMock(&argc, argv); + + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/server/internal/service/tests/UserService_test.cpp b/server/internal/service/tests/UserService_test.cpp deleted file mode 100644 index 63abcf0..0000000 --- a/server/internal/service/tests/UserService_test.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/server/internal/service/virtual/ITaskService.h b/server/internal/service/virtual/ITaskService.h index 2a1029d..731fb0f 100644 --- a/server/internal/service/virtual/ITaskService.h +++ b/server/internal/service/virtual/ITaskService.h @@ -1,11 +1,13 @@ #pragma once -#include "Task.hpp" #include +#include "Task.hpp" class ITaskService { public: + virtual ~ITaskService() = default; virtual Task createTask(std::string desc) = 0; - virtual std::vector getAllTasks(size_t id) = 0; + virtual Task getTask(size_t id) = 0; + virtual std::vector getAllTasks() = 0; virtual void deleteTask(size_t id) = 0; }; -- GitLab From f931ae85c2308e47f282abb7839bbe9ebd651c77 Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 20:45:53 +0300 Subject: [PATCH 12/19] upd ci --- .github/workflows/ci.yml | 4 +-- Dockerfile | 76 +++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index debe623..16503a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ defaults: jobs: build: runs-on: ubuntu-latest - container: raiden454/sourced-out + container: raiden454/ddt-project steps: - uses: actions/checkout@v3 - name: Building @@ -27,7 +27,7 @@ jobs: # ./build/tests/test_parser linters: runs-on: ubuntu-latest - container: raiden454/sourced-out + container: raiden454/ddt-project steps: - uses: actions/checkout@v3 - name: Cppcheck diff --git a/Dockerfile b/Dockerfile index 16fed7e..fd9957b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,44 @@ -FROM ubuntu:20.04 AS base - -ENV TZ=Europe/Moscow -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt update -y -RUN apt install -y gcc -RUN apt install -y libpqxx-dev -RUN apt install -y clang-tidy -RUN apt install -y python3-pip -RUN apt install -y cppcheck -RUN apt install -y cmake -RUN apt install -y git -RUN apt-get update -y -RUN apt install -y xvfb -RUN pip install gcovr -RUN pip install cpplint - -RUN apt-get install wget -RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz -RUN tar xvf boost_1_82_0.tar.gz -WORKDIR boost_1_82_0 -RUN ./bootstrap.sh --prefix=/usr/ -RUN ./b2 install - -RUN git clone https://github.com/google/googletest.git -b release-1.11.0 -WORKDIR googletest/build -RUN cmake .. -DBUILD_GMOCK=OFF -RUN make -RUN make install - -WORKDIR /project - +FROM ubuntu:20.04 AS base + +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt update -y +RUN apt install -y gcc +RUN apt install -y libpqxx-dev +RUN apt install -y clang-tidy +RUN apt install -y nlohmann-json3-dev +RUN apt install -y python3-pip +RUN apt install -y cppcheck +RUN apt install -y git +RUN apt-get update -y +RUN apt install -y xvfb +RUN pip install gcovr +RUN pip install cpplint + +RUN apt-get install wget +RUN apt-get install libssl-dev + +RUN wget https://github.com/Kitware/CMake/releases/download/v3.26.3/cmake-3.26.3.tar.gz +RUN tar -zxvf cmake-3.26.3.tar.gz +WORKDIR cmake-3.26.3 +RUN ./bootstrap +RUN make +RUN make install +RUN cd .. + +RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz +RUN tar xvf boost_1_82_0.tar.gz +WORKDIR boost_1_82_0 +RUN ./bootstrap.sh --prefix=/usr/ +RUN ./b2 install + +RUN git clone https://github.com/google/googletest.git -b release-1.11.0 +WORKDIR googletest/build +RUN cmake .. -DBUILD_GMOCK=OFF +RUN make +RUN make install + +WORKDIR /project + COPY . . \ No newline at end of file -- GitLab From 33b1a89961a09a850d028333af5e7ae5fc66a52d Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 20:56:44 +0300 Subject: [PATCH 13/19] add my tests to ci --- .github/workflows/ci.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c816f4..455e715 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ defaults: jobs: build: runs-on: ubuntu-latest - container: raiden454/sourced-out + container: raiden454/ddt-project steps: - uses: actions/checkout@v3 - name: Building @@ -22,12 +22,17 @@ jobs: cd build cmake .. make - # - name: Testing - # run: | - # ./build/tests/test_parser + tests: + runs-on: ubuntu-latest + container: raiden454/ddt-project + needs: [build] + steps: + - uses: actions/checkout@v3 + - name: Run-Tests + run: ./build/server/internal/service/tests/test_service linters: runs-on: ubuntu-latest - container: raiden454/sourced-out + container: raiden454/ddt-project steps: - uses: actions/checkout@v3 - name: Cppcheck @@ -35,4 +40,4 @@ jobs: cppcheck server --std=c++17 --enable=all - name: Cpplint run: | - cpplint --extensions=cpp,hpp,h --recursive ./server/* \ No newline at end of file + cpplint --extensions=cpp,hpp,h --recursive ./server/* -- GitLab From 969d4eab39f95d8956dfe78c8bb52a7119c67c6f Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 2 May 2023 23:26:33 +0300 Subject: [PATCH 14/19] add test support to ci --- .github/workflows/ci.yml | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16503a9..fb53bfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,26 +13,43 @@ defaults: jobs: build: runs-on: ubuntu-latest - container: raiden454/ddt-project + container: raiden454/cpp-app steps: - uses: actions/checkout@v3 + - name: Installing + run: | + apt update + git clone https://github.com/google/googletest.git -b release-1.11.0 + cd googletest + mkdir build + cd build + cmake .. -DBUILD_GMOCK=ON + make + make install + cd ../.. - name: Building run: | mkdir build cd build cmake .. make - # - name: Testing - # run: | - # ./build/tests/test_parser + # tests: + # runs-on: ubuntu-latest + # container: raiden454/cpp-app + # needs: [build] + # steps: + # - uses: actions/checkout@v3 + # - name: Run-Tests + # run: | + # find / -name "test_service" linters: runs-on: ubuntu-latest - container: raiden454/ddt-project + container: raiden454/cpp-app steps: - uses: actions/checkout@v3 - name: Cppcheck run: | - cppcheck src --std=c++17 --enable=all + cppcheck server --std=c++17 --enable=all - name: Cpplint run: | - cpplint --extensions=cpp,hpp --recursive ./src/* \ No newline at end of file + cpplint --extensions=cpp,hpp,h --recursive ./server/* -- GitLab From 10a888a8323d0a7d6377269e8e6b846ca968a8a6 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 3 May 2023 00:49:36 +0300 Subject: [PATCH 15/19] add some test to ci --- .github/workflows/ci.yml | 24 +++--- CMakeLists.txt | 2 +- Dockerfile | 76 +++++++++++-------- server/CMakeLists.txt | 2 - server/cmd/CMakeLists.txt | 4 - server/internal/CMakeLists.txt | 3 - server/internal/dbManager/CMakeLists.txt | 2 - server/internal/entities/CMakeLists.txt | 2 - server/internal/repository/CMakeLists.txt | 2 - .../repository/include/TaskRepository.hpp | 2 +- .../repository/src/TaskRepository.cpp | 3 +- .../repository/virtual/ITaskRepository.hpp | 2 +- server/internal/service/CMakeLists.txt | 2 - server/internal/service/src/TaskService.cpp | 4 +- server/internal/service/tests/CMakeLists.txt | 1 - .../internal/service/tests/Service_test.cpp | 55 +++++++++++--- server/internal/src/CMakeLists.txt | 2 - server/internal/src/db/CMakeLists.txt | 2 - 18 files changed, 112 insertions(+), 78 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 455e715..02e6602 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,26 +13,32 @@ defaults: jobs: build: runs-on: ubuntu-latest - container: raiden454/ddt-project + container: raiden454/cpp-app steps: - uses: actions/checkout@v3 + - name: Installing + run: | + apt update + git clone https://github.com/google/googletest.git -b release-1.11.0 + cd googletest + mkdir build + cd build + cmake .. -DBUILD_GMOCK=ON + make + make install + cd ../.. - name: Building run: | mkdir build cd build cmake .. make - tests: - runs-on: ubuntu-latest - container: raiden454/ddt-project - needs: [build] - steps: - - uses: actions/checkout@v3 - name: Run-Tests - run: ./build/server/internal/service/tests/test_service + run: | + ./build/server/internal/service/tests/test_service linters: runs-on: ubuntu-latest - container: raiden454/ddt-project + container: raiden454/cpp-app steps: - uses: actions/checkout@v3 - name: Cppcheck diff --git a/CMakeLists.txt b/CMakeLists.txt index e51f2bf..41c84fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ 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} --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") diff --git a/Dockerfile b/Dockerfile index 16fed7e..fd9957b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,44 @@ -FROM ubuntu:20.04 AS base - -ENV TZ=Europe/Moscow -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt update -y -RUN apt install -y gcc -RUN apt install -y libpqxx-dev -RUN apt install -y clang-tidy -RUN apt install -y python3-pip -RUN apt install -y cppcheck -RUN apt install -y cmake -RUN apt install -y git -RUN apt-get update -y -RUN apt install -y xvfb -RUN pip install gcovr -RUN pip install cpplint - -RUN apt-get install wget -RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz -RUN tar xvf boost_1_82_0.tar.gz -WORKDIR boost_1_82_0 -RUN ./bootstrap.sh --prefix=/usr/ -RUN ./b2 install - -RUN git clone https://github.com/google/googletest.git -b release-1.11.0 -WORKDIR googletest/build -RUN cmake .. -DBUILD_GMOCK=OFF -RUN make -RUN make install - -WORKDIR /project - +FROM ubuntu:20.04 AS base + +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt update -y +RUN apt install -y gcc +RUN apt install -y libpqxx-dev +RUN apt install -y clang-tidy +RUN apt install -y nlohmann-json3-dev +RUN apt install -y python3-pip +RUN apt install -y cppcheck +RUN apt install -y git +RUN apt-get update -y +RUN apt install -y xvfb +RUN pip install gcovr +RUN pip install cpplint + +RUN apt-get install wget +RUN apt-get install libssl-dev + +RUN wget https://github.com/Kitware/CMake/releases/download/v3.26.3/cmake-3.26.3.tar.gz +RUN tar -zxvf cmake-3.26.3.tar.gz +WORKDIR cmake-3.26.3 +RUN ./bootstrap +RUN make +RUN make install +RUN cd .. + +RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz +RUN tar xvf boost_1_82_0.tar.gz +WORKDIR boost_1_82_0 +RUN ./bootstrap.sh --prefix=/usr/ +RUN ./b2 install + +RUN git clone https://github.com/google/googletest.git -b release-1.11.0 +WORKDIR googletest/build +RUN cmake .. -DBUILD_GMOCK=OFF +RUN make +RUN make install + +WORKDIR /project + COPY . . \ No newline at end of file diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 53ca1ea..2e5c3dc 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -1,5 +1,3 @@ -set(CMAKE_CXX_STANDARD 20) -cmake_minimum_required(VERSION 3.19) set(CMAKE_PREFIX_PATH build) project(SourcedOut CXX) # find_package(antlr4-runtime REQUIRED) diff --git a/server/cmd/CMakeLists.txt b/server/cmd/CMakeLists.txt index 7b7c468..446f2a8 100644 --- a/server/cmd/CMakeLists.txt +++ b/server/cmd/CMakeLists.txt @@ -1,7 +1,3 @@ -cmake_minimum_required(VERSION 3.19) - -set(CMAKE_CXX_STANDARD 20) - set(PROJECT_NAME "Server") project(${PROJECT_NAME}) diff --git a/server/internal/CMakeLists.txt b/server/internal/CMakeLists.txt index c3d79ef..f23cb6b 100644 --- a/server/internal/CMakeLists.txt +++ b/server/internal/CMakeLists.txt @@ -1,6 +1,3 @@ -set(CMAKE_CXX_STANDARD 20) -cmake_minimum_required(VERSION 3.19) - add_subdirectory(src) add_subdirectory(entities) add_subdirectory(dbManager) diff --git a/server/internal/dbManager/CMakeLists.txt b/server/internal/dbManager/CMakeLists.txt index 432484e..3299f96 100644 --- a/server/internal/dbManager/CMakeLists.txt +++ b/server/internal/dbManager/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.19) - project("DbManagerLib") set(LIB_NAME libDbManager) diff --git a/server/internal/entities/CMakeLists.txt b/server/internal/entities/CMakeLists.txt index 08858c7..7b6ad66 100644 --- a/server/internal/entities/CMakeLists.txt +++ b/server/internal/entities/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.19) - project("EntitiesLib") set(LIB_NAME libEntities) diff --git a/server/internal/repository/CMakeLists.txt b/server/internal/repository/CMakeLists.txt index 872a4fa..67bead1 100644 --- a/server/internal/repository/CMakeLists.txt +++ b/server/internal/repository/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.19) - project("RepositoryLib") set(LIB_NAME libRepository) diff --git a/server/internal/repository/include/TaskRepository.hpp b/server/internal/repository/include/TaskRepository.hpp index 6780c36..11d2f3e 100644 --- a/server/internal/repository/include/TaskRepository.hpp +++ b/server/internal/repository/include/TaskRepository.hpp @@ -15,7 +15,7 @@ public: void updateTask(Task task) override; - void storeTask(Task task) override; + int storeTask(Task task) override; void deleteTask(Task task) override; diff --git a/server/internal/repository/src/TaskRepository.cpp b/server/internal/repository/src/TaskRepository.cpp index 58725b5..ea43451 100644 --- a/server/internal/repository/src/TaskRepository.cpp +++ b/server/internal/repository/src/TaskRepository.cpp @@ -32,7 +32,7 @@ void TaskRepository::updateTask(Task task) { } } -void TaskRepository::storeTask(Task task) { +int TaskRepository::storeTask(Task task) { try { auto c = manager->connection(); std::string sql = (boost::format("INSERT INTO tasks (description) " \ @@ -45,6 +45,7 @@ void TaskRepository::storeTask(Task task) { std::cerr << e.what() << std::endl; throw e; } + return 0; } void TaskRepository::deleteTask(Task task) { diff --git a/server/internal/repository/virtual/ITaskRepository.hpp b/server/internal/repository/virtual/ITaskRepository.hpp index 1ba3292..e367c21 100644 --- a/server/internal/repository/virtual/ITaskRepository.hpp +++ b/server/internal/repository/virtual/ITaskRepository.hpp @@ -11,7 +11,7 @@ class ITaskRepository { virtual void updateTask(Task task) = 0; - virtual void storeTask(Task task) = 0; + virtual int storeTask(Task task) = 0; virtual void deleteTask(Task task) = 0; diff --git a/server/internal/service/CMakeLists.txt b/server/internal/service/CMakeLists.txt index f405d37..1fd20be 100644 --- a/server/internal/service/CMakeLists.txt +++ b/server/internal/service/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.19) - project("ServiceLib") file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) diff --git a/server/internal/service/src/TaskService.cpp b/server/internal/service/src/TaskService.cpp index 92452f3..62d43db 100644 --- a/server/internal/service/src/TaskService.cpp +++ b/server/internal/service/src/TaskService.cpp @@ -3,7 +3,9 @@ TaskService::TaskService(std::unique_ptr taskRepo) : taskRepo(std::move(taskRepo)) {} -Task TaskService::createTask(std::string desc) { return Task(); } +Task TaskService::createTask(std::string desc) { + return Task(desc); +} std::vector TaskService::getAllTasks() { return std::vector(); } diff --git a/server/internal/service/tests/CMakeLists.txt b/server/internal/service/tests/CMakeLists.txt index 1b81101..914089a 100644 --- a/server/internal/service/tests/CMakeLists.txt +++ b/server/internal/service/tests/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.16) project(test_service) set(CMAKE_CXX_STANDARD 20) diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp index 2210fd3..f7e26c3 100644 --- a/server/internal/service/tests/Service_test.cpp +++ b/server/internal/service/tests/Service_test.cpp @@ -5,12 +5,22 @@ #include "TaskService.h" +bool operator==(Task p1, Task p2) { return p1.getId() == p2.getId(); } + +class Exception : public std::exception { + std::string _msg; + + public: + Exception(const std::string& msg) : _msg(msg) {} + virtual const char* what() const noexcept override { return _msg.c_str(); } +}; + class TaskRepositoryMock : public ITaskRepository { public: ~TaskRepositoryMock() override = default; MOCK_METHOD(Task, getTaskById, (size_t id), (override)); MOCK_METHOD(void, updateTask, (Task task), (override)); - MOCK_METHOD(void, storeTask, (Task task), (override)); + MOCK_METHOD(int, storeTask, (Task task), (override)); MOCK_METHOD(void, deleteTask, (Task task), (override)); MOCK_METHOD(void, deleteTaskById, (size_t id), (override)); }; @@ -24,19 +34,46 @@ struct TaskServiceTest : public testing::Test { mock_ptr = mock.get(); ts = new TaskService(std::move(mock)); } - void TearDown() { - delete ts; - } + void TearDown() { delete ts; } }; -TEST_F(TaskServiceTest, GetTask) { - EXPECT_CALL(*mock_ptr, deleteTaskById(1)); +ACTION(MyThrowException) { throw Exception("no user with this id in db"); } + +TEST_F(TaskServiceTest, deleteTaskById) { + EXPECT_CALL(*mock_ptr, deleteTaskById(1)).Times(1); ts->deleteTask(1); } -TEST_F(TaskServiceTest, Test) { - int a = 2; - EXPECT_EQ(a, 2); +TEST_F(TaskServiceTest, deleteTasWithInvalidId) { + EXPECT_CALL(*mock_ptr, deleteTaskById(1)) + .Times(1) + .WillRepeatedly(MyThrowException()); + EXPECT_THROW(ts->deleteTask(1), Exception); +} + +TEST_F(TaskServiceTest, GetTaskById) { + EXPECT_CALL(*mock_ptr, getTaskById(1)) + .Times(1) + .WillOnce(::testing::Return(Task(1, "desription"))); + Task t = ts->getTask(1); + EXPECT_EQ(t.getId(), 1); + EXPECT_EQ(t.getDescription(), "desription"); +} + +TEST_F(TaskServiceTest, CreateTask) { + EXPECT_CALL(*mock_ptr, storeTask(Task("desc"))) + .Times(1) + .WillOnce(::testing::Return(1)); + Task t = ts->createTask("desc"); + EXPECT_EQ(t.getId(), 1); + EXPECT_EQ(t.getDescription(), "desc"); + + EXPECT_CALL(*mock_ptr, storeTask(Task("desc2"))) + .Times(1) + .WillOnce(::testing::Return(2)); + t = ts->createTask("desc2"); + EXPECT_EQ(t.getId(), 2); + EXPECT_EQ(t.getDescription(), "desc2"); } int main(int argc, char** argv) { diff --git a/server/internal/src/CMakeLists.txt b/server/internal/src/CMakeLists.txt index 72e4c50..58510fa 100644 --- a/server/internal/src/CMakeLists.txt +++ b/server/internal/src/CMakeLists.txt @@ -1,5 +1,3 @@ -set(CMAKE_CXX_STANDARD 20) -cmake_minimum_required(VERSION 3.19) add_subdirectory(db) set(DB_Lib_LIB ${DB_Lib_LIB} PARENT_SCOPE) set(DB_Lib_INCLUDE_DIRS ${DB_Lib_INCLUDE_DIRS} PARENT_SCOPE) \ No newline at end of file diff --git a/server/internal/src/db/CMakeLists.txt b/server/internal/src/db/CMakeLists.txt index df02471..9d4549e 100644 --- a/server/internal/src/db/CMakeLists.txt +++ b/server/internal/src/db/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.10) - project("DBLib") set(LIB_NAME DB_Lib) -- GitLab From e242d9883ea39d1d3e301a5db5dc2efc94d0c0bb Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 3 May 2023 10:50:01 +0300 Subject: [PATCH 16/19] add test for user service --- .../repository/virtual/IUserRepository.hpp | 1 + server/internal/service/include/Exeptions.h | 9 ++ server/internal/service/include/UserService.h | 1 + server/internal/service/src/TaskService.cpp | 3 +- server/internal/service/src/UserService.cpp | 12 ++- .../internal/service/tests/Service_test.cpp | 87 ++++++++++++++++++- .../internal/service/virtual/IUserService.h | 1 + 7 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 server/internal/service/include/Exeptions.h diff --git a/server/internal/repository/virtual/IUserRepository.hpp b/server/internal/repository/virtual/IUserRepository.hpp index 8b3f7ab..14d7a50 100644 --- a/server/internal/repository/virtual/IUserRepository.hpp +++ b/server/internal/repository/virtual/IUserRepository.hpp @@ -5,6 +5,7 @@ #include "../../entities/include/User.hpp" class IUserRepository { public: + virtual ~IUserRepository() = default; virtual User getUserById(size_t id) = 0; virtual User getUserByLogin(std::string login) = 0; diff --git a/server/internal/service/include/Exeptions.h b/server/internal/service/include/Exeptions.h new file mode 100644 index 0000000..43925ff --- /dev/null +++ b/server/internal/service/include/Exeptions.h @@ -0,0 +1,9 @@ +#pragma once + +class ValidateExeption : public std::exception { + std::string _msg; + + public: + ValidateExeption(const std::string& msg) : _msg(msg) {} + virtual const char* what() const noexcept override { return _msg.c_str(); } +}; \ No newline at end of file diff --git a/server/internal/service/include/UserService.h b/server/internal/service/include/UserService.h index aa0de45..719aa02 100644 --- a/server/internal/service/include/UserService.h +++ b/server/internal/service/include/UserService.h @@ -10,6 +10,7 @@ class UserService : IUserService { std::unique_ptr userRepo; public: + ~UserService() override = default; explicit UserService(std::unique_ptr userRepo); User createUser(std::string login, std::string username, std::string password) override; diff --git a/server/internal/service/src/TaskService.cpp b/server/internal/service/src/TaskService.cpp index 62d43db..a3ce5ef 100644 --- a/server/internal/service/src/TaskService.cpp +++ b/server/internal/service/src/TaskService.cpp @@ -4,7 +4,8 @@ TaskService::TaskService(std::unique_ptr taskRepo) : taskRepo(std::move(taskRepo)) {} Task TaskService::createTask(std::string desc) { - return Task(desc); + size_t id = taskRepo->storeTask(Task(desc)); + return Task(id, desc); } std::vector TaskService::getAllTasks() { return std::vector(); } diff --git a/server/internal/service/src/UserService.cpp b/server/internal/service/src/UserService.cpp index 8cbd084..270f801 100644 --- a/server/internal/service/src/UserService.cpp +++ b/server/internal/service/src/UserService.cpp @@ -1,13 +1,19 @@ #include "UserService.h" +#include "Exeptions.h" + UserService::UserService(std::unique_ptr userRepo) : userRepo(std::move(userRepo)) {} User UserService::createUser(std::string login, std::string username, std::string password) { - return User(); + if (login == "") { + throw ValidateExeption("invalid login"); + } + size_t id = userRepo->makeUser(User(login, password, username)); + return User(id, login, password, username); } -User UserService::getUserById(size_t id) { return User(); } +User UserService::getUserById(size_t id) { return userRepo->getUserById(id); } -void UserService::deleteUser(size_t id) {} +void UserService::deleteUser(size_t id) { userRepo->deleteByUserId(id); } diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp index f7e26c3..199dfa8 100644 --- a/server/internal/service/tests/Service_test.cpp +++ b/server/internal/service/tests/Service_test.cpp @@ -3,9 +3,11 @@ #include +#include "Exeptions.h" #include "TaskService.h" +#include "UserService.h" -bool operator==(Task p1, Task p2) { return p1.getId() == p2.getId(); } +bool operator==(Task t1, Task t2) { return t1.getId() == t2.getId(); } class Exception : public std::exception { std::string _msg; @@ -37,7 +39,7 @@ struct TaskServiceTest : public testing::Test { void TearDown() { delete ts; } }; -ACTION(MyThrowException) { throw Exception("no user with this id in db"); } +ACTION(NoTaskException) { throw Exception("no task with this id in db"); } TEST_F(TaskServiceTest, deleteTaskById) { EXPECT_CALL(*mock_ptr, deleteTaskById(1)).Times(1); @@ -47,11 +49,11 @@ TEST_F(TaskServiceTest, deleteTaskById) { TEST_F(TaskServiceTest, deleteTasWithInvalidId) { EXPECT_CALL(*mock_ptr, deleteTaskById(1)) .Times(1) - .WillRepeatedly(MyThrowException()); + .WillRepeatedly(NoTaskException()); EXPECT_THROW(ts->deleteTask(1), Exception); } -TEST_F(TaskServiceTest, GetTaskById) { +TEST_F(TaskServiceTest, GetTaskByIdOK) { EXPECT_CALL(*mock_ptr, getTaskById(1)) .Times(1) .WillOnce(::testing::Return(Task(1, "desription"))); @@ -60,6 +62,11 @@ TEST_F(TaskServiceTest, GetTaskById) { EXPECT_EQ(t.getDescription(), "desription"); } +TEST_F(TaskServiceTest, GetTaskByIdEXEPTION) { + EXPECT_CALL(*mock_ptr, getTaskById(-1)).Times(1).WillRepeatedly(NoTaskException()); + EXPECT_THROW(ts->getTask(-1), Exception); +} + TEST_F(TaskServiceTest, CreateTask) { EXPECT_CALL(*mock_ptr, storeTask(Task("desc"))) .Times(1) @@ -76,6 +83,78 @@ TEST_F(TaskServiceTest, CreateTask) { EXPECT_EQ(t.getDescription(), "desc2"); } +bool operator==(User u1, User u2) { return u1.getId() == u2.getId(); } + +class UserRepositoryMock : public IUserRepository { + public: + ~UserRepositoryMock() override = default; + MOCK_METHOD(User, getUserById, (size_t id), (override)); + MOCK_METHOD(User, getUserByLogin, (std::string login), (override)); + MOCK_METHOD(size_t, makeUser, (User user), (override)); + MOCK_METHOD(void, deleteUser, (User user), (override)); + MOCK_METHOD(void, deleteByUserId, (size_t id), (override)); + MOCK_METHOD(std::vector, getAllUsers, (), (override)); +}; + +struct UserServiceTest : public testing::Test { + UserService* us; + UserRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + us = new UserService(std::move(mock)); + } + void TearDown() { delete us; } +}; + +ACTION(NoUserException) { throw Exception("no user with this id in db"); } + +TEST_F(UserServiceTest, deleteUser) { + EXPECT_CALL(*mock_ptr, deleteByUserId(1)).Times(1); + us->deleteUser(1); +} + +TEST_F(UserServiceTest, deleteUserWithInvalidId) { + EXPECT_CALL(*mock_ptr, deleteByUserId(1)) + .Times(1) + .WillRepeatedly(NoUserException()); + EXPECT_THROW(us->deleteUser(1), Exception); +} + +TEST_F(UserServiceTest, getUserOk) { + EXPECT_CALL(*mock_ptr, getUserById(1)) + .Times(1) + .WillOnce(::testing::Return(User(1, "login", "password", "username"))); + User u = us->getUserById(1); + EXPECT_EQ(u.getLogin(), "login"); + EXPECT_EQ(u.getId(), 1); + EXPECT_EQ(u.getPassword(), "password"); + EXPECT_EQ(u.getUsername(), "username"); +} + +TEST_F(UserServiceTest, getUserEXEPTION) { + EXPECT_CALL(*mock_ptr, getUserById(-1)).Times(1).WillOnce(NoUserException()); + EXPECT_THROW(us->getUserById(-1), Exception); +} + +TEST_F(UserServiceTest, makeUserOk) { + EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) + .Times(1) + .WillOnce(::testing::Return(1)); + User u = us->createUser("login", "username", "password"); + EXPECT_EQ(u.getLogin(), "login"); + EXPECT_EQ(u.getId(), 1); + EXPECT_EQ(u.getPassword(), "password"); + EXPECT_EQ(u.getUsername(), "username"); +} + +TEST_F(UserServiceTest, makeUserInvalidData) { + EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) + .Times(0); + EXPECT_THROW(us->createUser("", "", ""), ValidateExeption); +} + int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); diff --git a/server/internal/service/virtual/IUserService.h b/server/internal/service/virtual/IUserService.h index ad74eff..06d7972 100644 --- a/server/internal/service/virtual/IUserService.h +++ b/server/internal/service/virtual/IUserService.h @@ -6,6 +6,7 @@ class IUserService { public: + virtual ~IUserService() = default; virtual User createUser(std::string login, std::string username, std::string password) = 0; virtual User getUserById(size_t id) = 0; -- GitLab From 8623a1e7f7375ed65eec87d3026314d86144dddd Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 3 May 2023 13:19:27 +0300 Subject: [PATCH 17/19] add user validator tests --- .../include/{Exeptions.h => Exceptions.h} | 4 +-- .../internal/service/include/UserValidator.h | 2 +- server/internal/service/src/UserService.cpp | 4 +-- server/internal/service/src/UserValidator.cpp | 33 ++++++++++++++++--- .../internal/service/tests/Service_test.cpp | 33 +++++++++++++++++-- 5 files changed, 64 insertions(+), 12 deletions(-) rename server/internal/service/include/{Exeptions.h => Exceptions.h} (50%) diff --git a/server/internal/service/include/Exeptions.h b/server/internal/service/include/Exceptions.h similarity index 50% rename from server/internal/service/include/Exeptions.h rename to server/internal/service/include/Exceptions.h index 43925ff..a032c21 100644 --- a/server/internal/service/include/Exeptions.h +++ b/server/internal/service/include/Exceptions.h @@ -1,9 +1,9 @@ #pragma once -class ValidateExeption : public std::exception { +class ValidateException : public std::exception { std::string _msg; public: - ValidateExeption(const std::string& msg) : _msg(msg) {} + ValidateException(const std::string& msg) : _msg(msg) {} virtual const char* what() const noexcept override { return _msg.c_str(); } }; \ No newline at end of file diff --git a/server/internal/service/include/UserValidator.h b/server/internal/service/include/UserValidator.h index 77f1a50..002f450 100644 --- a/server/internal/service/include/UserValidator.h +++ b/server/internal/service/include/UserValidator.h @@ -12,5 +12,5 @@ class UserValidator { public: explicit UserValidator(User user); bool validateUser(); - ~UserValidator(); + ~UserValidator() = default; }; diff --git a/server/internal/service/src/UserService.cpp b/server/internal/service/src/UserService.cpp index 270f801..b44ecf3 100644 --- a/server/internal/service/src/UserService.cpp +++ b/server/internal/service/src/UserService.cpp @@ -1,6 +1,6 @@ #include "UserService.h" -#include "Exeptions.h" +#include "Exceptions.h" UserService::UserService(std::unique_ptr userRepo) : userRepo(std::move(userRepo)) {} @@ -8,7 +8,7 @@ UserService::UserService(std::unique_ptr userRepo) User UserService::createUser(std::string login, std::string username, std::string password) { if (login == "") { - throw ValidateExeption("invalid login"); + throw ValidateException("invalid login"); } size_t id = userRepo->makeUser(User(login, password, username)); return User(id, login, password, username); diff --git a/server/internal/service/src/UserValidator.cpp b/server/internal/service/src/UserValidator.cpp index da64212..6666641 100644 --- a/server/internal/service/src/UserValidator.cpp +++ b/server/internal/service/src/UserValidator.cpp @@ -1,11 +1,36 @@ #include "UserValidator.h" +#include + UserValidator::UserValidator(User user) : user(user) {} -bool UserValidator::validateUser() { return true; } +bool UserValidator::validateUser() { + if (validateLogin() && validatePassword() && validateUsername()) { + return true; + } + return false; +} -bool UserValidator::validateLogin() { return true; } +bool UserValidator::validateLogin() { + std::string login = user.getLogin(); + if (login.length() < 3 || login.length() > 30) { + return false; + } + return true; +} -bool UserValidator::validatePassword() { return true; } +bool UserValidator::validatePassword() { + std::string password = user.getPassword(); + if (password.length() < 8 || password.length() > 30) { + return false; + } + return true; +} -bool UserValidator::validateUsername() { return true; } +bool UserValidator::validateUsername() { + std::string username = user.getUsername(); + if (username.length() < 3 || username.length() > 20) { + return false; + } + return true; +} diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp index 199dfa8..2ab0b88 100644 --- a/server/internal/service/tests/Service_test.cpp +++ b/server/internal/service/tests/Service_test.cpp @@ -3,7 +3,7 @@ #include -#include "Exeptions.h" +#include "Exceptions.h" #include "TaskService.h" #include "UserService.h" @@ -63,7 +63,9 @@ TEST_F(TaskServiceTest, GetTaskByIdOK) { } TEST_F(TaskServiceTest, GetTaskByIdEXEPTION) { - EXPECT_CALL(*mock_ptr, getTaskById(-1)).Times(1).WillRepeatedly(NoTaskException()); + EXPECT_CALL(*mock_ptr, getTaskById(-1)) + .Times(1) + .WillRepeatedly(NoTaskException()); EXPECT_THROW(ts->getTask(-1), Exception); } @@ -152,7 +154,32 @@ TEST_F(UserServiceTest, makeUserOk) { TEST_F(UserServiceTest, makeUserInvalidData) { EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) .Times(0); - EXPECT_THROW(us->createUser("", "", ""), ValidateExeption); + EXPECT_THROW(us->createUser("", "", ""), ValidateException); +} + +TEST(UserValidatorTest, validateOK) { + UserValidator uv(User("login", "password", "username")); + EXPECT_TRUE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidLogin) { + UserValidator uv(User("", "password", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidPassword) { + UserValidator uv(User("login", "", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUsername) { + UserValidator uv(User("login", "password", "")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUserFields) { + UserValidator uv(User("", "", "")); + EXPECT_FALSE(uv.validateUser()); } int main(int argc, char** argv) { -- GitLab From c38fa50b78672548ccc727c4e086496ee76ea3e1 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 3 May 2023 17:35:00 +0300 Subject: [PATCH 18/19] add solution tests --- CMakeLists.txt | 2 +- .../repository/include/SolutionRepository.hpp | 4 +- .../repository/src/SolutionRepository.cpp | 6 +- .../virtual/ISolutionRepository.hpp | 5 +- .../internal/service/src/SolutionService.cpp | 27 +++- .../internal/service/tests/Service_test.cpp | 116 +++++++++++++++--- .../service/virtual/ISolutionService.h | 1 + 7 files changed, 138 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41c84fa..e51f2bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ 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} --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") diff --git a/server/internal/repository/include/SolutionRepository.hpp b/server/internal/repository/include/SolutionRepository.hpp index 04034d5..8b4d326 100644 --- a/server/internal/repository/include/SolutionRepository.hpp +++ b/server/internal/repository/include/SolutionRepository.hpp @@ -11,13 +11,15 @@ using namespace pqxx; class SolutionRepository : ISolutionRepository { + // ~SolutionRepository()override = default; Solution getSolutionById(size_t id) override; std::vector getSolutionsBySenderId(size_t sender_id) override; std::vector getSolutionsByTaskId(size_t task_id) override; + std::vector getSolutions(size_t sender_id, size_t task_id) override; - void storeSolution(Solution solution) override; + size_t storeSolution(Solution solution) override; void updateSolution(Solution solution) override; diff --git a/server/internal/repository/src/SolutionRepository.cpp b/server/internal/repository/src/SolutionRepository.cpp index 4e21f05..a33884b 100644 --- a/server/internal/repository/src/SolutionRepository.cpp +++ b/server/internal/repository/src/SolutionRepository.cpp @@ -5,6 +5,10 @@ #include "SolutionRepository.hpp" using namespace pqxx; +std::vector SolutionRepository::getSolutions(size_t sender_id, size_t task_id){ + return std::vector(); +} + Solution SolutionRepository::getSolutionById(size_t id) { try { auto c = manager->connection(); @@ -53,7 +57,7 @@ std::vector SolutionRepository::getSolutionsByTaskId(size_t task_id) } } -void SolutionRepository::storeSolution(Solution solution) { +size_t SolutionRepository::storeSolution(Solution solution) { try { auto c = manager->connection(); diff --git a/server/internal/repository/virtual/ISolutionRepository.hpp b/server/internal/repository/virtual/ISolutionRepository.hpp index c64a1b6..8a7b035 100644 --- a/server/internal/repository/virtual/ISolutionRepository.hpp +++ b/server/internal/repository/virtual/ISolutionRepository.hpp @@ -6,13 +6,16 @@ #include "../../entities/include/Solution.hpp" class ISolutionRepository { + public: + virtual ~ISolutionRepository() = default; virtual Solution getSolutionById(size_t id) = 0; virtual std::vector getSolutionsBySenderId(size_t sender_id) = 0; + virtual std::vector getSolutions(size_t sender_id, size_t task_id) = 0; virtual std::vector getSolutionsByTaskId(size_t task_id) = 0; - virtual void storeSolution(Solution solution) = 0; + virtual size_t storeSolution(Solution solution) = 0; virtual void updateSolution(Solution solution) = 0; diff --git a/server/internal/service/src/SolutionService.cpp b/server/internal/service/src/SolutionService.cpp index ba707c3..216b76c 100644 --- a/server/internal/service/src/SolutionService.cpp +++ b/server/internal/service/src/SolutionService.cpp @@ -6,16 +6,35 @@ SolutionService::SolutionService( Solution SolutionService::createSolution(size_t userId, size_t taskId, std::string source) { - return Solution(); + size_t id = solutionRepo->storeSolution( + Solution(0, "", userId, "", "", "", taskId, "")); + return Solution(id, "", userId, source, "", "", taskId, ""); } std::vector SolutionService::getSolutionsByUserAndTaskId( size_t userId, size_t taskId) { - return std::vector(); + try { + return solutionRepo->getSolutions(userId, taskId); + } catch (std::exception& e) { + throw e; + } } -void SolutionService::deleteSolutionById(size_t solId) {} +void SolutionService::deleteSolutionById(size_t solId) { + try { + solutionRepo->deleteSolutionById(solId); + } catch (std::exception& e) { + throw e; + } +} std::pair SolutionService::getMetrics(size_t solId) { - return std::make_pair("", ""); + try { + Solution sol = solutionRepo->getSolutionById(solId); + std::string tokens = sol.getTokens(); + std::string astTree = sol.getAstTree(); + return std::make_pair(tokens, astTree); + } catch (std::exception& e) { + throw e; + } } diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp index 2ab0b88..ebc89de 100644 --- a/server/internal/service/tests/Service_test.cpp +++ b/server/internal/service/tests/Service_test.cpp @@ -1,9 +1,11 @@ #include #include +#include #include #include "Exceptions.h" +#include "SolutionService.h" #include "TaskService.h" #include "UserService.h" @@ -85,6 +87,31 @@ TEST_F(TaskServiceTest, CreateTask) { EXPECT_EQ(t.getDescription(), "desc2"); } +TEST(UserValidatorTest, validateOK) { + UserValidator uv(User("login", "password", "username")); + EXPECT_TRUE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidLogin) { + UserValidator uv(User("", "password", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidPassword) { + UserValidator uv(User("login", "", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUsername) { + UserValidator uv(User("login", "password", "")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUserFields) { + UserValidator uv(User("", "", "")); + EXPECT_FALSE(uv.validateUser()); +} + bool operator==(User u1, User u2) { return u1.getId() == u2.getId(); } class UserRepositoryMock : public IUserRepository { @@ -157,29 +184,88 @@ TEST_F(UserServiceTest, makeUserInvalidData) { EXPECT_THROW(us->createUser("", "", ""), ValidateException); } -TEST(UserValidatorTest, validateOK) { - UserValidator uv(User("login", "password", "username")); - EXPECT_TRUE(uv.validateUser()); +bool operator==(Solution s1, Solution s2) { return s1.getId() == s2.getId(); } + +class SolutionRepositoryMock : public ISolutionRepository { + public: + ~SolutionRepositoryMock() override = default; + MOCK_METHOD(Solution, getSolutionById, (size_t id), (override)); + MOCK_METHOD(std::vector, getSolutionsBySenderId, (size_t sender_id), + (override)); + MOCK_METHOD(std::vector, getSolutionsByTaskId, (size_t task_id), + (override)); + MOCK_METHOD(std::vector, getSolutions, + (size_t sender_id, size_t task_id), (override)); + MOCK_METHOD(size_t, storeSolution, (Solution solution), (override)); + MOCK_METHOD(void, updateSolution, (Solution solution), (override)); + MOCK_METHOD(void, deleteSolutionById, (size_t id), (override)); + MOCK_METHOD(void, deleteSolution, (Solution solution), (override)); +}; + +struct SolutionServiceTest : public testing::Test { + SolutionService* ss; + SolutionRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + ss = new SolutionService(std::move(mock)); + } + void TearDown() { delete ss; } +}; + +ACTION(NoSolutionException) { + throw Exception("no solution with this id in db"); } -TEST(UserValidatorTest, invalidLogin) { - UserValidator uv(User("", "password", "username")); - EXPECT_FALSE(uv.validateUser()); +TEST_F(SolutionServiceTest, getSolutionsByUserAndTaskId) { + std::vector solutions; + solutions.push_back(Solution(0, "", 1, "", "", "", 1, "")); + solutions.push_back(Solution(1, "", 1, "", "", "", 1, "")); + EXPECT_CALL(*mock_ptr, getSolutions(1, 1)) + .Times(1) + .WillOnce(::testing::Return(solutions)); + std::vector sols = ss->getSolutionsByUserAndTaskId(1, 1); + EXPECT_EQ(sols.size(), 2); } -TEST(UserValidatorTest, invalidPassword) { - UserValidator uv(User("login", "", "username")); - EXPECT_FALSE(uv.validateUser()); +TEST_F(SolutionServiceTest, deleteSolution) { + EXPECT_CALL(*mock_ptr, deleteSolutionById(1)).Times(1); + ss->deleteSolutionById(1); } -TEST(UserValidatorTest, invalidUsername) { - UserValidator uv(User("login", "password", "")); - EXPECT_FALSE(uv.validateUser()); +TEST_F(SolutionServiceTest, deleteSolutionException) { + EXPECT_CALL(*mock_ptr, deleteSolutionById(-1)) + .Times(1) + .WillRepeatedly(NoSolutionException()); + EXPECT_THROW(ss->deleteSolutionById(-1), std::exception); } -TEST(UserValidatorTest, invalidUserFields) { - UserValidator uv(User("", "", "")); - EXPECT_FALSE(uv.validateUser()); +TEST_F(SolutionServiceTest, getMetrics) { + EXPECT_CALL(*mock_ptr, getSolutionById(1)) + .Times(1) + .WillOnce(::testing::Return( + Solution(1, "", 1, "", "tokens", "astTree", 1, ""))); + std::pair metrics = ss->getMetrics(1); + EXPECT_EQ(metrics.first, "tokens"); + EXPECT_EQ(metrics.second, "astTree"); +} + +TEST_F(SolutionServiceTest, getMetricsException) { + EXPECT_CALL(*mock_ptr, getSolutionById(-1)) + .Times(1) + .WillRepeatedly(NoSolutionException()); + EXPECT_THROW(ss->getMetrics(-1), std::exception); +} + +TEST_F(SolutionServiceTest, createSolution) { + EXPECT_CALL(*mock_ptr, + storeSolution(Solution(0, "", 2, "source", "", "", 1, ""))) + .Times(1) + .WillRepeatedly(::testing::Return(1)); + Solution sol = ss->createSolution(2, 1, "source"); + EXPECT_EQ(sol.getId(), 1); + EXPECT_EQ(sol.getSource(), "source"); } int main(int argc, char** argv) { diff --git a/server/internal/service/virtual/ISolutionService.h b/server/internal/service/virtual/ISolutionService.h index e7fb0e1..a9ec548 100644 --- a/server/internal/service/virtual/ISolutionService.h +++ b/server/internal/service/virtual/ISolutionService.h @@ -7,6 +7,7 @@ class ISolutionService { public: + virtual ~ISolutionService() = default; virtual Solution createSolution(size_t userId, size_t taskId, std::string source) = 0; virtual std::vector getSolutionsByUserAndTaskId(size_t userId, -- GitLab From fe4c7d111ebb13f1ecd16fd4d1b50a0673b80817 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 3 May 2023 17:58:49 +0300 Subject: [PATCH 19/19] refactor test files --- server/internal/service/tests/CMakeLists.txt | 2 +- .../internal/service/tests/Service_test.cpp | 275 ------------------ .../service/tests/SolutionServiceTest.cpp | 96 ++++++ .../service/tests/TaskServiceTest.cpp | 82 ++++++ .../service/tests/UserServiceTest.cpp | 85 ++++++ .../service/tests/UserValidatorTest.cpp | 29 ++ server/internal/service/tests/main.cpp | 8 + 7 files changed, 301 insertions(+), 276 deletions(-) delete mode 100644 server/internal/service/tests/Service_test.cpp create mode 100644 server/internal/service/tests/SolutionServiceTest.cpp create mode 100644 server/internal/service/tests/TaskServiceTest.cpp create mode 100644 server/internal/service/tests/UserServiceTest.cpp create mode 100644 server/internal/service/tests/UserValidatorTest.cpp create mode 100644 server/internal/service/tests/main.cpp diff --git a/server/internal/service/tests/CMakeLists.txt b/server/internal/service/tests/CMakeLists.txt index 914089a..5dc8740 100644 --- a/server/internal/service/tests/CMakeLists.txt +++ b/server/internal/service/tests/CMakeLists.txt @@ -10,7 +10,7 @@ find_package(GTest REQUIRED) add_executable(${PROJECT_NAME} ${SOURCES}) -target_link_libraries(${PROJECT_NAME} ${SERVICE_lib_LIBRARY} GTest::GTest gmock pthread) +target_link_libraries(${PROJECT_NAME} ${SERVICE_lib_LIBRARY} GTest::GTest gmock) target_include_directories(${PROJECT_NAME} PUBLIC ${SERVICE_lib_INCLUDE_DIRS}) diff --git a/server/internal/service/tests/Service_test.cpp b/server/internal/service/tests/Service_test.cpp deleted file mode 100644 index ebc89de..0000000 --- a/server/internal/service/tests/Service_test.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include - -#include -#include - -#include "Exceptions.h" -#include "SolutionService.h" -#include "TaskService.h" -#include "UserService.h" - -bool operator==(Task t1, Task t2) { return t1.getId() == t2.getId(); } - -class Exception : public std::exception { - std::string _msg; - - public: - Exception(const std::string& msg) : _msg(msg) {} - virtual const char* what() const noexcept override { return _msg.c_str(); } -}; - -class TaskRepositoryMock : public ITaskRepository { - public: - ~TaskRepositoryMock() override = default; - MOCK_METHOD(Task, getTaskById, (size_t id), (override)); - MOCK_METHOD(void, updateTask, (Task task), (override)); - MOCK_METHOD(int, storeTask, (Task task), (override)); - MOCK_METHOD(void, deleteTask, (Task task), (override)); - MOCK_METHOD(void, deleteTaskById, (size_t id), (override)); -}; - -struct TaskServiceTest : public testing::Test { - TaskService* ts; - TaskRepositoryMock* mock_ptr; - - void SetUp() { - auto mock = std::make_unique(); - mock_ptr = mock.get(); - ts = new TaskService(std::move(mock)); - } - void TearDown() { delete ts; } -}; - -ACTION(NoTaskException) { throw Exception("no task with this id in db"); } - -TEST_F(TaskServiceTest, deleteTaskById) { - EXPECT_CALL(*mock_ptr, deleteTaskById(1)).Times(1); - ts->deleteTask(1); -} - -TEST_F(TaskServiceTest, deleteTasWithInvalidId) { - EXPECT_CALL(*mock_ptr, deleteTaskById(1)) - .Times(1) - .WillRepeatedly(NoTaskException()); - EXPECT_THROW(ts->deleteTask(1), Exception); -} - -TEST_F(TaskServiceTest, GetTaskByIdOK) { - EXPECT_CALL(*mock_ptr, getTaskById(1)) - .Times(1) - .WillOnce(::testing::Return(Task(1, "desription"))); - Task t = ts->getTask(1); - EXPECT_EQ(t.getId(), 1); - EXPECT_EQ(t.getDescription(), "desription"); -} - -TEST_F(TaskServiceTest, GetTaskByIdEXEPTION) { - EXPECT_CALL(*mock_ptr, getTaskById(-1)) - .Times(1) - .WillRepeatedly(NoTaskException()); - EXPECT_THROW(ts->getTask(-1), Exception); -} - -TEST_F(TaskServiceTest, CreateTask) { - EXPECT_CALL(*mock_ptr, storeTask(Task("desc"))) - .Times(1) - .WillOnce(::testing::Return(1)); - Task t = ts->createTask("desc"); - EXPECT_EQ(t.getId(), 1); - EXPECT_EQ(t.getDescription(), "desc"); - - EXPECT_CALL(*mock_ptr, storeTask(Task("desc2"))) - .Times(1) - .WillOnce(::testing::Return(2)); - t = ts->createTask("desc2"); - EXPECT_EQ(t.getId(), 2); - EXPECT_EQ(t.getDescription(), "desc2"); -} - -TEST(UserValidatorTest, validateOK) { - UserValidator uv(User("login", "password", "username")); - EXPECT_TRUE(uv.validateUser()); -} - -TEST(UserValidatorTest, invalidLogin) { - UserValidator uv(User("", "password", "username")); - EXPECT_FALSE(uv.validateUser()); -} - -TEST(UserValidatorTest, invalidPassword) { - UserValidator uv(User("login", "", "username")); - EXPECT_FALSE(uv.validateUser()); -} - -TEST(UserValidatorTest, invalidUsername) { - UserValidator uv(User("login", "password", "")); - EXPECT_FALSE(uv.validateUser()); -} - -TEST(UserValidatorTest, invalidUserFields) { - UserValidator uv(User("", "", "")); - EXPECT_FALSE(uv.validateUser()); -} - -bool operator==(User u1, User u2) { return u1.getId() == u2.getId(); } - -class UserRepositoryMock : public IUserRepository { - public: - ~UserRepositoryMock() override = default; - MOCK_METHOD(User, getUserById, (size_t id), (override)); - MOCK_METHOD(User, getUserByLogin, (std::string login), (override)); - MOCK_METHOD(size_t, makeUser, (User user), (override)); - MOCK_METHOD(void, deleteUser, (User user), (override)); - MOCK_METHOD(void, deleteByUserId, (size_t id), (override)); - MOCK_METHOD(std::vector, getAllUsers, (), (override)); -}; - -struct UserServiceTest : public testing::Test { - UserService* us; - UserRepositoryMock* mock_ptr; - - void SetUp() { - auto mock = std::make_unique(); - mock_ptr = mock.get(); - us = new UserService(std::move(mock)); - } - void TearDown() { delete us; } -}; - -ACTION(NoUserException) { throw Exception("no user with this id in db"); } - -TEST_F(UserServiceTest, deleteUser) { - EXPECT_CALL(*mock_ptr, deleteByUserId(1)).Times(1); - us->deleteUser(1); -} - -TEST_F(UserServiceTest, deleteUserWithInvalidId) { - EXPECT_CALL(*mock_ptr, deleteByUserId(1)) - .Times(1) - .WillRepeatedly(NoUserException()); - EXPECT_THROW(us->deleteUser(1), Exception); -} - -TEST_F(UserServiceTest, getUserOk) { - EXPECT_CALL(*mock_ptr, getUserById(1)) - .Times(1) - .WillOnce(::testing::Return(User(1, "login", "password", "username"))); - User u = us->getUserById(1); - EXPECT_EQ(u.getLogin(), "login"); - EXPECT_EQ(u.getId(), 1); - EXPECT_EQ(u.getPassword(), "password"); - EXPECT_EQ(u.getUsername(), "username"); -} - -TEST_F(UserServiceTest, getUserEXEPTION) { - EXPECT_CALL(*mock_ptr, getUserById(-1)).Times(1).WillOnce(NoUserException()); - EXPECT_THROW(us->getUserById(-1), Exception); -} - -TEST_F(UserServiceTest, makeUserOk) { - EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) - .Times(1) - .WillOnce(::testing::Return(1)); - User u = us->createUser("login", "username", "password"); - EXPECT_EQ(u.getLogin(), "login"); - EXPECT_EQ(u.getId(), 1); - EXPECT_EQ(u.getPassword(), "password"); - EXPECT_EQ(u.getUsername(), "username"); -} - -TEST_F(UserServiceTest, makeUserInvalidData) { - EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) - .Times(0); - EXPECT_THROW(us->createUser("", "", ""), ValidateException); -} - -bool operator==(Solution s1, Solution s2) { return s1.getId() == s2.getId(); } - -class SolutionRepositoryMock : public ISolutionRepository { - public: - ~SolutionRepositoryMock() override = default; - MOCK_METHOD(Solution, getSolutionById, (size_t id), (override)); - MOCK_METHOD(std::vector, getSolutionsBySenderId, (size_t sender_id), - (override)); - MOCK_METHOD(std::vector, getSolutionsByTaskId, (size_t task_id), - (override)); - MOCK_METHOD(std::vector, getSolutions, - (size_t sender_id, size_t task_id), (override)); - MOCK_METHOD(size_t, storeSolution, (Solution solution), (override)); - MOCK_METHOD(void, updateSolution, (Solution solution), (override)); - MOCK_METHOD(void, deleteSolutionById, (size_t id), (override)); - MOCK_METHOD(void, deleteSolution, (Solution solution), (override)); -}; - -struct SolutionServiceTest : public testing::Test { - SolutionService* ss; - SolutionRepositoryMock* mock_ptr; - - void SetUp() { - auto mock = std::make_unique(); - mock_ptr = mock.get(); - ss = new SolutionService(std::move(mock)); - } - void TearDown() { delete ss; } -}; - -ACTION(NoSolutionException) { - throw Exception("no solution with this id in db"); -} - -TEST_F(SolutionServiceTest, getSolutionsByUserAndTaskId) { - std::vector solutions; - solutions.push_back(Solution(0, "", 1, "", "", "", 1, "")); - solutions.push_back(Solution(1, "", 1, "", "", "", 1, "")); - EXPECT_CALL(*mock_ptr, getSolutions(1, 1)) - .Times(1) - .WillOnce(::testing::Return(solutions)); - std::vector sols = ss->getSolutionsByUserAndTaskId(1, 1); - EXPECT_EQ(sols.size(), 2); -} - -TEST_F(SolutionServiceTest, deleteSolution) { - EXPECT_CALL(*mock_ptr, deleteSolutionById(1)).Times(1); - ss->deleteSolutionById(1); -} - -TEST_F(SolutionServiceTest, deleteSolutionException) { - EXPECT_CALL(*mock_ptr, deleteSolutionById(-1)) - .Times(1) - .WillRepeatedly(NoSolutionException()); - EXPECT_THROW(ss->deleteSolutionById(-1), std::exception); -} - -TEST_F(SolutionServiceTest, getMetrics) { - EXPECT_CALL(*mock_ptr, getSolutionById(1)) - .Times(1) - .WillOnce(::testing::Return( - Solution(1, "", 1, "", "tokens", "astTree", 1, ""))); - std::pair metrics = ss->getMetrics(1); - EXPECT_EQ(metrics.first, "tokens"); - EXPECT_EQ(metrics.second, "astTree"); -} - -TEST_F(SolutionServiceTest, getMetricsException) { - EXPECT_CALL(*mock_ptr, getSolutionById(-1)) - .Times(1) - .WillRepeatedly(NoSolutionException()); - EXPECT_THROW(ss->getMetrics(-1), std::exception); -} - -TEST_F(SolutionServiceTest, createSolution) { - EXPECT_CALL(*mock_ptr, - storeSolution(Solution(0, "", 2, "source", "", "", 1, ""))) - .Times(1) - .WillRepeatedly(::testing::Return(1)); - Solution sol = ss->createSolution(2, 1, "source"); - EXPECT_EQ(sol.getId(), 1); - EXPECT_EQ(sol.getSource(), "source"); -} - -int main(int argc, char** argv) { - ::testing::InitGoogleMock(&argc, argv); - - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/server/internal/service/tests/SolutionServiceTest.cpp b/server/internal/service/tests/SolutionServiceTest.cpp new file mode 100644 index 0000000..2dcb91f --- /dev/null +++ b/server/internal/service/tests/SolutionServiceTest.cpp @@ -0,0 +1,96 @@ +#include +#include + +#include "SolutionService.h" + +class Exception : public std::exception { + std::string _msg; + + public: + Exception(const std::string& msg) : _msg(msg) {} + virtual const char* what() const noexcept override { return _msg.c_str(); } +}; + +bool operator==(Solution s1, Solution s2) { return s1.getId() == s2.getId(); } + +class SolutionRepositoryMock : public ISolutionRepository { + public: + ~SolutionRepositoryMock() override = default; + MOCK_METHOD(Solution, getSolutionById, (size_t id), (override)); + MOCK_METHOD(std::vector, getSolutionsBySenderId, (size_t sender_id), + (override)); + MOCK_METHOD(std::vector, getSolutionsByTaskId, (size_t task_id), + (override)); + MOCK_METHOD(std::vector, getSolutions, + (size_t sender_id, size_t task_id), (override)); + MOCK_METHOD(size_t, storeSolution, (Solution solution), (override)); + MOCK_METHOD(void, updateSolution, (Solution solution), (override)); + MOCK_METHOD(void, deleteSolutionById, (size_t id), (override)); + MOCK_METHOD(void, deleteSolution, (Solution solution), (override)); +}; + +struct SolutionServiceTest : public testing::Test { + SolutionService* ss; + SolutionRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + ss = new SolutionService(std::move(mock)); + } + void TearDown() { delete ss; } +}; + +ACTION(NoSolutionException) { + throw Exception("no solution with this id in db"); +} + +TEST_F(SolutionServiceTest, getSolutionsByUserAndTaskId) { + std::vector solutions; + solutions.push_back(Solution(0, "", 1, "", "", "", 1, "")); + solutions.push_back(Solution(1, "", 1, "", "", "", 1, "")); + EXPECT_CALL(*mock_ptr, getSolutions(1, 1)) + .Times(1) + .WillOnce(::testing::Return(solutions)); + std::vector sols = ss->getSolutionsByUserAndTaskId(1, 1); + EXPECT_EQ(sols.size(), 2); +} + +TEST_F(SolutionServiceTest, deleteSolution) { + EXPECT_CALL(*mock_ptr, deleteSolutionById(1)).Times(1); + ss->deleteSolutionById(1); +} + +TEST_F(SolutionServiceTest, deleteSolutionException) { + EXPECT_CALL(*mock_ptr, deleteSolutionById(-1)) + .Times(1) + .WillRepeatedly(NoSolutionException()); + EXPECT_THROW(ss->deleteSolutionById(-1), std::exception); +} + +TEST_F(SolutionServiceTest, getMetrics) { + EXPECT_CALL(*mock_ptr, getSolutionById(1)) + .Times(1) + .WillOnce(::testing::Return( + Solution(1, "", 1, "", "tokens", "astTree", 1, ""))); + std::pair metrics = ss->getMetrics(1); + EXPECT_EQ(metrics.first, "tokens"); + EXPECT_EQ(metrics.second, "astTree"); +} + +TEST_F(SolutionServiceTest, getMetricsException) { + EXPECT_CALL(*mock_ptr, getSolutionById(-1)) + .Times(1) + .WillRepeatedly(NoSolutionException()); + EXPECT_THROW(ss->getMetrics(-1), std::exception); +} + +TEST_F(SolutionServiceTest, createSolution) { + EXPECT_CALL(*mock_ptr, + storeSolution(Solution(0, "", 2, "source", "", "", 1, ""))) + .Times(1) + .WillRepeatedly(::testing::Return(1)); + Solution sol = ss->createSolution(2, 1, "source"); + EXPECT_EQ(sol.getId(), 1); + EXPECT_EQ(sol.getSource(), "source"); +} \ No newline at end of file diff --git a/server/internal/service/tests/TaskServiceTest.cpp b/server/internal/service/tests/TaskServiceTest.cpp new file mode 100644 index 0000000..5a450d2 --- /dev/null +++ b/server/internal/service/tests/TaskServiceTest.cpp @@ -0,0 +1,82 @@ +#include +#include + +#include "TaskService.h" + +bool operator==(Task t1, Task t2) { return t1.getId() == t2.getId(); } + +class Exception : public std::exception { + std::string _msg; + + public: + Exception(const std::string& msg) : _msg(msg) {} + virtual const char* what() const noexcept override { return _msg.c_str(); } +}; + +class TaskRepositoryMock : public ITaskRepository { + public: + ~TaskRepositoryMock() override = default; + MOCK_METHOD(Task, getTaskById, (size_t id), (override)); + MOCK_METHOD(void, updateTask, (Task task), (override)); + MOCK_METHOD(int, storeTask, (Task task), (override)); + MOCK_METHOD(void, deleteTask, (Task task), (override)); + MOCK_METHOD(void, deleteTaskById, (size_t id), (override)); +}; + +struct TaskServiceTest : public testing::Test { + TaskService* ts; + TaskRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + ts = new TaskService(std::move(mock)); + } + void TearDown() { delete ts; } +}; + +ACTION(NoTaskException) { throw Exception("no task with this id in db"); } + +TEST_F(TaskServiceTest, deleteTaskById) { + EXPECT_CALL(*mock_ptr, deleteTaskById(1)).Times(1); + ts->deleteTask(1); +} + +TEST_F(TaskServiceTest, deleteTasWithInvalidId) { + EXPECT_CALL(*mock_ptr, deleteTaskById(1)) + .Times(1) + .WillRepeatedly(NoTaskException()); + EXPECT_THROW(ts->deleteTask(1), Exception); +} + +TEST_F(TaskServiceTest, GetTaskByIdOK) { + EXPECT_CALL(*mock_ptr, getTaskById(1)) + .Times(1) + .WillOnce(::testing::Return(Task(1, "desription"))); + Task t = ts->getTask(1); + EXPECT_EQ(t.getId(), 1); + EXPECT_EQ(t.getDescription(), "desription"); +} + +TEST_F(TaskServiceTest, GetTaskByIdEXEPTION) { + EXPECT_CALL(*mock_ptr, getTaskById(-1)) + .Times(1) + .WillRepeatedly(NoTaskException()); + EXPECT_THROW(ts->getTask(-1), Exception); +} + +TEST_F(TaskServiceTest, CreateTask) { + EXPECT_CALL(*mock_ptr, storeTask(Task("desc"))) + .Times(1) + .WillOnce(::testing::Return(1)); + Task t = ts->createTask("desc"); + EXPECT_EQ(t.getId(), 1); + EXPECT_EQ(t.getDescription(), "desc"); + + EXPECT_CALL(*mock_ptr, storeTask(Task("desc2"))) + .Times(1) + .WillOnce(::testing::Return(2)); + t = ts->createTask("desc2"); + EXPECT_EQ(t.getId(), 2); + EXPECT_EQ(t.getDescription(), "desc2"); +} diff --git a/server/internal/service/tests/UserServiceTest.cpp b/server/internal/service/tests/UserServiceTest.cpp new file mode 100644 index 0000000..a742351 --- /dev/null +++ b/server/internal/service/tests/UserServiceTest.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "Exceptions.h" +#include "UserService.h" + +bool operator==(User u1, User u2) { return u1.getId() == u2.getId(); } + +class Exception : public std::exception { + std::string _msg; + + public: + Exception(const std::string& msg) : _msg(msg) {} + virtual const char* what() const noexcept override { return _msg.c_str(); } +}; + +class UserRepositoryMock : public IUserRepository { + public: + ~UserRepositoryMock() override = default; + MOCK_METHOD(User, getUserById, (size_t id), (override)); + MOCK_METHOD(User, getUserByLogin, (std::string login), (override)); + MOCK_METHOD(size_t, makeUser, (User user), (override)); + MOCK_METHOD(void, deleteUser, (User user), (override)); + MOCK_METHOD(void, deleteByUserId, (size_t id), (override)); + MOCK_METHOD(std::vector, getAllUsers, (), (override)); +}; + +struct UserServiceTest : public testing::Test { + UserService* us; + UserRepositoryMock* mock_ptr; + + void SetUp() { + auto mock = std::make_unique(); + mock_ptr = mock.get(); + us = new UserService(std::move(mock)); + } + void TearDown() { delete us; } +}; + +ACTION(NoUserException) { throw Exception("no user with this id in db"); } + +TEST_F(UserServiceTest, deleteUser) { + EXPECT_CALL(*mock_ptr, deleteByUserId(1)).Times(1); + us->deleteUser(1); +} + +TEST_F(UserServiceTest, deleteUserWithInvalidId) { + EXPECT_CALL(*mock_ptr, deleteByUserId(1)) + .Times(1) + .WillRepeatedly(NoUserException()); + EXPECT_THROW(us->deleteUser(1), Exception); +} + +TEST_F(UserServiceTest, getUserOk) { + EXPECT_CALL(*mock_ptr, getUserById(1)) + .Times(1) + .WillOnce(::testing::Return(User(1, "login", "password", "username"))); + User u = us->getUserById(1); + EXPECT_EQ(u.getLogin(), "login"); + EXPECT_EQ(u.getId(), 1); + EXPECT_EQ(u.getPassword(), "password"); + EXPECT_EQ(u.getUsername(), "username"); +} + +TEST_F(UserServiceTest, getUserEXEPTION) { + EXPECT_CALL(*mock_ptr, getUserById(-1)).Times(1).WillOnce(NoUserException()); + EXPECT_THROW(us->getUserById(-1), Exception); +} + +TEST_F(UserServiceTest, makeUserOk) { + EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) + .Times(1) + .WillOnce(::testing::Return(1)); + User u = us->createUser("login", "username", "password"); + EXPECT_EQ(u.getLogin(), "login"); + EXPECT_EQ(u.getId(), 1); + EXPECT_EQ(u.getPassword(), "password"); + EXPECT_EQ(u.getUsername(), "username"); +} + +TEST_F(UserServiceTest, makeUserInvalidData) { + EXPECT_CALL(*mock_ptr, makeUser(User("login", "password", "username"))) + .Times(0); + EXPECT_THROW(us->createUser("", "", ""), ValidateException); +} \ No newline at end of file diff --git a/server/internal/service/tests/UserValidatorTest.cpp b/server/internal/service/tests/UserValidatorTest.cpp new file mode 100644 index 0000000..802b2f0 --- /dev/null +++ b/server/internal/service/tests/UserValidatorTest.cpp @@ -0,0 +1,29 @@ +#include +#include + +#include "UserValidator.h" + +TEST(UserValidatorTest, validateOK) { + UserValidator uv(User("login", "password", "username")); + EXPECT_TRUE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidLogin) { + UserValidator uv(User("", "password", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidPassword) { + UserValidator uv(User("login", "", "username")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUsername) { + UserValidator uv(User("login", "password", "")); + EXPECT_FALSE(uv.validateUser()); +} + +TEST(UserValidatorTest, invalidUserFields) { + UserValidator uv(User("", "", "")); + EXPECT_FALSE(uv.validateUser()); +} \ No newline at end of file diff --git a/server/internal/service/tests/main.cpp b/server/internal/service/tests/main.cpp new file mode 100644 index 0000000..4ccb037 --- /dev/null +++ b/server/internal/service/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 -- GitLab