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:
Oliver Hamlet
2016-08-14 21:50:49 +01:00
parent 344e4bf00f
commit d1cecd9647
24 changed files with 3630 additions and 0 deletions
+6
View File
@@ -77,3 +77,9 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
# =========================
# Other
# =========================
build/
+209
View File
@@ -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>)
+16
View File
@@ -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
+458
View File
@@ -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;
}
+126
View File
@@ -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();
}
+81
View File
@@ -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
+27
View File
@@ -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"
+123
View File
@@ -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
+259
View File
@@ -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
+78
View File
@@ -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
+105
View File
@@ -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
+327
View File
@@ -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
+88
View File
@@ -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
+82
View File
@@ -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
+114
View File
@@ -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
+143
View File
@@ -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
+83
View File
@@ -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
+92
View File
@@ -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