Skip to content

Commit

Permalink
test(daemon): cover domain layer with unit tests
Browse files Browse the repository at this point in the history
Covers (most of) the domain layer with unit tests, also fixes some bugs found along the
way.
  • Loading branch information
LordTermor committed Nov 1, 2024
1 parent b592fcb commit f873127
Show file tree
Hide file tree
Showing 31 changed files with 979 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/change.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
uses: ./.github/workflows/analysis.yml
needs: dev-build
secrets: inherit
test:
uses: ./.github/workflows/test.yml
needs: dev-build
secrets: inherit
deploy:
uses: ./.github/workflows/deploy.yml
needs: prod-build
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Run CTest
on: workflow_call

jobs:
run-ctest:
name: Run CTest
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Download Docker image from artifacts
uses: actions/download-artifact@v4
with:
name: bxt-development-image
path: distfiles
- name: Load Docker image
run: docker load -i distfiles/bxt-development.tar
- uses: addnab/docker-run-action@v3
with:
image: anydistro/bxt-development:latest
options: -v ${{ github.workspace }}:/src
run: |
cd /src/build
ctest --output-on-failure
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
################################################################################
cmake_minimum_required(VERSION 3.23)
project(bxt C CXX)
include(CTest)

list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
Expand All @@ -12,6 +13,7 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wall -Wextra")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(FETCHCONTENT_QUIET FALSE)

option(BXT_EXPERIMENTAL_COPY_MOVE "Enable experimental copy/move operations" OFF)
Expand Down
7 changes: 5 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"BUILD_TESTING": "ON",
"CONAN_INSTALL_ARGS": "--build=missing;-o testing=True"
}
},
{
Expand All @@ -34,7 +36,8 @@
"name": "release",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
"CMAKE_BUILD_TYPE": "Release",
"BUID_TESTING": "OFF"
}
}
],
Expand Down
12 changes: 11 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
class BxtConanFile(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps"

options = {
"testing": [True, False],
}
default_options = {
"testing": False,
}

def requirements(self):
# to link to them you need to change cmake/deps.cmake
self.requires("openssl/3.3.1")
Expand All @@ -27,6 +33,10 @@ def requirements(self):
self.requires("cereal/1.3.2")
self.requires("libcoro/0.12.1")
self.requires("scope-lite/0.2.0")

if self.options.testing:
print("Testing enabled")
self.requires("catch2/3.7.0")

def configure(self):
self.options["boost/*"].shared = True
Expand Down
7 changes: 6 additions & 1 deletion daemon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ project(bxtd LANGUAGES CXX)
################################################################################
add_subdirectory(swagger)

if(BUILD_TESTING)
add_subdirectory(tests)
endif()

file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "*.cpp")
list(FILTER SOURCES EXCLUDE REGEX "tests/.*")

################################################################################
# Executable Configuration
Expand Down Expand Up @@ -41,4 +46,4 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
reflectcpp
)

add_dependencies(${PROJECT_NAME} deploy_swagger)
add_dependencies(${PROJECT_NAME} deploy_swagger daemon_tests)
1 change: 1 addition & 0 deletions daemon/core/domain/entities/Section.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Section {
std::string string() const {
return fmt::format("{}/{}/{}", branch(), repository(), architecture());
}
auto operator<=>(Section const& other) const = default;

private:
Name m_branch;
Expand Down
7 changes: 7 additions & 0 deletions daemon/core/domain/services/PermissionMatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
#include "PermissionMatcher.h"

#include <algorithm>

namespace bxt::Core::Domain::PermissionMatcher {

bool match(Permission const& lh, Permission const& rh) {
Expand All @@ -23,6 +25,11 @@ bool match(Permission const& lh, Permission const& rh) {
}
}

if (ltags.size() != rtags.size() && !std::ranges::contains(ltags, "*")
&& !std::ranges::contains(rtags, "*")) {
return false;
}

return true;
}

Expand Down
4 changes: 4 additions & 0 deletions daemon/core/domain/value_objects/PackageVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ struct PackageVersion {
return compare(*this, rh);
};

auto operator==(PackageVersion const& rh) const {
return compare(*this, rh) == 0;
}

static ParseResult from_string(std::string_view str);
std::string string() const;

Expand Down
2 changes: 2 additions & 0 deletions daemon/event_log/domain/entities/PackageLogEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class PackageLogEntry {
return m_version;
}

bool operator==(PackageLogEntry const& other) const = default;

private:
LogEntryType m_type;
Core::Domain::Section m_section;
Expand Down
2 changes: 2 additions & 0 deletions daemon/event_log/domain/entities/PackageUpdateLogEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class PackageUpdateLogEntry {
return previous_package_log_entry;
}

bool operator==(PackageUpdateLogEntry const& other) const = default;

private:
PackageLogEntry package_log_entry;
PackageLogEntry previous_package_log_entry;
Expand Down
53 changes: 53 additions & 0 deletions daemon/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
################################################################################
# Test Configuration
################################################################################

find_package(Catch2 REQUIRED)

################################################################################
# Test Sources
################################################################################

file(GLOB_RECURSE TEST_SOURCES "src/unit/*/**.cpp")
file(GLOB_RECURSE BXT_SOURCES "../*/**.cpp")

################################################################################
# Test Executable
################################################################################

add_executable(daemon_tests
${TEST_SOURCES} ${BXT_SOURCES}
)

target_link_libraries(daemon_tests PRIVATE
Catch2::Catch2WithMain
deps
reflectcpp
Dexode::EventBus
)

target_include_directories(daemon_tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../
${lmdbxx_SOURCE_DIR}/include
)

set_target_properties(daemon_tests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tests
)

get_target_property(TESTS_RUNTIME_OUTPUT_DIRECTORY daemon_tests RUNTIME_OUTPUT_DIRECTORY)

message("Tests will be run from ${TESTS_RUNTIME_OUTPUT_DIRECTORY}")

################################################################################
# Test Data
################################################################################

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data DESTINATION ${TESTS_RUNTIME_OUTPUT_DIRECTORY})

