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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,10 @@ IF (MINGW)
SET(OD_SOURCEFILES ${OD_SOURCEFILES} ${SRC}/utils/StackTraceWinMinGW.cpp)
ELSEIF(MSVC)
SET(OD_SOURCEFILES ${OD_SOURCEFILES} ${SRC}/utils/StackTraceWinMSVC.cpp)
ELSEIF(APPLE)
# StackTraceUnix relies on struct sigcontext and the deprecated ucontext
# routines, neither of which exists on macOS.
SET(OD_SOURCEFILES ${OD_SOURCEFILES} ${SRC}/utils/StackTraceStub.cpp)
ELSEIF(UNIX)
SET(OD_SOURCEFILES ${OD_SOURCEFILES} ${SRC}/utils/StackTraceUnix.cpp)
ELSE()
Expand Down
7 changes: 4 additions & 3 deletions cmake/modules/BoostTestTargets/BoostTestTargets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ if(Boost_FOUND)
if(Boost_USE_STATIC_LIBS)
set(_boostConfig "BoostTestTargetsStatic.h")
else()
if(NOT APPLE)
set(_boostConfig "BoostTestTargetsDynamic.h")
endif()
# Also on Apple: the "included" fallback compiles the whole
# framework into every file including BoostTestTargetConfig.h,
# which gives duplicate symbols in multi-file tests.
set(_boostConfig "BoostTestTargetsDynamic.h")
endif()
endif()
get_filename_component(_moddir ${CMAKE_CURRENT_LIST_FILE} PATH)
Expand Down
51 changes: 51 additions & 0 deletions scripts/unix/run_boost_test_with_server.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash
# Launch a headless OpenDungeons server, run the given boost test binary
# (which acts as a game client) against it, then shut the server down.
#
# Usage: run_boost_test_with_server.sh <od-binary> <level> <test-command...>
#
# This is wired as the LAUNCHER of the integration tests (the aa-*/ab-* ones)
# in source/tests/CMakeLists.txt, so that a plain `ctest` run works without
# having to start a server manually. run_unit_tests.sh remains the way to run
# the whole suite directly from a build directory.

set -u

