Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Copyright (C) 2005 - 2026 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

name: Unit tests

on:
push:
branches:
- master
- develop
- bugfix/**
- feature/**
- fix/**
- github/**
- pr/**
pull_request:

concurrency:
group: ${{format('tests-{0}:{1}', github.repository, github.ref)}}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
StyleAndFormatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- run: curl -sSL --retry 5 --connect-timeout 15 https://github.com/Return-To-The-Roots/s25client/raw/refs/heads/master/.clang-format --output .clang-format
- name: Validation
run: tools/ci/staticValidation.sh "$GITHUB_WORKSPACE"
- name: Formatting
uses: DoozyX/clang-format-lint-action@bcb4eb2cb0d707ee4f3e5cc3b456eb075f12cf73 # v0.20
with:
source: "libs tests"
clangFormatVersion: 10
- name: Lint markdown files
uses: avto-dev/markdown-lint@04d43ee9191307b50935a753da3b775ab695eceb # v1.5.0
with:
args: .
- name: Check licensing
run:
pip install --user reuse
reuse lint
UnitTests:
strategy:
matrix:
include:
- { compiler: gcc-9, os: ubuntu-22.04, buildType: Debug, boostVersion: 1.73.0 } # Older ones fail due to PTHREAD_STACK_MIN use in Boost.Thread
- { compiler: clang, os: macos-26, buildType: Debug, boostVersion: 1.81.0 } # New libc++ only supported since 1.81
# Latest GCC
- { compiler: gcc-14, os: ubuntu-24.04, buildType: Debug, boostVersion: 1.87.0 }
# Latest Clang
- { compiler: clang-19, os: ubuntu-24.04, buildType: Debug, boostVersion: 1.81.0 }
# Windows
- { compiler: msvc-14.3, os: windows-2022, buildType: Debug, boostVersion: 1.87.0, generator: 'Visual Studio 17 2022' }
- { compiler: msvc-14.5, os: windows-2025-vs2026, buildType: Debug, boostVersion: 1.91.0, generator: 'Visual Studio 18 2026' }
- { compiler: gcc, sys: MINGW64, os: windows-latest, buildType: Debug, boostVersion: 1.91.0, generator: 'Ninja' }

runs-on: ${{matrix.os}}
defaults:
run:
shell: ${{matrix.sys && 'msys2 {0}' || 'bash'}}
steps:
- name: Setup MSYS2 environment for MinGW
if: matrix.sys
uses: msys2/setup-msys2@ec48f7c5447b3140e2b088413ae3a55687bccb6e # v2.33.0
with:
msystem: ${{matrix.sys}}
update: true
install: git python
pacboy: gcc:p cmake:p ninja:p miniupnpc:p

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install system packages (Linux)
if: runner.os == 'Linux'
run: |
pkgs=${{matrix.compiler}}
pkgs=${pkgs/gcc-/g++-}
sudo apt install ccache libminiupnpc-dev $pkgs
- name: Install system packages (OSX)
if: runner.os == 'macOS'
run: brew install ccache cmake miniupnpc
- name: Install system packages (Windows)
if: runner.os == 'Windows' && ! matrix.sys
run: choco install wget

- name: Setup compiler
if: "!startsWith(matrix.compiler, 'msvc')"
run: tools/ci/setupCompiler.sh
env:
COMPILER: ${{matrix.compiler}}

- name: Setup cmake
if: runner.os != 'Windows'
uses: jwlawson/actions-setup-cmake@0d6a7d60b009d01c9e7523be22153ff8f19460d3 # v2.2.0
with:
cmake-version: '3.20.x'

- name: Setup CCache
if: runner.os != 'Windows'
uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23
with:
key: ${{matrix.os}}-${{matrix.compiler}}-${{matrix.buildType}}-${{matrix.boostVersion}}
max-size: 200M

- run: echo "BOOST_ROOT=${{runner.temp}}/boost${{matrix.boostVersion}}" >> $GITHUB_ENV
- name: Cache Boost installation
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{env.BOOST_ROOT}}
key: ${{matrix.os}}-${{matrix.compiler}}-${{matrix.boostVersion}}-${{matrix.buildType}}

- name: Install Boost
env:
BOOST_VERSION: ${{matrix.boostVersion}}
TOOLSET: ${{matrix.compiler}}
VARIANT: ${{matrix.buildType}}
run: |
echo "ADDITIONAL_CMAKE_FLAGS=-DBoost_NO_SYSTEM_PATHS=ON" >> $GITHUB_ENV
LINK=""
if [[ "$RUNNER_OS" == "Windows" ]]; then
LINK=static
else
LINK=shared
fi
tools/ci/installBoost.sh "${BOOST_VERSION}" "${BOOST_ROOT}" "filesystem,locale,test" $LINK

- name: Checkout libendian
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Return-To-The-Roots/libendian
ref: master
path: ${{github.workspace}}/libendian
- name: Build
run: tools/ci/build.sh "${{matrix.buildType}}" "${ADDITIONAL_CMAKE_FLAGS}" "tests"
env:
GENERATOR: ${{matrix.generator}}
LIBENDIAN_DIR: ${{github.workspace}}/libendian
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ project(s25util)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(isTopLevel TRUE)
find_path(RTTR_LIBENDIAN_DIR NAMES "include/libendian" HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../libendian PATHS ENV LIBENDIAN_DIR PATH_SUFFIXES ".." libendian)
if(NOT RTTR_LIBENDIAN_DIR)
message(FATAL_ERROR "Path to libendian not found! You can set the full path in the env var LIBENDIAN_DIR ($ENV{LIBENDIAN_DIR})")
endif()
add_subdirectory(${RTTR_LIBENDIAN_DIR} libendian)
include(EnableCCache)
include(RttrBoostCfg)
# Boost 1.73 contains Boost.Nowide, 1.74 a required fix
find_package(Boost 1.74 COMPONENTS nowide)
else()
set(isTopLevel FALSE)
endif()

# The super project might e.g. call find_package(Boost ... nowide), if the target is not defined, download directly
if(NOT TARGET Boost::nowide)
message(STATUS "Fetching Boost.Nowide from repository...")
Expand Down
38 changes: 38 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2005 - 2026 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

version: 1.0.{build}

shallow_clone: true

branches:
only: [master]

image: Visual Studio 2019

configuration:
- Debug
- Release

platform: x64

environment:
global:
BOOST_DIR: 'C:\Libraries\boost_1_85_0'
RTTR_DISABLE_ASSERT_BREAKPOINT: 1

install:
- git clone https://github.com/Return-To-The-Roots/libendian.git libendian
- set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%cd%\libendian

before_build:
- mkdir build
- cd build
- dir /a:d %BOOST_DIR%
- cmake -G "Visual Studio 16 2019" -A %platform% -DRTTR_ENABLE_WERROR=ON -DBOOST_ROOT="%BOOST_DIR%\lib64-msvc-14.2\cmake" -DBoost_VERBOSE=ON ..

build_script: cmake --build . --config %configuration% --parallel 4

test_script: ctest --output-on-failure -C %configuration% --parallel 4

6 changes: 5 additions & 1 deletion cmake/AddTestcase.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2005 - 2021 Settlers Freaks <sf-team at siedler25.org>
# Copyright (C) 2005 - 2026 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

Expand Down Expand Up @@ -56,4 +56,8 @@ function(add_testcase)
)
set_tests_properties(${name} PROPERTIES ENVIRONMENT "${options}")
endif()
if(NOT TARGET tests)
add_custom_target(tests)
endif()
add_dependencies(tests ${name})
endfunction()
2 changes: 1 addition & 1 deletion cmake/RttrBoostCfg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Show message about boost config

# Default boost libs are static on self-build windows versions and dynamic in the linux package repos
if(WIN32 AND NOT MINGW)
if(WIN32)
set(RTTR_USE_STATIC_BOOST_DEFAULT ON)
else()
set(RTTR_USE_STATIC_BOOST_DEFAULT OFF)
Expand Down
12 changes: 6 additions & 6 deletions libs/common/include/s25util/span.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,19 @@ class span
constexpr span() noexcept : s_(0, 0)
{}

template<class I, std::enable_if_t<E == dynamic_extent && detail::span_convertible_v<I, T>, int> = 0>
template<class I, std::enable_if_t<detail::span_convertible_v<I, T> && E == dynamic_extent, int> = 0>
constexpr span(I* f, size_type c) : s_(f, c)
{}

template<class I, std::enable_if_t<E != dynamic_extent && detail::span_convertible_v<I, T>, int> = 0>
template<class I, std::enable_if_t<detail::span_convertible_v<I, T> && E != dynamic_extent, int> = 0>
explicit constexpr span(I* f, size_type c) : s_(f, c)
{}

template<class I, class L, std::enable_if_t<E == dynamic_extent && detail::span_convertible_v<I, T>, int> = 0>
template<class I, class L, std::enable_if_t<detail::span_convertible_v<I, T> && E == dynamic_extent, int> = 0>
constexpr span(I* f, L* l) : s_(f, l - f)
{}

template<class I, class L, std::enable_if_t<E != dynamic_extent && detail::span_convertible_v<I, T>, int> = 0>
template<class I, class L, std::enable_if_t<detail::span_convertible_v<I, T> && E != dynamic_extent, int> = 0>
explicit constexpr span(I* f, L* l) : s_(f, l - f)
{}

Expand All @@ -242,11 +242,11 @@ class span
constexpr span(const std::array<U, N>& a) noexcept : s_(a.data(), N)
{}

template<class R, std::enable_if_t<E == dynamic_extent && detail::span_is_range_v<R, T>, int> = 0>
template<class R, std::enable_if_t<detail::span_is_range_v<R, T> && E == dynamic_extent, int> = 0>
constexpr span(R&& r) noexcept(noexcept(std::data(r)) && noexcept(r.size())) : s_(std::data(r), r.size())
{}

template<class R, std::enable_if_t<E != dynamic_extent && detail::span_is_range_v<R, T>, int> = 0>
template<class R, std::enable_if_t<detail::span_is_range_v<R, T> && E != dynamic_extent, int> = 0>
explicit constexpr span(R&& r) noexcept(noexcept(std::data(r)) && noexcept(r.size())) : s_(std::data(r), r.size())
{}

Expand Down
71 changes: 71 additions & 0 deletions tools/ci/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash

# Copyright (C) 2005 - 2026 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

set -euo pipefail

function print_on_gha {
[[ "${GITHUB_ACTIONS:-false}" != "true" ]] || echo "$@"
}
function startGroup {
print_on_gha "::group::$1"
}
function endGroup {
print_on_gha "::endgroup::"
}

# Required by the tests
export USER="${USER:-TestUser}"

BUILD_TYPE="${1}"
CMAKE_FLAGS="${2}"
TARGET="${3:-install}"

[[ -d build ]] || mkdir build
cd build

if [[ -z ${GENERATOR:-} ]]; then
if [[ "${RUNNER_OS:-}" == "Linux" ]] || [[ "${RUNNER_OS:-}" == "macOS" ]]; then
GENERATOR="Unix Makefiles"
else
echo 'Missing $GENERATOR!'
exit 1
fi
fi
if [[ $GENERATOR == "Visual Studio"* ]]; then
BUILD_FLAGS=""
else
BUILD_FLAGS="-j3"
fi

cmake --version

set -x
# shellcheck disable=SC2086
cmake \
-G "$GENERATOR" \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-DRTTR_ENABLE_WERROR=ON \
-DCMAKE_INSTALL_PREFIX="$PWD/installed" \
${CMAKE_FLAGS} \
..

cmake --build . --target "$TARGET" --config "${BUILD_TYPE}" -- $BUILD_FLAGS

# Execute tests
export RTTR_DISABLE_ASSERT_BREAKPOINT=1
export BOOST_TEST_LOG_LEVEL=message
export BOOST_TEST_REPORT_LEVEL=detailed
if ! ctest --output-on-failure -C "${BUILD_TYPE}" -j2; then
startGroup "CMake cache"
cat CMakeCache.txt
endGroup
echo "LD:${LD_LIBRARY_PATH:-}"
echo "DYLD:${DYLD_LIBRARY_PATH:-}"
echo "PATH:$PATH"
startGroup "Rerun failed tests only"
ctest --output-on-failure -C "${BUILD_TYPE}" --rerun-failed --extra-verbose
endGroup
fi
22 changes: 22 additions & 0 deletions tools/ci/checkUTF8.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
#
# Copyright (C) 2005 - 2026 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

# Check that all source files in the current folder are valid UTF-8.
# Prints the filenames of files that are not valid UTF-8 to stderr.
# Exits 0 if all files are valid UTF-8, 1 otherwise.

set -euo pipefail

failed=0
while IFS= read -r -d '' file; do
# Try to convert all source files from UTF-8 to detect encoding errors
if ! iconv -f UTF-8 "$file" > /dev/null; then
printf '%s\n' "$file" >&2
failed=1
fi
done < <(find . --exclude-dir=.git -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.tpp' -o -name '*.h' \) -print0)

exit "$failed"
Loading
Loading