################################################################################
# CTest Integration
################################################################################
include(Catch)

catch_discover_tests(daemon_tests WORKING_DIRECTORY ${TESTS_RUNTIME_OUTPUT_DIRECTORY})
Binary file added daemon/tests/data/dummy-1-1-any.pkg.tar.zst
Binary file not shown.
Binary file added daemon/tests/data/dummy-1-1-any.pkg.tar.zst.sig
Binary file not shown.
27 changes: 27 additions & 0 deletions daemon/tests/src/unit/core/domain/entities/PackageTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* === This file is part of bxt ===
*
* SPDX-FileCopyrightText: 2024 Artem Grinev <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
*/
#include "core/domain/entities/Package.h"

#include <catch2/catch_test_macros.hpp>

using namespace bxt::Core::Domain;

TEST_CASE("Package", "[core][domain][entities]") {
SECTION("Parse file name") {
REQUIRE(Package::parse_file_name("package-1.0.0-1-x86_64.pkg.tar.zst").value()
== "package");
REQUIRE(Package::parse_file_name("package-1.0.0-1-any.pkg.tar.zst").value() == "package");
REQUIRE(Package::parse_file_name("lib32-package-1.0.0-1-x86_64.pkg.tar.zst").value()
== "lib32-package");

// Invalid cases
REQUIRE(Package::parse_file_name("package.pkg.tar.zst") == std::nullopt);
REQUIRE(Package::parse_file_name("1.0.0-1-x86_64.pkg.tar.zst") == std::nullopt);
REQUIRE(Package::parse_file_name("package-") == std::nullopt);
REQUIRE(Package::parse_file_name("package-1.0.0-1.pkg.tar.zst") == std::nullopt);
}
}
49 changes: 49 additions & 0 deletions daemon/tests/src/unit/core/domain/entities/SectionTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* === This file is part of bxt ===
*
* SPDX-FileCopyrightText: 2024 Artem Grinev <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
*/
#include "core/domain/entities/Section.h"

#include <catch2/catch_test_macros.hpp>

using namespace bxt::Core::Domain;

TEST_CASE("Section entity", "[core][domain][entities]") {
SECTION("Construction and getters") {
Section section(Name("stable"), Name("core"), Name("x86_64"));

REQUIRE(section.branch() == Name("stable"));
REQUIRE(section.repository() == Name("core"));
REQUIRE(section.architecture() == Name("x86_64"));
}

SECTION("Setters") {
Section section(Name("stable"), Name("core"), Name("x86_64"));

section.set_branch(Name("testing"));
REQUIRE(section.branch() == Name("testing"));

section.set_repository(Name("extra"));
REQUIRE(section.repository() == Name("extra"));

section.set_architecture(Name("aarch64"));
REQUIRE(section.architecture() == Name("aarch64"));
}

SECTION("ID generation") {
Section section(Name("stable"), Name("core"), Name("x86_64"));
REQUIRE(section.id() == "stable/core/x86_64");
}

SECTION("String representation") {
Section section(Name("stable"), Name("core"), Name("x86_64"));
REQUIRE(section.string() == "stable/core/x86_64");
}

SECTION("to_string function") {
Section section(Name("stable"), Name("core"), Name("x86_64"));
REQUIRE(bxt::to_string(section) == "stable/core/x86_64");
}
}
59 changes: 59 additions & 0 deletions daemon/tests/src/unit/core/domain/entities/UserTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* === This file is part of bxt ===
*
* SPDX-FileCopyrightText: 2024 Artem Grinev <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
*/
#include "core/domain/entities/User.h"

#include <catch2/catch_test_macros.hpp>

using namespace bxt::Core::Domain;

TEST_CASE("User entity", "[core][domain][entities]") {
SECTION("Construction and getters") {
User user(Name("testuser"), "password123");

REQUIRE(user.name() == Name("testuser"));
REQUIRE(user.password() == "password123");
REQUIRE(user.permissions().empty());
}

SECTION("Setters") {
User user(Name("testuser"), "password123");

user.set_name("newuser");
REQUIRE(user.name() == Name("newuser"));

user.set_password("newpassword");
REQUIRE(user.password() == "newpassword");

std::set<Permission> new_permissions = {Permission("read"), Permission("write")};
user.set_permissions(new_permissions);
REQUIRE(user.permissions() == new_permissions);
}

SECTION("ID") {
User user(Name("testuser"), "password123");
REQUIRE(user.id() == Name("testuser"));
}

SECTION("Permission checking") {
User user(Name("testuser"), "password123");
std::set<Permission> permissions = {Permission("sections.*.*.*"),
Permission("packages.get.stable.core.x86_64")};
user.set_permissions(permissions);

REQUIRE(user.has_permission("sections.stable.core.x86_64"));
REQUIRE(user.has_permission("packages.get.stable.core.x86_64"));
REQUIRE_FALSE(user.has_permission("packages.snap.stable.core.x86_64"));
REQUIRE_FALSE(user.has_permission("users.add"));
}

SECTION("Default constructor") {
User default_user;
REQUIRE(default_user.name() == Name("Unnamed"));
REQUIRE(default_user.password().empty());
REQUIRE(default_user.permissions().empty());
}
}
Loading

0 comments on commit f873127

Please sign in to comment.