if [ $# -lt 3 ]; then
echo "Usage: $0 <od-binary> <level> <test-command...>" >&2
exit 1
fi

OD_BINARY="$1"
LEVEL="$2"
shift 2

if [ ! -x "${OD_BINARY}" ]; then
echo "Game binary not found or not executable: ${OD_BINARY}" >&2
exit 1
fi

# The game must be started from the directory containing its binary so that it
# finds resources.cfg and the game data symlinked into the build tree.
OD_DIR="$(cd "$(dirname "${OD_BINARY}")" && pwd)"

SERVER_LOG="srvLog-$(basename "${LEVEL}" .level).txt"
(cd "${OD_DIR}" && exec "./$(basename "${OD_BINARY}")" --server "${LEVEL}" --port 32222 --log "${SERVER_LOG}") &
SERVER_PID=$!

stop_server() {
kill "${SERVER_PID}" 2>/dev/null
wait "${SERVER_PID}" 2>/dev/null
}
trap stop_server EXIT

# The test client retries the connection itself, but fail fast if the server
# died right away (e.g. level not found).
sleep 1
if ! kill -0 "${SERVER_PID}" 2>/dev/null; then
echo "Server failed to start (level ${LEVEL}). Check ${SERVER_LOG} in the user data folder." >&2
exit 1
fi

"$@"
exit $?
38 changes: 38 additions & 0 deletions source/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
include(BoostTestTargets)

# The aa-*/ab-* tests are integration tests: each test binary is a game client
# that expects a headless game server listening on localhost:32222 and hosting
# the multiplayer level named after the two-letter test prefix
# (levels/multiplayer/aa.level, ab.level, ...). The 00-* tests are plain unit
# tests and need no server.
# On Unix we wrap the integration tests in a launcher script that starts and
# stops that server, so they can be run through a plain `ctest` (or by running
# scripts/unix/run_unit_tests.sh from the build directory). On Windows, use
# scripts/win32/OpenDungeonsTests.bat instead.
if(UNIX)
set(SERVER_LAUNCHER_AA LAUNCHER
${CMAKE_SOURCE_DIR}/scripts/unix/run_boost_test_with_server.sh
$<TARGET_FILE:${PROJECT_BINARY_NAME}> aa.level)
set(SERVER_LAUNCHER_AB LAUNCHER
${CMAKE_SOURCE_DIR}/scripts/unix/run_boost_test_with_server.sh
$<TARGET_FILE:${PROJECT_BINARY_NAME}> ab.level)
else()
set(SERVER_LAUNCHER_AA)
set(SERVER_LAUNCHER_AB)
endif()

add_boost_test(00-Random
SOURCES
test_Random.cpp
Expand Down Expand Up @@ -40,6 +61,7 @@ add_boost_test(00-Pathfinding
test_Pathfinding.cpp)

add_boost_test(aa-LaunchGame
${SERVER_LAUNCHER_AA}
SOURCES
${SRC}/tests/mocks/ODClientTest.cpp
${SRC}/game/SeatData.cpp
Expand All @@ -61,6 +83,7 @@ add_boost_test(aa-LaunchGame
${OGRE_LIBRARIES})

add_boost_test(aa-TestCreatures
${SERVER_LAUNCHER_AA}
SOURCES
${SRC}/tests/mocks/ODClientTest.cpp
${SRC}/game/SeatData.cpp
Expand All @@ -82,6 +105,7 @@ add_boost_test(aa-TestCreatures
${OGRE_LIBRARIES})

add_boost_test(aa-TestRooms
${SERVER_LAUNCHER_AA}
SOURCES
${SRC}/tests/mocks/ODClientTest.cpp
${SRC}/game/SeatData.cpp
Expand All @@ -104,6 +128,7 @@ add_boost_test(aa-TestRooms
${OGRE_LIBRARIES})

add_boost_test(aa-TestRoomSplit
${SERVER_LAUNCHER_AA}
SOURCES
${SRC}/tests/mocks/ODClientTest.cpp
${SRC}/game/SeatData.cpp
Expand All @@ -126,6 +151,7 @@ add_boost_test(aa-TestRoomSplit
${OGRE_LIBRARIES})

add_boost_test(ab-TestTraps
${SERVER_LAUNCHER_AB}
SOURCES
${SRC}/tests/mocks/ODClientTest.cpp
${SRC}/game/SeatData.cpp
Expand All @@ -147,3 +173,15 @@ add_boost_test(ab-TestTraps
${Boost_SYSTEM_LIBRARY_RELEASE}
${OGRE_LIBRARIES})


if(UNIX)
# The integration tests all use the same server port: prevent ctest from
# running two of them concurrently (e.g. with ctest -j).
set_tests_properties(
aa-LaunchGame-boost_test
aa-TestCreatures-boost_test
aa-TestRooms-boost_test
aa-TestRoomSplit-boost_test
ab-TestTraps-boost_test
PROPERTIES RESOURCE_LOCK od-test-server)
endif()
2 changes: 1 addition & 1 deletion source/utils/Helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ namespace Helper
{
return TTostring(d);
}
#if defined(__OpenBSD__) && defined(__LP64__)
#if defined(__APPLE__) || (defined(__OpenBSD__) && defined(__LP64__))
std::string toString(size_t d)
{
return TTostring(d);
Expand Down
5 changes: 4 additions & 1 deletion source/utils/Helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ namespace Helper
std::string toString(uint32_t d);
std::string toString(int64_t d);
std::string toString(uint64_t d);
#if defined(__OpenBSD__) && defined(__LP64__)
// On LP64 systems whose size_t is unsigned long while uint64_t is
// unsigned long long (macOS, OpenBSD), size_t matches none of the fixed
// width overloads and calls become ambiguous.
#if defined(__APPLE__) || (defined(__OpenBSD__) && defined(__LP64__))
std::string toString(size_t d);
#endif
std::string toString(const Ogre::Vector2& v);
Expand Down
12 changes: 8 additions & 4 deletions source/utils/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ ResourceManager::ResourceManager(boost::program_options::variables_map& options)

void ResourceManager::setupDataPath(boost::program_options::variables_map& options)
{
std::string path;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
//TODO - Test osx support
char applePath[1024];
Expand All @@ -115,12 +116,12 @@ void ResourceManager::setupDataPath(boost::program_options::variables_map& optio
CFRelease(mainBundleURL);
CFRelease(cfStringRef);

mMacBundlePath = std::string(applePath + "/");
// Not applePath + "/": that is a pointer plus a pointer, which does not compile.
mMacBundlePath = std::string(applePath) + "/";

mGameDataPath = mMacBundlePath + "Contents/Resources/";
#else // Windows and linux

std::string path;
#ifdef OD_DATA_PATH
path = std::string(OD_DATA_PATH);
#else
Expand All @@ -139,7 +140,12 @@ void ResourceManager::setupDataPath(boost::program_options::variables_map& optio
mGameDataPath = Ogre::FileSystemLayer::resolveBundlePath(mGameDataPath);
#endif
}
#endif // Windows and Linux

// From here on the logic is the same on every platform: data or a plugins.cfg
// in the current folder win over the installed ones. This is also what lets a
// macOS build run at all outside an .app bundle: the Apple branch above knows
// only the bundle layout, and nothing used to set the plugins path there.
// Test whether there is data in "./" and remove the system path in that case.
// Useful for developers.
std::string resourceCfg = "./" + RESOURCECFG;
Expand Down Expand Up @@ -179,8 +185,6 @@ void ResourceManager::setupDataPath(boost::program_options::variables_map& optio
mPluginsPath = pluginsCfg;
}

#endif // Windows and Linux

OD_LOG_INF( PLUGINSCFG + " path is: " + mPluginsPath + '\n');

mScriptPath = mGameDataPath + SCRIPTSUBPATH;
Expand Down