Minor fixes + tests + getSupportURL().

This commit is contained in:
Mikaël Capelle
2022-05-02 17:09:36 +02:00
parent 225c86d258
commit 6ea9d92b26
19 changed files with 203 additions and 51 deletions
+2
View File
@@ -27,6 +27,8 @@ add_subdirectory(src/proxy)
# force plugin_python to build mobase
add_dependencies(plugin_python mobase)
set(PLUGIN_PYTHON_TESTS ${PLUGIN_PYTHON_TESTS} CACHE BOOL "build tests for plugin_python")
if (PLUGIN_PYTHON_TESTS)
add_subdirectory(tests)
endif()
+5 -1
View File
@@ -520,7 +520,11 @@ namespace mo2::python {
DWORD returnCode;
bool result =
o->waitForApplication((HANDLE)handle, refresh, &returnCode);
return std::make_tuple(result, returnCode);
// we force signed return code because it's probably what's expected
// in Python
return std::make_tuple(
result, static_cast<std::make_signed_t<DWORD>>(returnCode));
},
"handle"_a, "refresh"_a = true)
+2 -1
View File
@@ -89,7 +89,8 @@ namespace mo2::python {
.def("nexusGameID", &IPluginGame::nexusGameID)
.def("looksValid", &IPluginGame::looksValid, "directory"_a)
.def("gameVersion", &IPluginGame::gameVersion)
.def("getLauncherName", &IPluginGame::getLauncherName);
.def("getLauncherName", &IPluginGame::getLauncherName)
.def("getSupportURL", &IPluginGame::getSupportURL);
}
// multiple installers
+4
View File
@@ -479,6 +479,10 @@ namespace mo2::python {
{
PYBIND11_OVERRIDE_PURE(QString, IPluginGame, getLauncherName, );
}
QString getSupportURL() const override
{
PYBIND11_OVERRIDE(QString, IPluginGame, getSupportURL, );
}
protected:
std::map<std::type_index, std::any> featureList() const override;
+2 -3
View File
@@ -139,9 +139,8 @@ namespace pybind11::detail {
return type_caster<QStringList>::cast(var.toStringList(), policy, parent);
case QVariant::List:
return type_caster<QVariantList>::cast(var.toList(), policy, parent);
case QVariant::Map: // return
// type_caster<QVariantMap>::cast(var.toList(),
// policy, parent);
case QVariant::Map:
return type_caster<QVariantMap>::cast(var.toMap(), policy, parent);
default: {
PyErr_Format(PyExc_TypeError, "type unsupported: %d", var.type());
throw pybind11::error_already_set();
+2 -44
View File
@@ -1,46 +1,4 @@
cmake_minimum_required(VERSION 3.16)
set(PYLIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/pylibs)
if (TARGET uibase)
set(UIBASE_PATH $<TARGET_FILE:uibase>)
else()
set(UIBASE_PATH "${MO2_INSTALL_PATH}/bin/uibase.dll")
endif()
add_custom_target(pytest
${CMAKE_COMMAND} -E env
PYTHONPATH="${PYLIB_DIR}\\;$<TARGET_FILE_DIR:mobase>"
"UIBASE_PATH=${UIBASE_PATH}" "QT_ROOT=${QT_ROOT}"
${CMAKE_CURRENT_BINARY_DIR}/pylibs/bin/pytest.exe ${CMAKE_CURRENT_SOURCE_DIR}/../tests -s
WORKING_DIRECTORY ${MO2_INSTALL_PATH}
)
mo2_python_pip_install(pytest
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pylibs
PACKAGES pytest PyQt6==6.3.0)
add_dependencies(pytest mobase)
file(GLOB test_files CONFIGURE_DEPENDS "test_*.cpp")
foreach (test_file ${test_files})
get_filename_component(target ${test_file} NAME_WLE)
string(REPLACE "test_" "" pymodule ${target})
pybind11_add_module(${target} THIN_LTO ${test_file})
set_target_properties(${target}
PROPERTIES
OUTPUT_NAME ${pymodule}
LIBRARY_OUTPUT_DIRECTORY "${PYLIB_DIR}/mobase_tests")
if(DEFINED CMAKE_CONFIGURATION_TYPES)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
set_target_properties(${target} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY_${config} "${PYLIB_DIR}/mobase_tests")
endforeach()
endif()
mo2_add_dependencies(${target} PRIVATE uibase Qt::Core Qt::Widgets)
target_link_libraries(${target} PRIVATE pybind11::qt)
add_dependencies(pytest ${target})
endforeach()
add_subdirectory(python)
add_subdirectory(runner)
+56
View File
@@ -0,0 +1,56 @@
#include "imoinfo.h"
#include <gmock/gmock.h>
using namespace MOBase;
class MockOrganizer : public IOrganizer {
public:
// clang-format off
MOCK_METHOD(IModRepositoryBridge*, createNexusBridge, (), (const, override));
MOCK_METHOD(QString, profileName, (), (const, override));
MOCK_METHOD(QString, profilePath, (), (const, override));
MOCK_METHOD(QString, downloadsPath, (), (const, override));
MOCK_METHOD(QString, overwritePath, (), (const, override));
MOCK_METHOD(QString, basePath, (), (const, override));
MOCK_METHOD(QString, modsPath, (), (const, override));
MOCK_METHOD(VersionInfo, appVersion, (), (const, override));
MOCK_METHOD(IModInterface*, createMod, (GuessedValue<QString> &name), (override));
MOCK_METHOD(IPluginGame*, getGame, (const QString &gameName), (const, override));
MOCK_METHOD(void, modDataChanged, (IModInterface *mod), (override));
MOCK_METHOD(QVariant, pluginSetting, (const QString &pluginName, const QString &key), (const, override));
MOCK_METHOD(void, setPluginSetting, (const QString &pluginName, const QString &key, const QVariant &value), (override));
MOCK_METHOD(bool, isPluginEnabled, (const QString& pluginName), (const, override));
MOCK_METHOD(bool, isPluginEnabled, (IPlugin *plugin), (const, override));
MOCK_METHOD(QVariant, persistent, (const QString &pluginName, const QString &key, const QVariant &def), (const, override));
MOCK_METHOD(void, setPersistent, (const QString &pluginName, const QString &key, const QVariant &value, bool sync), (override));
MOCK_METHOD(QString, pluginDataPath, (), (const, override));
MOCK_METHOD(IModInterface*, installMod, (const QString &fileName, const QString &nameSuggestion), (override));
MOCK_METHOD(QString, resolvePath, (const QString &fileName), (const, override));
MOCK_METHOD(QStringList, listDirectories, (const QString &directoryName), (const, override));
MOCK_METHOD(QStringList, findFiles, (const QString &path, const std::function<bool(const QString&)> &filter), (const, override));
MOCK_METHOD(QStringList, findFiles, (const QString &path, const QStringList &filter), (const, override));
MOCK_METHOD(QStringList, getFileOrigins, (const QString &fileName) ,(const, override));
MOCK_METHOD(QList<FileInfo>, findFileInfos, (const QString &path, const std::function<bool(const FileInfo&)> &filter), (const, override));
MOCK_METHOD(std::shared_ptr<const IFileTree>, virtualFileTree, (), (const, override));
MOCK_METHOD(MOBase::IDownloadManager*, downloadManager, (), (const, override));
MOCK_METHOD(MOBase::IPluginList*, pluginList, (), (const, override));
MOCK_METHOD(MOBase::IModList*, modList, (), (const, override));
MOCK_METHOD(MOBase::IProfile*, profile, (), (const, override));
MOCK_METHOD(HANDLE, startApplication, (const QString &executable, const QStringList &args, const QString &cwd, const QString &profile, const QString &forcedCustomOverwrite, bool ignoreCustomOverwrite), (override));
MOCK_METHOD(bool, waitForApplication, (HANDLE handle, bool refresh, LPDWORD exitCode), (const, override));
MOCK_METHOD(bool, onAboutToRun, (const std::function<bool(const QString&)> &func), (override));
MOCK_METHOD(bool, onFinishedRun, (const std::function<void(const QString&, unsigned int)> &func), (override));
MOCK_METHOD(void, refresh, (bool saveChanges), (override));
MOCK_METHOD(MOBase::IPluginGame const *, managedGame, (), (const, override));
MOCK_METHOD(bool, onUserInterfaceInitialized, (const std::function<void (QMainWindow *)> &), (override));
MOCK_METHOD(bool, onProfileCreated, (const std::function<void(MOBase::IProfile*)>&), (override));
MOCK_METHOD(bool, onProfileRemoved, (const std::function<void(const QString&)>&), (override));
MOCK_METHOD(bool, onProfileRenamed, (const std::function<void(MOBase::IProfile*, QString const&, QString const&)>&), (override));
MOCK_METHOD(bool, onProfileChanged, (const std::function<void (MOBase::IProfile*, MOBase::IProfile*)> &), (override));
MOCK_METHOD(bool, onPluginSettingChanged, (const std::function<void (const QString &,const QString &,const QVariant &,const QVariant &)> &), (override));
MOCK_METHOD(bool, onPluginEnabled, (const std::function<void(const MOBase::IPlugin*)>&), (override));
MOCK_METHOD(bool, onPluginEnabled, (const QString&, const std::function<void()>&), (override));
MOCK_METHOD(bool, onPluginDisabled, (const std::function<void(const MOBase::IPlugin*)>&), (override));
MOCK_METHOD(bool, onPluginDisabled, (const QString&, const std::function<void()>&), (override));
// clang-format on
};
+54
View File
@@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.16)
# pytest
find_package(GTest REQUIRED)
set(PYLIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/pylibs)
if (TARGET uibase)
set(UIBASE_PATH $<TARGET_FILE:uibase>)
else()
set(UIBASE_PATH "${MO2_INSTALL_PATH}/bin/uibase.dll")
endif()
add_custom_target(pytest
${CMAKE_COMMAND} -E env
PYTHONPATH="${PYLIB_DIR}\\;$<TARGET_FILE_DIR:mobase>"
"UIBASE_PATH=${UIBASE_PATH}" "QT_ROOT=${QT_ROOT}"
${CMAKE_CURRENT_BINARY_DIR}/pylibs/bin/pytest.exe ${CMAKE_CURRENT_SOURCE_DIR} -s
WORKING_DIRECTORY ${MO2_INSTALL_PATH}
)
mo2_python_pip_install(pytest
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pylibs
PACKAGES pytest PyQt6==6.3.0)
add_dependencies(pytest mobase)
file(GLOB test_files CONFIGURE_DEPENDS "test_*.cpp")
foreach (test_file ${test_files})
get_filename_component(target ${test_file} NAME_WLE)
string(REPLACE "test_" "" pymodule ${target})
pybind11_add_module(${target} THIN_LTO ${test_file})
set_target_properties(${target}
PROPERTIES
OUTPUT_NAME ${pymodule}
LIBRARY_OUTPUT_DIRECTORY "${PYLIB_DIR}/mobase_tests")
if(DEFINED CMAKE_CONFIGURATION_TYPES)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
set_target_properties(${target} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY_${config} "${PYLIB_DIR}/mobase_tests")
endforeach()
endif()
mo2_add_dependencies(${target} PRIVATE uibase Qt::Core Qt::Widgets)
# set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
target_link_libraries(${target} PRIVATE pybind11::qt GTest::gmock)
target_include_directories(${target}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mocks)
add_dependencies(pytest ${target})
endforeach()
+43
View File
@@ -0,0 +1,43 @@
#include "pybind11_qt/pybind11_qt.h"
#include <pybind11/pybind11.h>
#include <QMap>
#include <QWidget>
#include "MockOrganizer.h"
namespace py = pybind11;
using namespace pybind11::literals;
using ::testing::NiceMock;
PYBIND11_MODULE(organizer, m)
{
m.def(
"organizer",
[]() -> IOrganizer* {
MockOrganizer* mock = new NiceMock<MockOrganizer>();
ON_CALL(*mock, profileName).WillByDefault([&mock]() {
return "profile";
});
const auto handle = (HANDLE)std::uintptr_t{4654};
ON_CALL(*mock, startApplication).WillByDefault([&mock, handle](auto&&...) {
return handle;
});
ON_CALL(*mock, waitForApplication)
.WillByDefault([&mock, original_handle = handle](
HANDLE handle, bool refresh, LPDWORD exitCode) {
if (handle == original_handle) {
*exitCode = 0;
return true;
}
else {
*exitCode = -1;
return false;
}
});
return mock;
},
py::return_value_policy::take_ownership);
}
+12
View File
@@ -0,0 +1,12 @@
import pytest
from PyQt6.QtWidgets import QWidget
m = pytest.importorskip("mobase_tests.organizer")
def test_getters():
o = m.organizer()
assert o.profileName() == "profile"
assert o.startApplication("") == 4654
assert o.waitForApplication(42) == (False, -1)
assert o.waitForApplication(4654) == (True, 0)
@@ -5,8 +5,6 @@
#include <QMap>
#include <QWidget>
#include <iostream>
namespace py = pybind11;
using namespace pybind11::literals;
+8
View File
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.16)
add_executable(pythonrunner-tests)
mo2_configure_tests(pythonrunner-tests
WARNINGS OFF)
mo2_add_dependencies(pythonrunner-tests PUBLIC uibase)
target_include_directories(pythonrunner-tests
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mocks)
+13
View File
@@ -0,0 +1,13 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "MockOrganizer.h"
using ::testing::Eq;
using ::testing::NaggyMock;
using ::testing::Return;
TEST(Organizer, Basic)
{
MockOrganizer mock;
}