mirror of
https://github.com/loot/loot-api-c.git
synced 2026-07-27 14:14:23 -07:00
Commit the C API code
This is LOOT v0.9.2's API, modified to wrap the LOOT C++ API at 5982136f71cd026ecf80a7b6c7b9dd53e0dcb8d5 (the commit may be rebased out of history, but it's the first iteration of the C++ API with the Error class exposed). Changes from the v0.9.2 API include: * a different header name (c_api.h) * a different DLL name (loot_c_api.dll) * loot_cleanliness codes that replace the loot_needs_cleaning codes * loot_get_tag_map() has been removed * loot_get_plugin_tags() now returns tags as strings
This commit is contained in:
@@ -77,3 +77,9 @@ $RECYCLE.BIN/
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# =========================
|
||||
# Other
|
||||
# =========================
|
||||
|
||||
build/
|
||||
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
cmake_minimum_required (VERSION 2.8.12.1)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
project (loot_api_c)
|
||||
include(ExternalProject)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build a shared library" ON)
|
||||
option(MSVC_STATIC_RUNTIME "Build with static runtime libs (/MT)" ON)
|
||||
|
||||
#######################################
|
||||
# External Projects
|
||||
#######################################
|
||||
|
||||
set (Boost_USE_STATIC_LIBS ON)
|
||||
set (Boost_USE_MULTITHREADED ON)
|
||||
|
||||
IF (MSVC)
|
||||
set (Boost_USE_STATIC_RUNTIME ${MSVC_STATIC_RUNTIME})
|
||||
ELSE()
|
||||
set (Boost_USE_STATIC_RUNTIME OFF)
|
||||
ENDIF()
|
||||
|
||||
IF (NOT Boost_USE_STATIC_LIBS)
|
||||
add_definitions(-DBOOST_LOG_DYN_LINK)
|
||||
ENDIF ()
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS atomic log log_setup regex locale thread date_time chrono filesystem system iostreams)
|
||||
|
||||
ExternalProject_Add(GTest
|
||||
PREFIX "external"
|
||||
URL "https://github.com/google/googletest/archive/release-1.7.0.tar.gz"
|
||||
CMAKE_ARGS -Dgtest_force_shared_crt=${MSVC_SHARED_RUNTIME}
|
||||
INSTALL_COMMAND "")
|
||||
ExternalProject_Get_Property(GTest SOURCE_DIR BINARY_DIR)
|
||||
set (GTEST_INCLUDE_DIRS "${SOURCE_DIR}/include")
|
||||
set (GTEST_LIBRARIES "${BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
ExternalProject_Add(testing-metadata
|
||||
PREFIX "external"
|
||||
URL "https://github.com/loot/testing-metadata/archive/2.0.0.tar.gz"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
ExternalProject_Add(testing-plugins
|
||||
PREFIX "external"
|
||||
URL "https://github.com/WrinklyNinja/testing-plugins/archive/1.0.0.tar.gz"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
ExternalProject_Add(loot_api
|
||||
PREFIX "external"
|
||||
URL "https://github.com/loot/loot/archive/5982136f71cd026ecf80a7b6c7b9dd53e0dcb8d5.zip"
|
||||
CMAKE_ARGS -DBOOST_INCLUDEDIR=${Boost_INCLUDE_DIR} -DMSVC_STATIC_RUNTIME=${MSVC_STATIC_RUNTIME} -DBUILD_SHARED_LIBS=OFF
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} --build . --target loot_api --config $(CONFIGURATION)
|
||||
INSTALL_COMMAND "")
|
||||
ExternalProject_Get_Property(loot_api SOURCE_DIR BINARY_DIR)
|
||||
set(LOOT_API_INCLUDE_DIRS "${SOURCE_DIR}/include")
|
||||
set(LOOT_API_LIBRARIES
|
||||
"${BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}loot_api${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
"${BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}loot_common${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
${Boost_LIBRARIES}
|
||||
"${BINARY_DIR}/external/src/libgit2-build/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}git2${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
"${BINARY_DIR}/external/src/libloadorder-build/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}loadorder${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
"${BINARY_DIR}/external/src/yaml-cpp-build/${CMAKE_CFG_INTDIR}/libyaml-cpp${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
##############################
|
||||
# General Settings
|
||||
##############################
|
||||
|
||||
set(LOOT_C_API_SRC "${CMAKE_SOURCE_DIR}/src/api/c_api.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/api/loot_db.cpp")
|
||||
|
||||
set(LOOT_C_API_HEADERS "${CMAKE_SOURCE_DIR}/include/loot/c_api.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/api/loot_db.h")
|
||||
|
||||
set(LOOT_C_API_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/test/main.cpp")
|
||||
|
||||
set(LOOT_C_API_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/test/api_game_operations_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_apply_load_order_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_create_db_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_eval_lists_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_dirty_info_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_masterlist_revision_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_plugin_messages_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_plugin_tags_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_tag_map_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_load_lists_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_sort_plugins_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_update_masterlist_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_write_minimal_list_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/test_api.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/common_game_test_fixture.h")
|
||||
|
||||
set(LOOT_C_API_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/test/main.cpp")
|
||||
|
||||
set(LOOT_C_API_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/test/api_game_operations_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_apply_load_order_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_create_db_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_eval_lists_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_dirty_info_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_masterlist_revision_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_plugin_messages_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_get_plugin_tags_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_load_lists_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_sort_plugins_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_update_masterlist_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/loot_write_minimal_list_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/test_api.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/test/common_game_test_fixture.h")
|
||||
|
||||
source_group("Header Files\\api" FILES ${LOOT_C_API_HEADERS})
|
||||
source_group("Header Files\\tests" FILES ${LOOT_C_API_TESTS_HEADERS})
|
||||
|
||||
source_group("Source Files\\api" FILES ${LOOT_C_API_SRC})
|
||||
source_group("Source Files\\tests" FILES ${LOOT_C_API_TESTS_SRC})
|
||||
|
||||
# Include source and library directories.
|
||||
include_directories("${CMAKE_SOURCE_DIR}/src"
|
||||
"${CMAKE_SOURCE_DIR}/include"
|
||||
${LOOT_API_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${GTEST_INCLUDE_DIRS})
|
||||
|
||||
##############################
|
||||
# System-Specific Settings
|
||||
##############################
|
||||
|
||||
# Settings when compiling for Windows.
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
add_definitions(-DUNICODE -D_UNICODE -DLIBLO_STATIC -DLOOT_STATIC)
|
||||
set(LOOT_C_API_SRC ${LOOT_C_API_SRC} "${CMAKE_SOURCE_DIR}/src/api/resource.rc")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};.")
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=c++14")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++14")
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
# Force static C++ runtime linkage.
|
||||
if (MSVC_STATIC_RUNTIME)
|
||||
foreach(flag
|
||||
CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT
|
||||
CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT)
|
||||
string(REPLACE "/MD" "/MT" "${flag}" "${${flag}}")
|
||||
set("${flag}" "${${flag}} /EHsc")
|
||||
endforeach()
|
||||
endif ()
|
||||
|
||||
# Set /bigobj to allow building Debug tests
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
|
||||
|
||||
|
||||
set (LOOT_API_LIBRARIES ${LOOT_API_LIBRARIES}
|
||||
version
|
||||
shlwapi
|
||||
winhttp
|
||||
crypt32
|
||||
Rpcrt4)
|
||||
endif ()
|
||||
|
||||
##############################
|
||||
# Define Targets
|
||||
##############################
|
||||
|
||||
# Build API.
|
||||
add_library (loot_c_api ${LOOT_C_API_SRC} ${LOOT_C_API_HEADERS})
|
||||
add_dependencies (loot_c_api loot_api)
|
||||
target_link_libraries(loot_c_api ${LOOT_API_LIBRARIES})
|
||||
|
||||
# Build API tests.
|
||||
add_executable (c_api_tests ${LOOT_C_API_TESTS_SRC} ${LOOT_C_API_TESTS_HEADERS})
|
||||
add_dependencies (c_api_tests loot_c_api GTest testing-metadata testing-plugins)
|
||||
target_link_libraries(c_api_tests loot_c_api ${GTEST_LIBRARIES})
|
||||
|
||||
##############################
|
||||
# Set Target-Specific Flags
|
||||
##############################
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(loot_c_api PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS} LOOT_C_API_EXPORT")
|
||||
else ()
|
||||
set_target_properties(loot_c_api PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS} LOOT_C_API_STATIC")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
##############################
|
||||
# Post-Build Steps
|
||||
##############################
|
||||
|
||||
# Copy testing metadata
|
||||
ExternalProject_Get_Property(testing-metadata SOURCE_DIR)
|
||||
add_custom_command(TARGET loot_c_api POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${SOURCE_DIR}
|
||||
"$<TARGET_FILE_DIR:loot_c_api>/testing-metadata")
|
||||
|
||||
# Copy testing plugins
|
||||
ExternalProject_Get_Property(testing-plugins SOURCE_DIR)
|
||||
add_custom_command(TARGET loot_c_api POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${SOURCE_DIR}
|
||||
$<TARGET_FILE_DIR:loot_c_api>)
|
||||
@@ -0,0 +1,16 @@
|
||||
LOOT API C Wrapper
|
||||
==================
|
||||
|
||||
A wrapper library for LOOT's C++ API that provides it as a C API.
|
||||
|
||||
This library is at a very early stage of development and wraps an API that is itself still a work-in-progress.
|
||||
|
||||
## Build Instructions
|
||||
|
||||
The library's build system uses [CMake](https://cmake.org/). Most of LOOT's C++ dependencies are managed by CMake, but the following must be obtained manually:
|
||||
|
||||
* [Boost](http://www.boost.org/) v1.55+
|
||||
|
||||
To build the wrapper, run CMake, and build the generated solution file. Only Windows support has been tested, though Linux builds should also be possible. A `loot_c_api.dll` is produced: this statically links the C++ API, so only one DLL is required.
|
||||
|
||||
**Note:** The module is currently built against revision [5982136](https://github.com/loot/loot/tree/5982136f71cd026ecf80a7b6c7b9dd53e0dcb8d5) of the API, which is post-0.9.2 and pre-0.10.0, but uses the v0.10 metadata syntax (as specified at that revision, in case there are further changes before the v0.10 release).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,458 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2013-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include <loot/api.h>
|
||||
|
||||
#include "api/loot_db.h"
|
||||
|
||||
using loot::Error;
|
||||
using loot::GameType;
|
||||
using loot::MessageType;
|
||||
using loot::LanguageCode;
|
||||
|
||||
const unsigned int loot_ok = Error::asUnsignedInt(Error::Code::ok);
|
||||
const unsigned int loot_error_liblo_error = Error::asUnsignedInt(Error::Code::liblo_error);
|
||||
const unsigned int loot_error_file_write_fail = Error::asUnsignedInt(Error::Code::path_write_fail);
|
||||
const unsigned int loot_error_parse_fail = Error::asUnsignedInt(Error::Code::path_read_fail);
|
||||
const unsigned int loot_error_condition_eval_fail = Error::asUnsignedInt(Error::Code::condition_eval_fail);
|
||||
const unsigned int loot_error_regex_eval_fail = Error::asUnsignedInt(Error::Code::regex_eval_fail);
|
||||
const unsigned int loot_error_no_mem = Error::asUnsignedInt(Error::Code::no_mem);
|
||||
const unsigned int loot_error_invalid_args = Error::asUnsignedInt(Error::Code::invalid_args);
|
||||
const unsigned int loot_error_no_tag_map = Error::asUnsignedInt(Error::Code::no_tag_map);
|
||||
const unsigned int loot_error_path_not_found = Error::asUnsignedInt(Error::Code::path_not_found);
|
||||
const unsigned int loot_error_no_game_detected = Error::asUnsignedInt(Error::Code::no_game_detected);
|
||||
const unsigned int loot_error_git_error = Error::asUnsignedInt(Error::Code::git_error);
|
||||
const unsigned int loot_error_windows_error = Error::asUnsignedInt(Error::Code::windows_error);
|
||||
const unsigned int loot_error_sorting_error = Error::asUnsignedInt(Error::Code::sorting_error);
|
||||
const unsigned int loot_return_max = loot_error_sorting_error;
|
||||
|
||||
// The following are the games identifiers used by the API.
|
||||
const unsigned int loot_game_tes4 = static_cast<unsigned int>(GameType::tes4);
|
||||
const unsigned int loot_game_tes5 = static_cast<unsigned int>(GameType::tes5);
|
||||
const unsigned int loot_game_fo3 = static_cast<unsigned int>(GameType::fo3);
|
||||
const unsigned int loot_game_fonv = static_cast<unsigned int>(GameType::fonv);
|
||||
const unsigned int loot_game_fo4 = static_cast<unsigned int>(GameType::fo4);
|
||||
|
||||
const unsigned int loot_message_say = static_cast<unsigned int>(MessageType::say);
|
||||
const unsigned int loot_message_warn = static_cast<unsigned int>(MessageType::warn);
|
||||
const unsigned int loot_message_error = static_cast<unsigned int>(MessageType::error);
|
||||
|
||||
// LOOT message languages.
|
||||
const unsigned int loot_lang_english = static_cast<unsigned int>(LanguageCode::english);
|
||||
const unsigned int loot_lang_spanish = static_cast<unsigned int>(LanguageCode::spanish);
|
||||
const unsigned int loot_lang_russian = static_cast<unsigned int>(LanguageCode::russian);
|
||||
const unsigned int loot_lang_french = static_cast<unsigned int>(LanguageCode::french);
|
||||
const unsigned int loot_lang_chinese = static_cast<unsigned int>(LanguageCode::chinese);
|
||||
const unsigned int loot_lang_polish = static_cast<unsigned int>(LanguageCode::polish);
|
||||
const unsigned int loot_lang_brazilian_portuguese = static_cast<unsigned int>(LanguageCode::brazilian_portuguese);
|
||||
const unsigned int loot_lang_finnish = static_cast<unsigned int>(LanguageCode::finnish);
|
||||
const unsigned int loot_lang_german = static_cast<unsigned int>(LanguageCode::german);
|
||||
const unsigned int loot_lang_danish = static_cast<unsigned int>(LanguageCode::danish);
|
||||
const unsigned int loot_lang_korean = static_cast<unsigned int>(LanguageCode::korean);
|
||||
|
||||
// LOOT cleanliness codes.
|
||||
const unsigned int loot_cleanliness_clean = static_cast<unsigned int>(loot::PluginCleanliness::clean);
|
||||
const unsigned int loot_cleanliness_dirty = static_cast<unsigned int>(loot::PluginCleanliness::dirty);
|
||||
const unsigned int loot_cleanliness_do_not_clean = static_cast<unsigned int>(loot::PluginCleanliness::do_not_clean);
|
||||
const unsigned int loot_cleanliness_unknown = static_cast<unsigned int>(loot::PluginCleanliness::unknown);
|
||||
|
||||
std::string extMessageStr;
|
||||
|
||||
unsigned int c_error(const Error& e) {
|
||||
extMessageStr = e.what();
|
||||
return e.codeAsUnsignedInt();
|
||||
}
|
||||
|
||||
unsigned int c_error(const unsigned int code, const std::string& what) {
|
||||
return c_error(Error(Error::Code(code), what.c_str()));
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Error Handling Functions
|
||||
//////////////////////////////
|
||||
|
||||
// Outputs a string giving the details of the last time an error or
|
||||
// warning return code was returned by a function. The string exists
|
||||
// until this function is called again or until CleanUpAPI is called.
|
||||
LOOT_C_API unsigned int loot_get_error_message(const char ** const message) {
|
||||
if (message == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null message pointer passed.");
|
||||
|
||||
*message = extMessageStr.c_str();
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Version Functions
|
||||
//////////////////////////////
|
||||
|
||||
LOOT_C_API bool loot_is_compatible(const unsigned int versionMajor, const unsigned int versionMinor, const unsigned int versionPatch) {
|
||||
return loot::IsCompatible(versionMajor, versionMinor, versionPatch);
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_get_version(unsigned int * const versionMajor, unsigned int * const versionMinor, unsigned int * const versionPatch) {
|
||||
if (versionMajor == nullptr || versionMinor == nullptr || versionPatch == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
*versionMajor = loot::LootVersion::major;
|
||||
*versionMinor = loot::LootVersion::minor;
|
||||
*versionPatch = loot::LootVersion::patch;
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_get_build_id(const char ** const revision) {
|
||||
if (revision == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null message pointer passed.");
|
||||
|
||||
*revision = loot::LootVersion::revision.c_str();
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Lifecycle Management Functions
|
||||
////////////////////////////////////
|
||||
|
||||
LOOT_C_API unsigned int loot_create_db(loot_db ** const db,
|
||||
const unsigned int clientGame,
|
||||
const char * const gamePath,
|
||||
const char * const gameLocalPath) {
|
||||
if (db == nullptr
|
||||
|| (clientGame != loot_game_tes4
|
||||
&& clientGame != loot_game_tes5
|
||||
&& clientGame != loot_game_fo3
|
||||
&& clientGame != loot_game_fonv
|
||||
&& clientGame != loot_game_fo4))
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
std::string game_path = "";
|
||||
if (gamePath != nullptr)
|
||||
game_path = gamePath;
|
||||
|
||||
std::string game_local_path = "";
|
||||
if (gameLocalPath != nullptr)
|
||||
game_local_path = gameLocalPath;
|
||||
#ifndef _WIN32
|
||||
else
|
||||
return c_error(loot_error_invalid_args, "A local data path must be supplied on non-Windows platforms.");
|
||||
#endif
|
||||
|
||||
try {
|
||||
*db = new loot_db(loot::GameType(clientGame), game_path, game_local_path);
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::bad_alloc& e) {
|
||||
return c_error(loot_error_no_mem, e.what());
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_invalid_args, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
// Destroys the given DB, freeing any memory allocated as part of its use.
|
||||
LOOT_C_API void loot_destroy_db(loot_db * const db) {
|
||||
delete db;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Database Loading Functions
|
||||
///////////////////////////////////
|
||||
|
||||
LOOT_C_API unsigned int loot_load_lists(loot_db * const db, const char * const masterlistPath,
|
||||
const char * const userlistPath) {
|
||||
if (db == nullptr || masterlistPath == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
try {
|
||||
std::string userlistPathString;
|
||||
if (userlistPath != nullptr)
|
||||
userlistPathString = userlistPath;
|
||||
|
||||
db->getDatabase()->LoadLists(masterlistPath, userlistPathString);
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_parse_fail, e.what());
|
||||
}
|
||||
|
||||
//Also free memory.
|
||||
db->clearArrays();
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_eval_lists(loot_db * const db, const unsigned int language) {
|
||||
if (db == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
if (language != loot_lang_english
|
||||
&& language != loot_lang_spanish
|
||||
&& language != loot_lang_russian
|
||||
&& language != loot_lang_french
|
||||
&& language != loot_lang_chinese
|
||||
&& language != loot_lang_polish
|
||||
&& language != loot_lang_brazilian_portuguese
|
||||
&& language != loot_lang_finnish
|
||||
&& language != loot_lang_german
|
||||
&& language != loot_lang_danish)
|
||||
return c_error(loot_error_invalid_args, "Invalid language code given.");
|
||||
|
||||
try {
|
||||
db->getDatabase()->EvalLists(loot::LanguageCode(language));
|
||||
} catch (loot::Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_condition_eval_fail, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// LOOT Functionality Functions
|
||||
////////////////////////////////////
|
||||
|
||||
LOOT_C_API unsigned int loot_sort_plugins(loot_db * const db,
|
||||
const char * const ** const sortedPlugins,
|
||||
size_t * const numPlugins) {
|
||||
if (db == nullptr || sortedPlugins == nullptr || numPlugins == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
//Initialise output.
|
||||
*numPlugins = 0;
|
||||
*sortedPlugins = nullptr;
|
||||
|
||||
try {
|
||||
auto plugins = db->getDatabase()->SortPlugins();
|
||||
db->setPluginNames(plugins);
|
||||
} catch (Error &e) {
|
||||
return c_error(e);
|
||||
} catch (std::bad_alloc& e) {
|
||||
return c_error(loot_error_no_mem, e.what());
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_sorting_error, e.what());
|
||||
}
|
||||
|
||||
if (db->getPluginNames().empty())
|
||||
return loot_ok;
|
||||
|
||||
*numPlugins = db->getPluginNames().size();
|
||||
*sortedPlugins = &db->getPluginNames()[0];
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_apply_load_order(loot_db * const db,
|
||||
const char * const * const loadOrder,
|
||||
const size_t numPlugins) {
|
||||
if (db == nullptr || loadOrder == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
try {
|
||||
auto plugins = std::vector<std::string>(loadOrder, loadOrder + numPlugins);
|
||||
db->getDatabase()->ApplyLoadOrder(plugins);
|
||||
} catch (Error &e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_liblo_error, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_update_masterlist(loot_db * const db,
|
||||
const char * const masterlistPath,
|
||||
const char * const remoteURL,
|
||||
const char * const remoteBranch,
|
||||
bool * const updated) {
|
||||
if (db == nullptr || masterlistPath == nullptr || remoteURL == nullptr || remoteBranch == nullptr || updated == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
*updated = false;
|
||||
|
||||
try {
|
||||
*updated = db->getDatabase()->UpdateMasterlist(masterlistPath, remoteURL, remoteBranch);
|
||||
} catch (Error &e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_git_error, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_get_masterlist_revision(loot_db * const db,
|
||||
const char * const masterlistPath,
|
||||
const bool getShortID,
|
||||
const char ** const revisionID,
|
||||
const char ** const revisionDate,
|
||||
bool * const isModified) {
|
||||
if (db == nullptr || masterlistPath == nullptr || revisionID == nullptr || revisionDate == nullptr || isModified == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
*revisionID = nullptr;
|
||||
*revisionDate = nullptr;
|
||||
*isModified = false;
|
||||
|
||||
bool modified = false;
|
||||
try {
|
||||
auto info = db->getDatabase()->GetMasterlistRevision(masterlistPath, getShortID);
|
||||
|
||||
if (info.revision_date.empty() || info.revision_id.empty())
|
||||
return loot_ok;
|
||||
|
||||
db->setRevisionIdString(info.revision_id);
|
||||
db->setRevisionDateString(info.revision_date);
|
||||
modified = info.is_modified;
|
||||
} catch (Error &e) {
|
||||
return c_error(e);
|
||||
} catch (std::bad_alloc& e) {
|
||||
return c_error(loot_error_no_mem, e.what());
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_git_error, e.what());
|
||||
}
|
||||
|
||||
*revisionID = db->getRevisionIdString();
|
||||
*revisionDate = db->getRevisionDateString();
|
||||
*isModified = modified;
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// DB Access Functions
|
||||
//////////////////////////
|
||||
|
||||
LOOT_C_API unsigned int loot_get_plugin_tags(loot_db * const db, const char * const plugin,
|
||||
const char * const ** const tagIds_added,
|
||||
size_t * const numTags_added,
|
||||
const char * const ** const tagIds_removed,
|
||||
size_t * const numTags_removed,
|
||||
bool * const userlistModified) {
|
||||
if (db == nullptr || plugin == nullptr || tagIds_added == nullptr || numTags_added == nullptr || tagIds_removed == nullptr || numTags_removed == nullptr || userlistModified == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
//Initialise output.
|
||||
*tagIds_added = nullptr;
|
||||
*tagIds_removed = nullptr;
|
||||
*userlistModified = false;
|
||||
*numTags_added = 0;
|
||||
*numTags_removed = 0;
|
||||
|
||||
try {
|
||||
auto tags = db->getDatabase()->GetPluginTags(plugin);
|
||||
|
||||
db->setAddedTags(tags.added);
|
||||
db->setRemovedTags(tags.removed);
|
||||
*userlistModified = tags.userlist_modified;
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_parse_fail, e.what());
|
||||
}
|
||||
|
||||
//Set outputs.
|
||||
*numTags_added = db->getAddedTags().size();
|
||||
*numTags_removed = db->getRemovedTags().size();
|
||||
|
||||
if (!db->getAddedTags().empty())
|
||||
*tagIds_added = reinterpret_cast<const char * const *>(&db->getAddedTags()[0]);
|
||||
|
||||
if (!db->getRemovedTags().empty())
|
||||
*tagIds_removed = reinterpret_cast<const char * const *>(&db->getRemovedTags()[0]);
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
// Returns the messages attached to the given plugin. Messages are valid until Load,
|
||||
// loot_destroy_db or loot_get_plugin_messages are next called. plugin is case-insensitive.
|
||||
// If no messages are attached, *messages will be nullptr and numMessages will equal 0.
|
||||
LOOT_C_API unsigned int loot_get_plugin_messages(loot_db * const db, const char * const plugin,
|
||||
const loot_message ** const messages,
|
||||
size_t * const numMessages) {
|
||||
if (db == nullptr || plugin == nullptr || messages == nullptr || numMessages == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
//Initialise output.
|
||||
*messages = nullptr;
|
||||
*numMessages = 0;
|
||||
|
||||
try {
|
||||
auto messages = db->getDatabase()->GetPluginMessages(plugin);
|
||||
|
||||
if (messages.empty())
|
||||
return loot_ok;
|
||||
|
||||
db->setPluginMessages(messages);
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_parse_fail, e.what());
|
||||
}
|
||||
|
||||
*messages = &db->getPluginMessages()[0];
|
||||
*numMessages = db->getPluginMessages().size();
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
LOOT_C_API unsigned int loot_get_dirty_info(loot_db * const db, const char * const plugin, unsigned int * const needsCleaning) {
|
||||
if (db == nullptr || plugin == nullptr || needsCleaning == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
*needsCleaning = loot_cleanliness_unknown;
|
||||
|
||||
try {
|
||||
*needsCleaning = static_cast<unsigned int>(db->getDatabase()->GetPluginCleanliness(plugin));
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_parse_fail, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
|
||||
// Writes a minimal masterlist that only contains mods that have Bash Tag suggestions,
|
||||
// and/or dirty messages, plus the Tag suggestions and/or messages themselves and their
|
||||
// conditions, in order to create the Wrye Bash taglist. outputFile is the path to use
|
||||
// for output. If outputFile already exists, it will only be overwritten if overwrite is true.
|
||||
LOOT_C_API unsigned int loot_write_minimal_list(loot_db * const db, const char * const outputFile, const bool overwrite) {
|
||||
if (db == nullptr || outputFile == nullptr)
|
||||
return c_error(loot_error_invalid_args, "Null pointer passed.");
|
||||
|
||||
try {
|
||||
db->getDatabase()->WriteMinimalList(outputFile, overwrite);
|
||||
} catch (Error& e) {
|
||||
return c_error(e);
|
||||
} catch (std::exception& e) {
|
||||
return c_error(loot_error_file_write_fail, e.what());
|
||||
}
|
||||
|
||||
return loot_ok;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2013-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "api/loot_db.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
loot_db::loot_db(const loot::GameType gameType, const std::string& gamePath, const std::string& gameLocalDataPath)
|
||||
: database(loot::CreateDatabase(gameType, gamePath, gameLocalDataPath)) {}
|
||||
|
||||
std::shared_ptr<loot::DatabaseInterface> loot_db::getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
const char * loot_db::getRevisionIdString() const {
|
||||
return revisionId.c_str();
|
||||
}
|
||||
|
||||
const char * loot_db::getRevisionDateString() const {
|
||||
return revisionDate.c_str();
|
||||
}
|
||||
|
||||
const std::vector<const char *>& loot_db::getPluginNames() const {
|
||||
return cPluginNames;
|
||||
}
|
||||
|
||||
const std::vector<const char *>& loot_db::getAddedTags() const {
|
||||
return addedTags;
|
||||
}
|
||||
|
||||
const std::vector<const char *>& loot_db::getRemovedTags() const {
|
||||
return removedTags;
|
||||
}
|
||||
|
||||
const std::vector<loot_message>& loot_db::getPluginMessages() const {
|
||||
return cPluginMessages;
|
||||
}
|
||||
|
||||
void loot_db::setRevisionIdString(const std::string& str) {
|
||||
revisionId = str;
|
||||
}
|
||||
|
||||
void loot_db::setRevisionDateString(const std::string& str) {
|
||||
revisionDate = str;
|
||||
}
|
||||
|
||||
void loot_db::setPluginNames(const std::vector<std::string>& plugins) {
|
||||
// First take copies of the C++ strings to store.
|
||||
pluginNames = plugins;
|
||||
|
||||
// Now store their C strings.
|
||||
cPluginNames.resize(pluginNames.size());
|
||||
std::transform(begin(pluginNames),
|
||||
end(pluginNames),
|
||||
begin(cPluginNames),
|
||||
[](const std::string& pluginName) {
|
||||
return pluginName.c_str();
|
||||
});
|
||||
}
|
||||
|
||||
void loot_db::setAddedTags(const std::set<std::string>& names) {
|
||||
addedTags.clear();
|
||||
for (const auto& name : names) {
|
||||
addedTags.push_back(storeTag(name));
|
||||
}
|
||||
}
|
||||
|
||||
void loot_db::setRemovedTags(const std::set<std::string>& names) {
|
||||
removedTags.clear();
|
||||
for (const auto& name : names) {
|
||||
removedTags.push_back(storeTag(name));
|
||||
}
|
||||
}
|
||||
|
||||
void loot_db::setPluginMessages(const std::vector<loot::PluginMessage>& pluginMessages) {
|
||||
cPluginMessages.resize(pluginMessages.size());
|
||||
pluginMessageStrings.resize(pluginMessages.size());
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto& message : pluginMessages) {
|
||||
pluginMessageStrings[i] = message.text;
|
||||
|
||||
cPluginMessages[i].type = static_cast<unsigned int>(message.type);
|
||||
cPluginMessages[i].message = pluginMessageStrings[i].c_str();
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void loot_db::clearArrays() {
|
||||
bashTags.clear();
|
||||
|
||||
pluginNames.clear();
|
||||
cPluginNames.clear();
|
||||
|
||||
addedTags.clear();
|
||||
removedTags.clear();
|
||||
|
||||
cPluginMessages.clear();
|
||||
pluginMessageStrings.clear();
|
||||
}
|
||||
|
||||
const char * loot_db::storeTag(const std::string & tag) {
|
||||
return bashTags.insert(tag).first->c_str();
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2013-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_API_LOOT_DB
|
||||
#define LOOT_API_LOOT_DB
|
||||
|
||||
#include <loot/api.h>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
struct loot_db {
|
||||
loot_db(const loot::GameType gameType,
|
||||
const std::string& gamePath,
|
||||
const std::string& gameLocalDataPath);
|
||||
|
||||
std::shared_ptr<loot::DatabaseInterface> getDatabase();
|
||||
|
||||
const char * getRevisionIdString() const;
|
||||
const char * getRevisionDateString() const;
|
||||
|
||||
const std::vector<const char *>& getPluginNames() const;
|
||||
|
||||
const std::vector<const char *>& getAddedTags() const;
|
||||
const std::vector<const char *>& getRemovedTags() const;
|
||||
|
||||
const std::vector<loot_message>& getPluginMessages() const;
|
||||
|
||||
void setRevisionIdString(const std::string& str);
|
||||
void setRevisionDateString(const std::string& str);
|
||||
|
||||
void setPluginNames(const std::vector<std::string>& plugins);
|
||||
|
||||
void setAddedTags(const std::set<std::string>& names);
|
||||
void setRemovedTags(const std::set<std::string>& names);
|
||||
|
||||
void setPluginMessages(const std::vector<loot::PluginMessage>& pluginMessages);
|
||||
|
||||
void clearArrays();
|
||||
private:
|
||||
const char * storeTag(const std::string& tag);
|
||||
|
||||
std::shared_ptr<loot::DatabaseInterface> database;
|
||||
|
||||
std::string revisionId;
|
||||
std::string revisionDate;
|
||||
|
||||
std::vector<std::string> pluginNames;
|
||||
std::vector<const char *> cPluginNames;
|
||||
|
||||
std::unordered_set<std::string> bashTags;
|
||||
std::vector<const char *> addedTags;
|
||||
std::vector<const char *> removedTags;
|
||||
|
||||
std::vector<loot_message> cPluginMessages;
|
||||
std::vector<std::string> pluginMessageStrings;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
#define MAINICON 101
|
||||
#endif
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 0, 9, 2, 0
|
||||
PRODUCTVERSION 0, 9, 2, 0
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileVersion", "0.9.2"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013-2016 WrinklyNinja"
|
||||
VALUE "ProductVersion", "0.9.2"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
MAINICON ICON "../resources/icon.ico"
|
||||
@@ -0,0 +1,123 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2013-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_API_GAME_OPERATIONS_TEST
|
||||
#define LOOT_TESTS_API_API_GAME_OPERATIONS_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/common_game_test_fixture.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class ApiGameOperationsTest :
|
||||
public ::testing::TestWithParam<unsigned int>,
|
||||
public CommonGameTestFixture {
|
||||
protected:
|
||||
ApiGameOperationsTest() :
|
||||
CommonGameTestFixture(GetParam()),
|
||||
db_(nullptr),
|
||||
masterlistPath(localPath / "masterlist.yaml"),
|
||||
noteMessage("Do not clean ITM records, they are intentional and required for the mod to function."),
|
||||
warningMessage("Check you are using v2+. If not, Update. v1 has a severe bug with the Mystic Emporium disappearing."),
|
||||
errorMessage("Obsolete. Remove this and install Enhanced Weather.") {}
|
||||
|
||||
virtual void SetUp() {
|
||||
setUp();
|
||||
|
||||
ASSERT_FALSE(boost::filesystem::exists(masterlistPath));
|
||||
|
||||
ASSERT_EQ(loot_ok, loot_create_db(&db_, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str()));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
tearDown();
|
||||
|
||||
ASSERT_NO_THROW(loot_destroy_db(db_));
|
||||
|
||||
// The masterlist may have been created during the test, so delete it.
|
||||
ASSERT_NO_THROW(boost::filesystem::remove(masterlistPath));
|
||||
}
|
||||
|
||||
void GenerateMasterlist() {
|
||||
using std::endl;
|
||||
|
||||
boost::filesystem::ofstream masterlist(masterlistPath);
|
||||
masterlist
|
||||
<< "plugins:" << endl
|
||||
<< " - name: " << blankEsm << endl
|
||||
<< " after:" << endl
|
||||
<< " - " << masterFile << endl
|
||||
<< " msg:" << endl
|
||||
<< " - type: say" << endl
|
||||
<< " content: '" << noteMessage << "'" << endl
|
||||
<< " tag:" << endl
|
||||
<< " - Actors.ACBS" << endl
|
||||
<< " - Actors.AIData" << endl
|
||||
<< " - '-C.Water'" << endl
|
||||
<< " - name: " << blankDifferentEsm << endl
|
||||
<< " after:" << endl
|
||||
<< " - " << blankMasterDependentEsm << endl
|
||||
<< " msg:" << endl
|
||||
<< " - type: warn" << endl
|
||||
<< " content: '" << warningMessage << "'" << endl
|
||||
<< " dirty:" << endl
|
||||
<< " - crc: 0x7d22f9df" << endl
|
||||
<< " utility: TES4Edit" << endl
|
||||
<< " udr: 4" << endl
|
||||
<< " - name: " << blankDifferentEsp << endl
|
||||
<< " after:" << endl
|
||||
<< " - " << blankPluginDependentEsp << endl
|
||||
<< " msg:" << endl
|
||||
<< " - type: error" << endl
|
||||
<< " content: '" << errorMessage << "'" << endl
|
||||
<< " - name: " << blankEsp << endl
|
||||
<< " after:" << endl
|
||||
<< " - " << blankDifferentMasterDependentEsp << endl
|
||||
<< " - name: " << blankDifferentMasterDependentEsp << endl
|
||||
<< " after:" << endl
|
||||
<< " - " << blankMasterDependentEsp << endl
|
||||
<< " msg:" << endl
|
||||
<< " - type: say" << endl
|
||||
<< " content: '" << noteMessage << "'" << endl
|
||||
<< " - type: warn" << endl
|
||||
<< " content: '" << warningMessage << "'" << endl
|
||||
<< " - type: error" << endl
|
||||
<< " content: '" << errorMessage << "'" << endl;
|
||||
|
||||
masterlist.close();
|
||||
}
|
||||
|
||||
loot_db * db_;
|
||||
|
||||
const boost::filesystem::path masterlistPath;
|
||||
|
||||
const std::string noteMessage;
|
||||
const std::string warningMessage;
|
||||
const std::string errorMessage;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,259 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_COMMON_GAME_TEST_FIXTURE
|
||||
#define LOOT_TESTS_COMMON_GAME_TEST_FIXTURE
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class CommonGameTestFixture {
|
||||
protected:
|
||||
CommonGameTestFixture(unsigned int gameType) :
|
||||
gameType(gameType),
|
||||
missingPath("./missing"),
|
||||
dataPath(getPluginsPath()),
|
||||
localPath(getLocalPath()),
|
||||
masterFile(getMasterFile()),
|
||||
missingEsp("Blank.missing.esp"),
|
||||
blankEsm("Blank.esm"),
|
||||
blankDifferentEsm("Blank - Different.esm"),
|
||||
blankMasterDependentEsm("Blank - Master Dependent.esm"),
|
||||
blankDifferentMasterDependentEsm("Blank - Different Master Dependent.esm"),
|
||||
blankEsp("Blank.esp"),
|
||||
blankDifferentEsp("Blank - Different.esp"),
|
||||
blankMasterDependentEsp("Blank - Master Dependent.esp"),
|
||||
blankDifferentMasterDependentEsp("Blank - Different Master Dependent.esp"),
|
||||
blankPluginDependentEsp("Blank - Plugin Dependent.esp"),
|
||||
blankDifferentPluginDependentEsp("Blank - Different Plugin Dependent.esp"),
|
||||
blankEsmCrc(getBlankEsmCrc()) {}
|
||||
|
||||
void setUp() {
|
||||
ASSERT_NO_THROW(boost::filesystem::create_directories(localPath));
|
||||
ASSERT_TRUE(boost::filesystem::exists(localPath));
|
||||
|
||||
ASSERT_FALSE(boost::filesystem::exists(missingPath));
|
||||
ASSERT_FALSE(boost::filesystem::exists(dataPath / missingEsp));
|
||||
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankEsm));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentEsm));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankMasterDependentEsm));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentMasterDependentEsm));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankEsp));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentEsp));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankMasterDependentEsp));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentMasterDependentEsp));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankPluginDependentEsp));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / blankDifferentPluginDependentEsp));
|
||||
|
||||
// Make sure the game master file exists.
|
||||
ASSERT_FALSE(boost::filesystem::exists(dataPath / masterFile));
|
||||
ASSERT_NO_THROW(boost::filesystem::copy_file(dataPath / blankEsm, dataPath / masterFile));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / masterFile));
|
||||
|
||||
// Set initial load order and active plugins.
|
||||
setLoadOrder(getInitialLoadOrder());
|
||||
|
||||
// Ghost a plugin.
|
||||
ASSERT_FALSE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost")));
|
||||
ASSERT_NO_THROW(boost::filesystem::rename(dataPath / blankMasterDependentEsm, dataPath / (blankMasterDependentEsm + ".ghost")));
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost")));
|
||||
}
|
||||
|
||||
void tearDown() {
|
||||
ASSERT_NO_THROW(boost::filesystem::remove_all(localPath));
|
||||
|
||||
ASSERT_NO_THROW(boost::filesystem::remove(dataPath / masterFile));
|
||||
|
||||
// Unghost the ghosted plugin.
|
||||
ASSERT_TRUE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost")));
|
||||
ASSERT_NO_THROW(boost::filesystem::rename(dataPath / (blankMasterDependentEsm + ".ghost"), dataPath / blankMasterDependentEsm));
|
||||
ASSERT_FALSE(boost::filesystem::exists(dataPath / (blankMasterDependentEsm + ".ghost")));
|
||||
}
|
||||
|
||||
std::vector<std::string> getLoadOrder() {
|
||||
std::vector<std::string> actual;
|
||||
if (isLoadOrderTimestampBased(gameType)) {
|
||||
std::map<time_t, std::string> loadOrder;
|
||||
for (boost::filesystem::directory_iterator it(dataPath); it != boost::filesystem::directory_iterator(); ++it) {
|
||||
if (boost::filesystem::is_regular_file(it->status())) {
|
||||
std::string filename = it->path().filename().string();
|
||||
if (boost::ends_with(filename, ".ghost"))
|
||||
filename = it->path().stem().string();
|
||||
if (boost::ends_with(filename, ".esp") || boost::ends_with(filename, ".esm"))
|
||||
loadOrder.emplace(boost::filesystem::last_write_time(it->path()), filename);
|
||||
}
|
||||
}
|
||||
for (const auto& plugin : loadOrder)
|
||||
actual.push_back(plugin.second);
|
||||
} else if (gameType == tes5) {
|
||||
boost::filesystem::ifstream in(localPath / "loadorder.txt");
|
||||
while (in) {
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
if (!line.empty())
|
||||
actual.push_back(line);
|
||||
}
|
||||
} else {
|
||||
boost::filesystem::ifstream in(localPath / "plugins.txt");
|
||||
while (in) {
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
if (!line.empty()) {
|
||||
if (line[0] == '*')
|
||||
line = line.substr(1);
|
||||
|
||||
actual.push_back(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
inline std::vector<std::pair<std::string, bool>> getInitialLoadOrder() const {
|
||||
return std::vector<std::pair<std::string, bool>>({
|
||||
{masterFile, true},
|
||||
{blankEsm, true},
|
||||
{blankDifferentEsm, false},
|
||||
{blankMasterDependentEsm, false},
|
||||
{blankDifferentMasterDependentEsm, false},
|
||||
{blankEsp, false},
|
||||
{blankDifferentEsp, false},
|
||||
{blankMasterDependentEsp, false},
|
||||
{blankDifferentMasterDependentEsp, true},
|
||||
{blankPluginDependentEsp, false},
|
||||
{blankDifferentPluginDependentEsp, false},
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
// This needs to be here to ensure the correct initialisation order.
|
||||
const unsigned int gameType;
|
||||
|
||||
protected:
|
||||
const boost::filesystem::path missingPath;
|
||||
const boost::filesystem::path dataPath;
|
||||
const boost::filesystem::path localPath;
|
||||
|
||||
const std::string masterFile;
|
||||
const std::string missingEsp;
|
||||
const std::string blankEsm;
|
||||
const std::string blankDifferentEsm;
|
||||
const std::string blankMasterDependentEsm;
|
||||
const std::string blankDifferentMasterDependentEsm;
|
||||
const std::string blankEsp;
|
||||
const std::string blankDifferentEsp;
|
||||
const std::string blankMasterDependentEsp;
|
||||
const std::string blankDifferentMasterDependentEsp;
|
||||
const std::string blankPluginDependentEsp;
|
||||
const std::string blankDifferentPluginDependentEsp;
|
||||
|
||||
const uint32_t blankEsmCrc;
|
||||
|
||||
private:
|
||||
static const unsigned int tes4 = 1;
|
||||
static const unsigned int tes5 = 2;
|
||||
static const unsigned int fo3 = 3;
|
||||
static const unsigned int fonv = 4;
|
||||
static const unsigned int fo4 = 5;
|
||||
|
||||
inline boost::filesystem::path getLocalPath() const {
|
||||
if (gameType == tes4)
|
||||
return "./local/Oblivion";
|
||||
else
|
||||
return "./local/Skyrim";
|
||||
}
|
||||
|
||||
inline boost::filesystem::path getPluginsPath() const {
|
||||
if (gameType == tes4)
|
||||
return "./Oblivion/Data";
|
||||
else
|
||||
return "./Skyrim/Data";
|
||||
}
|
||||
|
||||
inline std::string getMasterFile() const {
|
||||
if (gameType == tes4)
|
||||
return "Oblivion.esm";
|
||||
else if (gameType == tes5)
|
||||
return "Skyrim.esm";
|
||||
else if (gameType == fo3)
|
||||
return "Fallout3.esm";
|
||||
else if (gameType == fonv)
|
||||
return "FalloutNV.esm";
|
||||
else
|
||||
return "Fallout4.esm";
|
||||
}
|
||||
|
||||
inline uint32_t getBlankEsmCrc() const {
|
||||
if (gameType == tes4)
|
||||
return 0x374E2A6F;
|
||||
else
|
||||
return 0x187BE342;
|
||||
}
|
||||
|
||||
void setLoadOrder(const std::vector<std::pair<std::string, bool>>& loadOrder) const {
|
||||
boost::filesystem::ofstream out(localPath / "plugins.txt");
|
||||
for (const auto &plugin : loadOrder) {
|
||||
if (gameType == fo4 && plugin.second)
|
||||
out << '*';
|
||||
else if (gameType != fo4 && !plugin.second)
|
||||
continue;
|
||||
|
||||
out << plugin.first << std::endl;
|
||||
}
|
||||
|
||||
if (isLoadOrderTimestampBased(gameType)) {
|
||||
time_t modificationTime = time(NULL); // Current time.
|
||||
for (const auto &plugin : loadOrder) {
|
||||
if (boost::filesystem::exists(dataPath / boost::filesystem::path(plugin.first + ".ghost"))) {
|
||||
boost::filesystem::last_write_time(dataPath / boost::filesystem::path(plugin.first + ".ghost"), modificationTime);
|
||||
} else {
|
||||
boost::filesystem::last_write_time(dataPath / plugin.first, modificationTime);
|
||||
}
|
||||
modificationTime += 60;
|
||||
}
|
||||
} else if (gameType == tes5) {
|
||||
boost::filesystem::ofstream out(localPath / "loadorder.txt");
|
||||
for (const auto &plugin : loadOrder)
|
||||
out << plugin.first << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool isLoadOrderTimestampBased(unsigned int gameId) {
|
||||
return gameId == tes4 || gameId == fo3 || gameId == fonv;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_APPLY_LOAD_ORDER_TEST
|
||||
#define LOOT_TESTS_API_LOOT_APPLY_LOAD_ORDER_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_apply_load_order_test : public ApiGameOperationsTest {};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_apply_load_order_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_apply_load_order_test, shouldReturnAnInvalidArgsIfTheDbOrLoadOrderPointersAreNull) {
|
||||
const char * loadOrder[1] = {
|
||||
masterFile.c_str(),
|
||||
};
|
||||
size_t numPlugins = 0;
|
||||
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(NULL, loadOrder, numPlugins));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_apply_load_order(db_, NULL, numPlugins));
|
||||
}
|
||||
|
||||
TEST_P(loot_apply_load_order_test, shouldReturnOkIfLoadOrderGivenIsNotEmpty) {
|
||||
const char * loadOrder[11] = {
|
||||
masterFile.c_str(),
|
||||
blankEsm.c_str(),
|
||||
blankMasterDependentEsm.c_str(),
|
||||
blankDifferentEsm.c_str(),
|
||||
blankDifferentMasterDependentEsm.c_str(),
|
||||
blankMasterDependentEsp.c_str(),
|
||||
blankDifferentMasterDependentEsp.c_str(),
|
||||
blankEsp.c_str(),
|
||||
blankPluginDependentEsp.c_str(),
|
||||
blankDifferentEsp.c_str(),
|
||||
blankDifferentPluginDependentEsp.c_str(),
|
||||
};
|
||||
size_t numPlugins = 11;
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_apply_load_order(db_, loadOrder, numPlugins));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_CREATE_DB_TEST
|
||||
#define LOOT_TESTS_API_LOOT_CREATE_DB_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include "test/common_game_test_fixture.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_create_db_test :
|
||||
public ::testing::TestWithParam<unsigned int>,
|
||||
public CommonGameTestFixture {
|
||||
protected:
|
||||
loot_create_db_test() :
|
||||
CommonGameTestFixture(GetParam()),
|
||||
db_(nullptr) {}
|
||||
|
||||
void SetUp() {
|
||||
setUp();
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
tearDown();
|
||||
|
||||
ASSERT_NO_THROW(loot_destroy_db(db_));
|
||||
}
|
||||
|
||||
loot_db * db_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_create_db_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_create_db_test, shouldSucceedIfPassedValidParametersWithRelativePaths) {
|
||||
EXPECT_EQ(loot_ok, loot_create_db(&db_, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str()));
|
||||
EXPECT_NE(nullptr, db_);
|
||||
}
|
||||
|
||||
TEST_P(loot_create_db_test, shouldSucceedIfPassedValidParametersWithAbsolutePaths) {
|
||||
boost::filesystem::path game = boost::filesystem::current_path() / dataPath.parent_path();
|
||||
boost::filesystem::path local = boost::filesystem::current_path() / localPath;
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_create_db(&db_, GetParam(), game.string().c_str(), local.string().c_str()));
|
||||
EXPECT_NE(nullptr, db_);
|
||||
}
|
||||
|
||||
TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_create_db(NULL, GetParam(), dataPath.parent_path().string().c_str(), localPath.string().c_str()));
|
||||
}
|
||||
|
||||
TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedAnInvalidGameType) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db_, UINT_MAX, dataPath.parent_path().string().c_str(), localPath.string().c_str()));
|
||||
}
|
||||
|
||||
TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedAGamePathThatDoesNotExist) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db_, GetParam(), missingPath.string().c_str(), localPath.string().c_str()));
|
||||
}
|
||||
|
||||
TEST_P(loot_create_db_test, shouldReturnAnInvalidArgsErrorIfPassedALocalPathThatDoesNotExist) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_create_db(&db_, GetParam(), dataPath.parent_path().string().c_str(), missingPath.string().c_str()));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_P(loot_create_db_test, shouldReturnOkIfPassedANullLocalPathPointer) {
|
||||
EXPECT_EQ(loot_ok, loot_create_db(&db_, GetParam(), dataPath.parent_path().string().c_str(), NULL));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,327 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_DB_TEST
|
||||
#define LOOT_TESTS_API_LOOT_DB_TEST
|
||||
|
||||
#include "api/loot_db.h"
|
||||
|
||||
#include "tests/common_game_test_fixture.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_db_test :
|
||||
public ::testing::TestWithParam<unsigned int>,
|
||||
public CommonGameTestFixture {
|
||||
protected:
|
||||
loot_db_test() :
|
||||
CommonGameTestFixture(GetParam()),
|
||||
db_(nullptr) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
setUp();
|
||||
|
||||
db_ = new loot_db(static_cast<unsigned int>(GetParam()), dataPath.parent_path().string().c_str(), localPath.string().c_str());
|
||||
}
|
||||
|
||||
inline virtual void TearDown() {
|
||||
tearDown();
|
||||
|
||||
delete db_;
|
||||
}
|
||||
|
||||
loot_db * db_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_db_test,
|
||||
::testing::Values(
|
||||
static_cast<unsigned int>(GameType::tes4),
|
||||
static_cast<unsigned int>(GameType::tes5),
|
||||
static_cast<unsigned int>(GameType::fo3),
|
||||
static_cast<unsigned int>(GameType::fonv),
|
||||
static_cast<unsigned int>(GameType::fo4)));
|
||||
|
||||
TEST_P(loot_db_test, settingRevisionIdStringShouldCopyIt) {
|
||||
db_->setRevisionIdString("id");
|
||||
EXPECT_STREQ("id", db_->getRevisionIdString());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingRevisionDateStringShouldCopyIt) {
|
||||
db_->setRevisionDateString("date");
|
||||
EXPECT_STREQ("date", db_->getRevisionDateString());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingPluginNamesShouldCopyThem) {
|
||||
db_->setPluginNames(std::vector<PluginMetadata>({
|
||||
PluginMetadata("Blank.esm"),
|
||||
PluginMetadata("Blank.esp"),
|
||||
}));
|
||||
|
||||
EXPECT_EQ(2, db_->getPluginNames().size());
|
||||
EXPECT_STREQ("Blank.esm", db_->getPluginNames()[0]);
|
||||
EXPECT_STREQ("Blank.esp", db_->getPluginNames()[1]);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingPluginNamesTwiceShouldOverwriteTheFirstDataSet) {
|
||||
db_->setPluginNames(std::vector<PluginMetadata>({
|
||||
PluginMetadata("Blank.esm"),
|
||||
PluginMetadata("Blank.esp"),
|
||||
}));
|
||||
db_->setPluginNames(std::vector<PluginMetadata>({
|
||||
PluginMetadata("Blank - Different.esm"),
|
||||
PluginMetadata("Blank - Different.esp"),
|
||||
}));
|
||||
|
||||
EXPECT_EQ(2, db_->getPluginNames().size());
|
||||
EXPECT_STREQ("Blank - Different.esm", db_->getPluginNames()[0]);
|
||||
EXPECT_STREQ("Blank - Different.esp", db_->getPluginNames()[1]);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, addingNewBashTagsToTheMapShouldAppendThem) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
EXPECT_EQ(2, db_->getBashTagMap().size());
|
||||
EXPECT_STREQ("C.Climate", db_->getBashTagMap()[0]);
|
||||
EXPECT_STREQ("Relev", db_->getBashTagMap()[1]);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, addingAnExistingBashTagToTheMapShouldNotDuplicateIt) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
"C.Climate",
|
||||
});
|
||||
|
||||
EXPECT_EQ(2, db_->getBashTagMap().size());
|
||||
EXPECT_STREQ("C.Climate", db_->getBashTagMap()[0]);
|
||||
EXPECT_STREQ("Relev", db_->getBashTagMap()[1]);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, gettingABashTagsUidForATagThatIsNotInTheMapShouldThrow) {
|
||||
EXPECT_ANY_THROW(db_->getBashTagUid("Relev"));
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, gettingABashTagsUidShouldReturnItsTagMapIndex) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
EXPECT_EQ(1, db_->getBashTagUid("Relev"));
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, clearingAnEmptyBashTagMapShouldDoNothing) {
|
||||
EXPECT_NO_THROW(db_->clearBashTagMap());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, clearingABashTagMapShouldEmptyIt) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->clearBashTagMap();
|
||||
EXPECT_TRUE(db_->getBashTagMap().empty());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, clearingABashTagMapShouldAffectExistingReferences) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
auto& bashTagMap = db_->getBashTagMap();
|
||||
db_->clearBashTagMap();
|
||||
EXPECT_TRUE(bashTagMap.empty());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingAddedTagsWithNoTagMapShouldThrow) {
|
||||
EXPECT_ANY_THROW(db_->setAddedTags({
|
||||
"Relev",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, gettingSetAddedTagsShouldReturnTheirUids) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setAddedTags({
|
||||
"Relev",
|
||||
});
|
||||
|
||||
EXPECT_EQ(std::vector<unsigned int>({
|
||||
1,
|
||||
}), db_->getAddedTagIds());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingAddedTagsShouldReplaceExistingTags) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setAddedTags({
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setAddedTags({
|
||||
"C.Climate",
|
||||
});
|
||||
|
||||
EXPECT_EQ(std::vector<unsigned int>({
|
||||
0,
|
||||
}), db_->getAddedTagIds());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingRemovedTagsWithNoTagMapShouldThrow) {
|
||||
EXPECT_ANY_THROW(db_->setRemovedTags({
|
||||
"Relev",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, gettingSetRemovedTagsShouldReturnTheirUids) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setRemovedTags({
|
||||
"Relev",
|
||||
});
|
||||
|
||||
EXPECT_EQ(std::vector<unsigned int>({
|
||||
1,
|
||||
}), db_->getRemovedTagIds());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingRemovedTagsShouldReplaceExistingTags) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setRemovedTags({
|
||||
"Relev",
|
||||
});
|
||||
|
||||
db_->setRemovedTags({
|
||||
"C.Climate",
|
||||
});
|
||||
|
||||
EXPECT_EQ(std::vector<unsigned int>({
|
||||
0,
|
||||
}), db_->getRemovedTagIds());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingPluginMessagesShouldCopyThem) {
|
||||
db_->setPluginMessages(std::list<Message>({
|
||||
Message(Message::Type::warn, "Test 1"),
|
||||
Message(Message::Type::error, "Test 2"),
|
||||
}));
|
||||
|
||||
EXPECT_EQ(2, db_->getPluginMessages().size());
|
||||
EXPECT_EQ(static_cast<unsigned int>(Message::Type::warn), db_->getPluginMessages()[0].type);
|
||||
EXPECT_STREQ("Test 1", db_->getPluginMessages()[0].message);
|
||||
EXPECT_EQ(static_cast<unsigned int>(Message::Type::error), db_->getPluginMessages()[1].type);
|
||||
EXPECT_STREQ("Test 2", db_->getPluginMessages()[1].message);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, settingPluginMessagesTwiceShouldOverwriteTheFirstDataSet) {
|
||||
db_->setPluginMessages(std::list<Message>({
|
||||
Message(Message::Type::warn, "Test 1"),
|
||||
Message(Message::Type::error, "Test 2"),
|
||||
}));
|
||||
db_->setPluginMessages(std::list<Message>({
|
||||
Message(Message::Type::error, "Test 3"),
|
||||
Message(Message::Type::warn, "Test 4"),
|
||||
Message(Message::Type::say, "Test 5"),
|
||||
}));
|
||||
|
||||
EXPECT_EQ(3, db_->getPluginMessages().size());
|
||||
EXPECT_EQ(static_cast<unsigned int>(Message::Type::error), db_->getPluginMessages()[0].type);
|
||||
EXPECT_STREQ("Test 3", db_->getPluginMessages()[0].message);
|
||||
EXPECT_EQ(static_cast<unsigned int>(Message::Type::warn), db_->getPluginMessages()[1].type);
|
||||
EXPECT_STREQ("Test 4", db_->getPluginMessages()[1].message);
|
||||
EXPECT_EQ(static_cast<unsigned int>(Message::Type::say), db_->getPluginMessages()[2].type);
|
||||
EXPECT_STREQ("Test 5", db_->getPluginMessages()[2].message);
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, clearingArraysShouldEmptyPluginNamesTagIdsAndMessages) {
|
||||
db_->setPluginMessages(std::list<Message>({
|
||||
Message(Message::Type::warn, "Test 1"),
|
||||
Message(Message::Type::error, "Test 2"),
|
||||
}));
|
||||
db_->setPluginNames(std::vector<PluginMetadata>({
|
||||
PluginMetadata("Blank.esm"),
|
||||
PluginMetadata("Blank.esp"),
|
||||
}));
|
||||
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
db_->setAddedTags({
|
||||
"Relev",
|
||||
});
|
||||
db_->setRemovedTags({
|
||||
"Relev",
|
||||
});
|
||||
|
||||
ASSERT_FALSE(db_->getPluginMessages().empty());
|
||||
ASSERT_FALSE(db_->getPluginNames().empty());
|
||||
ASSERT_FALSE(db_->getAddedTagIds().empty());
|
||||
ASSERT_FALSE(db_->getRemovedTagIds().empty());
|
||||
ASSERT_FALSE(db_->getBashTagMap().empty());
|
||||
|
||||
EXPECT_NO_THROW(db_->clearArrays());
|
||||
|
||||
EXPECT_TRUE(db_->getPluginMessages().empty());
|
||||
EXPECT_TRUE(db_->getPluginNames().empty());
|
||||
EXPECT_TRUE(db_->getAddedTagIds().empty());
|
||||
EXPECT_TRUE(db_->getRemovedTagIds().empty());
|
||||
}
|
||||
|
||||
TEST_P(loot_db_test, clearingArraysShouldNotEmptyBashTagMap) {
|
||||
db_->addBashTagsToMap({
|
||||
"C.Climate",
|
||||
"Relev",
|
||||
});
|
||||
ASSERT_FALSE(db_->getBashTagMap().empty());
|
||||
|
||||
EXPECT_NO_THROW(db_->clearArrays());
|
||||
|
||||
EXPECT_FALSE(db_->getBashTagMap().empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_EVAL_LISTS_TEST
|
||||
#define LOOT_TESTS_API_LOOT_EVAL_LISTS_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_eval_lists_test : public ApiGameOperationsTest {};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_eval_lists_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_eval_lists_test, shouldReturnAnInvalidArgsErrorIfPassedANullPointer) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(NULL, loot_lang_english));
|
||||
}
|
||||
|
||||
TEST_P(loot_eval_lists_test, shouldReturnAnInvalidArgsErrorIfPassedAnInvalidLanguageCode) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_eval_lists(db_, UINT_MAX));
|
||||
}
|
||||
|
||||
TEST_P(loot_eval_lists_test, shouldReturnOkForAllLanguagesWithNoListsLoaded) {
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_english));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_english));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_spanish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_russian));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_french));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_chinese));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_polish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_brazilian_portuguese));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_finnish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_german));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_danish));
|
||||
}
|
||||
|
||||
TEST_P(loot_eval_lists_test, shouldReturnOKForAllLanguagesWithAMasterlistLoaded) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_english));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_english));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_spanish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_russian));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_french));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_chinese));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_polish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_brazilian_portuguese));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_finnish));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_german));
|
||||
EXPECT_EQ(loot_ok, loot_eval_lists(db_, loot_lang_danish));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TEST_API_LOOT_GET_DIRTY_INFO_TEST
|
||||
#define LOOT_TEST_API_LOOT_GET_DIRTY_INFO_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_get_dirty_info_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_get_dirty_info_test() :
|
||||
needsCleaning_(0) {}
|
||||
|
||||
unsigned int needsCleaning_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_get_dirty_info_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_get_dirty_info_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(NULL, blankEsp.c_str(), &needsCleaning_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db_, NULL, &needsCleaning_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_dirty_info(db_, blankEsp.c_str(), NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputUnknownForAPluginWithNoDirtyInfo) {
|
||||
EXPECT_EQ(loot_ok, loot_get_dirty_info(db_, blankEsp.c_str(), &needsCleaning_));
|
||||
EXPECT_EQ(loot_cleanliness_unknown, needsCleaning_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputDirtyForAPluginWithDirtyInfo) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_dirty_info(db_, blankDifferentEsm.c_str(), &needsCleaning_));
|
||||
EXPECT_EQ(loot_cleanliness_dirty, needsCleaning_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_dirty_info_test, shouldReturnOkAndOutputDoNotCleanForAPluginWithADoNotCleanMessage) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_dirty_info(db_, blankEsm.c_str(), &needsCleaning_));
|
||||
EXPECT_EQ(loot_cleanliness_do_not_clean, needsCleaning_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_GET_MASTERLIST_REVISION_TEST
|
||||
#define LOOT_TESTS_API_LOOT_GET_MASTERLIST_REVISION_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_get_masterlist_revision_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_get_masterlist_revision_test() :
|
||||
url_("https://github.com/loot/testing-metadata.git"),
|
||||
branch_("2.x"),
|
||||
revisionId_("foo"),
|
||||
revisionDate_("bar"),
|
||||
isModified_(true),
|
||||
updated_(false) {}
|
||||
|
||||
const std::string url_;
|
||||
const std::string branch_;
|
||||
const char * revisionId_;
|
||||
const char * revisionDate_;
|
||||
bool isModified_;
|
||||
bool updated_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_get_masterlist_revision_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(NULL, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db_, NULL, false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, NULL, &revisionDate_, &isModified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, NULL, &isModified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfNoMasterlistIsPresent) {
|
||||
EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_EQ(NULL, revisionId_);
|
||||
EXPECT_EQ(NULL, revisionDate_);
|
||||
EXPECT_FALSE(isModified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfANonVersionControlledMasterlistIsPresent) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_EQ(NULL, revisionId_);
|
||||
EXPECT_EQ(NULL, revisionDate_);
|
||||
EXPECT_FALSE(isModified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldOutputLongStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsFalse) {
|
||||
ASSERT_EQ(loot_ok, loot_update_masterlist(db_, masterlistPath.string().c_str(), url_.c_str(), branch_.c_str(), &updated_));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_STRNE(NULL, revisionId_);
|
||||
EXPECT_EQ(40, strlen(revisionId_));
|
||||
EXPECT_STRNE(NULL, revisionDate_);
|
||||
EXPECT_EQ(10, strlen(revisionDate_));
|
||||
EXPECT_FALSE(isModified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldOutputShortStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsTrue) {
|
||||
ASSERT_EQ(loot_ok, loot_update_masterlist(db_, masterlistPath.string().c_str(), url_.c_str(), branch_.c_str(), &updated_));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
EXPECT_STRNE(NULL, revisionId_);
|
||||
EXPECT_GE(size_t(40), strlen(revisionId_));
|
||||
EXPECT_LE(size_t(7), strlen(revisionId_));
|
||||
EXPECT_STRNE(NULL, revisionDate_);
|
||||
EXPECT_EQ(10, strlen(revisionDate_));
|
||||
EXPECT_FALSE(isModified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_masterlist_revision_test, shouldSucceedIfAnEditedVersionControlledMasterlistIsPresent) {
|
||||
ASSERT_EQ(loot_ok, loot_update_masterlist(db_, masterlistPath.string().c_str(), url_.c_str(), branch_.c_str(), &updated_));
|
||||
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
EXPECT_EQ(loot_ok, loot_get_masterlist_revision(db_, masterlistPath.string().c_str(), false, &revisionId_, &revisionDate_, &isModified_));
|
||||
|
||||
EXPECT_STRNE(NULL, revisionId_);
|
||||
EXPECT_EQ(40, strlen(revisionId_));
|
||||
EXPECT_STRNE(NULL, revisionDate_);
|
||||
EXPECT_EQ(10, strlen(revisionDate_));
|
||||
EXPECT_TRUE(isModified_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_GET_PLUGIN_MESSAGES_TEST
|
||||
#define LOOT_TESTS_API_LOOT_GET_PLUGIN_MESSAGES_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_get_plugin_messages_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_get_plugin_messages_test() :
|
||||
messages_(nullptr),
|
||||
numMessages_(0) {}
|
||||
|
||||
const loot_message * messages_;
|
||||
size_t numMessages_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_get_plugin_messages_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(NULL, blankEsp.c_str(), &messages_, &numMessages_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db_, NULL, &messages_, &numMessages_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db_, blankEsp.c_str(), NULL, &numMessages_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_messages(db_, blankEsp.c_str(), &messages_, NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputANullArrayIfAPluginWithNoMessagesIsQueried) {
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_messages(db_, blankEsp.c_str(), &messages_, &numMessages_));
|
||||
EXPECT_EQ(0, numMessages_);
|
||||
EXPECT_EQ(NULL, messages_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputANoteIfAPluginWithANoteMessageIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_messages(db_, blankEsm.c_str(), &messages_, &numMessages_));
|
||||
ASSERT_EQ(1, numMessages_);
|
||||
EXPECT_EQ(loot_message_say, messages_[0].type);
|
||||
EXPECT_STREQ(noteMessage.c_str(), messages_[0].message);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputAWarningIfAPluginWithAWarningMessageIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_messages(db_, blankDifferentEsm.c_str(), &messages_, &numMessages_));
|
||||
ASSERT_EQ(1, numMessages_);
|
||||
EXPECT_EQ(loot_message_warn, messages_[0].type);
|
||||
EXPECT_STREQ(warningMessage.c_str(), messages_[0].message);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputAnErrorIfAPluginWithAnErrorMessageIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_messages(db_, blankDifferentEsp.c_str(), &messages_, &numMessages_));
|
||||
ASSERT_EQ(1, numMessages_);
|
||||
EXPECT_EQ(loot_message_error, messages_[0].type);
|
||||
EXPECT_STREQ(errorMessage.c_str(), messages_[0].message);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_messages_test, shouldReturnOkAndOutputMultipleMessagesIfAPluginWithMultipleMessagesIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_messages(db_, blankDifferentMasterDependentEsp.c_str(), &messages_, &numMessages_));
|
||||
ASSERT_EQ(3, numMessages_);
|
||||
EXPECT_EQ(loot_message_say, messages_[0].type);
|
||||
EXPECT_STREQ(noteMessage.c_str(), messages_[0].message);
|
||||
EXPECT_EQ(loot_message_warn, messages_[1].type);
|
||||
EXPECT_STREQ(warningMessage.c_str(), messages_[1].message);
|
||||
EXPECT_EQ(loot_message_error, messages_[2].type);
|
||||
EXPECT_STREQ(errorMessage.c_str(), messages_[2].message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_GET_PLUGIN_TAGS_TEST
|
||||
#define LOOT_TESTS_API_LOOT_GET_PLUGIN_TAGS_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_get_plugin_tags_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_get_plugin_tags_test() :
|
||||
added_(nullptr),
|
||||
removed_(nullptr),
|
||||
numAdded_(0),
|
||||
numRemoved_(0),
|
||||
modified_(false) {}
|
||||
|
||||
const char * const * added_;
|
||||
const char * const * removed_;
|
||||
size_t numAdded_;
|
||||
size_t numRemoved_;
|
||||
bool modified_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_get_plugin_tags_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_get_plugin_tags_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(NULL, blankEsm.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, NULL, &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, blankEsm.c_str(), NULL, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, NULL, &removed_, &numRemoved_, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, NULL, &numRemoved_, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, &removed_, NULL, &modified_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndOutputEmptyNonModifiedArraysIfAPluginWithoutTagsIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_tags(db_, blankEsp.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
|
||||
EXPECT_EQ(0, numAdded_);
|
||||
EXPECT_EQ(NULL, added_);
|
||||
EXPECT_EQ(0, numRemoved_);
|
||||
EXPECT_EQ(NULL, removed_);
|
||||
EXPECT_FALSE(modified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndNonEmptyNonModifiedArraysIfAPluginWithTagsIsQueried) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
|
||||
// The values are tag map indices, check they match up as expected.
|
||||
ASSERT_EQ(2, numAdded_);
|
||||
EXPECT_STREQ("Actors.ACBS", added_[0]);
|
||||
EXPECT_STREQ("Actors.AIData", added_[1]);
|
||||
|
||||
ASSERT_EQ(1, numRemoved_);
|
||||
EXPECT_STREQ("C.Water", removed_[0]);
|
||||
|
||||
EXPECT_FALSE(modified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_tags_test, shouldReturnOkAndNonEmptyModifiedArraysIfAPluginWithTagsIsQueriedAndMetadataWasAlsoLoadedFromAUserlist) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), masterlistPath.string().c_str()));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
|
||||
// The values are tag map indices, check they match up as expected.
|
||||
ASSERT_EQ(2, numAdded_);
|
||||
EXPECT_STREQ("Actors.ACBS", added_[0]);
|
||||
EXPECT_STREQ("Actors.AIData", added_[1]);
|
||||
|
||||
ASSERT_EQ(1, numRemoved_);
|
||||
EXPECT_STREQ("C.Water", removed_[0]);
|
||||
|
||||
EXPECT_TRUE(modified_);
|
||||
}
|
||||
|
||||
TEST_P(loot_get_plugin_tags_test, shouldOutputTheCorrectBashTagsForPluginsWhenMakingConsecutiveCalls) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_tags(db_, blankEsm.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
|
||||
ASSERT_EQ(2, numAdded_);
|
||||
EXPECT_STREQ("Actors.ACBS", added_[0]);
|
||||
EXPECT_STREQ("Actors.AIData", added_[1]);
|
||||
|
||||
ASSERT_EQ(1, numRemoved_);
|
||||
EXPECT_STREQ("C.Water", removed_[0]);
|
||||
EXPECT_FALSE(modified_);
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_get_plugin_tags(db_, blankEsp.c_str(), &added_, &numAdded_, &removed_, &numRemoved_, &modified_));
|
||||
|
||||
EXPECT_EQ(0, numAdded_);
|
||||
EXPECT_EQ(NULL, added_);
|
||||
EXPECT_EQ(0, numRemoved_);
|
||||
EXPECT_EQ(NULL, removed_);
|
||||
EXPECT_FALSE(modified_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_LOAD_LISTS_TEST
|
||||
#define LOOT_TESTS_API_LOOT_LOAD_LISTS_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_load_lists_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_load_lists_test() :
|
||||
userlistPath(localPath / "userlist.yaml") {}
|
||||
|
||||
inline virtual void TearDown() {
|
||||
ApiGameOperationsTest::TearDown();
|
||||
|
||||
// The userlist may have been created during the test, so delete it.
|
||||
ASSERT_NO_THROW(boost::filesystem::remove(userlistPath));
|
||||
}
|
||||
|
||||
const boost::filesystem::path userlistPath;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_load_lists_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_load_lists_test, shouldReturnAnInvalidArgsErrorIfTheDbOrMasterlistPathArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_load_lists(NULL, masterlistPath.string().c_str(), NULL));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_load_lists(db_, NULL, NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_load_lists_test, shouldReturnAPathNotFoundErrorIfNoMasterlistIsPresent) {
|
||||
EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_load_lists_test, shouldReturnAPathNotFoundErrorIfAMasterlistIsPresentButAUserlistDoesNotExistAtTheGivenPath) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
EXPECT_EQ(loot_error_path_not_found, loot_load_lists(db_, masterlistPath.string().c_str(), userlistPath.string().c_str()));
|
||||
}
|
||||
|
||||
TEST_P(loot_load_lists_test, shouldReturnOkIfTheMasterlistAndUserlistAreBothPresent) {
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_NO_THROW(boost::filesystem::copy(masterlistPath, userlistPath));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), userlistPath.string().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TESTS_API_LOOT_SORT_PLUGINS_TEST
|
||||
#define LOOT_TESTS_API_LOOT_SORT_PLUGINS_TEST
|
||||
|
||||
#include "loot/c_api.h"
|
||||
|
||||
#include "test/api_game_operations_test.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class loot_sort_plugins_test : public ApiGameOperationsTest {
|
||||
protected:
|
||||
loot_sort_plugins_test() :
|
||||
sortedPlugins_(nullptr),
|
||||
numPlugins_(0) {}
|
||||
|
||||
const char * const * sortedPlugins_;
|
||||
size_t numPlugins_;
|
||||
};
|
||||
|
||||
// Pass an empty first argument, as it's a prefix for the test instantation,
|
||||
// but we only have the one so no prefix is necessary.
|
||||
INSTANTIATE_TEST_CASE_P(,
|
||||
loot_sort_plugins_test,
|
||||
::testing::Values(
|
||||
loot_game_tes4,
|
||||
loot_game_tes5,
|
||||
loot_game_fo3,
|
||||
loot_game_fonv,
|
||||
loot_game_fo4));
|
||||
|
||||
TEST_P(loot_sort_plugins_test, shouldReturnAnInvalidArgsErrorIfAnyOfTheArgumentsAreNull) {
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(NULL, &sortedPlugins_, &numPlugins_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db_, NULL, &numPlugins_));
|
||||
EXPECT_EQ(loot_error_invalid_args, loot_sort_plugins(db_, &sortedPlugins_, NULL));
|
||||
}
|
||||
|
||||
TEST_P(loot_sort_plugins_test, shouldSucceedIfPassedValidArguments) {
|
||||
std::list<std::string> expectedOrder = {
|
||||
masterFile,
|
||||
blankEsm,
|
||||
blankMasterDependentEsm,
|
||||
blankDifferentEsm,
|
||||
blankDifferentMasterDependentEsm,
|
||||
blankMasterDependentEsp,
|
||||
blankDifferentMasterDependentEsp,
|
||||
blankEsp,
|
||||
blankPluginDependentEsp,
|
||||
blankDifferentEsp,
|
||||
blankDifferentPluginDependentEsp,
|
||||
};
|
||||
|
||||
ASSERT_NO_THROW(GenerateMasterlist());
|
||||
ASSERT_EQ(loot_ok, loot_load_lists(db_, masterlistPath.string().c_str(), NULL));
|
||||
|
||||
EXPECT_EQ(loot_ok, loot_sort_plugins(db_, &sortedPlugins_, &numPlugins_));
|
||||
|
||||
ASSERT_EQ(expectedOrder.size(), numPlugins_);
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto& plugin : expectedOrder) {
|
||||
EXPECT_EQ(plugin, sortedPlugins_[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user