Turn the C API into a C++ API

This commit is contained in:
Oliver Hamlet
2016-08-24 08:08:04 +01:00
parent 05059d36af
commit 1256853bad
32 changed files with 1478 additions and 3115 deletions
+17 -19
View File
@@ -224,21 +224,29 @@ set (LOOT_GUI_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/loot_handler.h"
"${CMAKE_SOURCE_DIR}/src/gui/query_handler.h"
"${CMAKE_SOURCE_DIR}/src/gui/resource.h")
set (LOOT_API_SRC "${CMAKE_SOURCE_DIR}/src/api/api.cpp"
"${CMAKE_SOURCE_DIR}/src/api/loot_db.cpp")
set (LOOT_API_SRC "${CMAKE_BINARY_DIR}/generated/loot_version.cpp"
"${CMAKE_SOURCE_DIR}/src/api/api.cpp"
"${CMAKE_SOURCE_DIR}/src/api/api_database.cpp")
set (LOOT_API_HEADERS "${CMAKE_SOURCE_DIR}/include/loot/api.h"
"${CMAKE_SOURCE_DIR}/src/api/loot_db.h")
"${CMAKE_SOURCE_DIR}/include/loot/database_interface.h"
"${CMAKE_SOURCE_DIR}/include/loot/game_type.h"
"${CMAKE_SOURCE_DIR}/include/loot/language_code.h"
"${CMAKE_SOURCE_DIR}/include/loot/loot_version.h"
"${CMAKE_SOURCE_DIR}/include/loot/masterlist_info.h"
"${CMAKE_SOURCE_DIR}/include/loot/message_type.h"
"${CMAKE_SOURCE_DIR}/include/loot/plugin_cleanliness.h"
"${CMAKE_SOURCE_DIR}/include/loot/plugin_message.h"
"${CMAKE_SOURCE_DIR}/include/loot/plugin_tags.h"
"${CMAKE_SOURCE_DIR}/src/api/api_database.h")
set (LOOT_VALIDATOR_SRC "${CMAKE_SOURCE_DIR}/src/validator/main.cpp")
set (LOOT_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/api/loot_db.cpp"
"${CMAKE_SOURCE_DIR}/src/tests/backend/main.cpp")
set (LOOT_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/tests/backend/main.cpp")
set (LOOT_TESTS_HEADERS # Testing this here rather than as part of the API tests
# because it tests internal code and requires internal
# linking.
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_db_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/backend/app/loot_paths_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/backend/app/loot_settings_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/backend/app/loot_state_test.h"
@@ -272,19 +280,9 @@ set (LOOT_TESTS_HEADERS # Testing this here rather than as part of the API tests
set(LOOT_API_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/tests/api/main.cpp")
set(LOOT_API_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/api/api_game_operations_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_apply_load_order_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_create_db_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_eval_lists_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_dirty_info_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_masterlist_revision_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_plugin_messages_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_plugin_tags_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_get_tag_map_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_load_lists_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_sort_plugins_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_update_masterlist_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/loot_write_minimal_list_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/test_api.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/create_database_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/database_interface_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/api/is_compatible_test.h"
"${CMAKE_SOURCE_DIR}/src/tests/common_game_test_fixture.h")
source_group("Header Files\\backend" FILES ${LOOT_HEADERS})
+58 -529
View File
File diff suppressed because it is too large Load Diff
+270
View File
@@ -0,0 +1,270 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-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_DATABASE_INTERFACE
#define LOOT_DATABASE_INTERFACE
#include <string>
#include <vector>
#include "loot/language_code.h"
#include "loot/masterlist_info.h"
#include "loot/plugin_cleanliness.h"
#include "loot/plugin_message.h"
#include "loot/plugin_tags.h"
namespace loot {
class DatabaseInterface {
public:
/**********************************************************************//**
* @name Database Loading Functions
*************************************************************************/
/**@{*/
/**
* @brief Loads the masterlist and userlist from the paths specified.
* @details Can be called multiple times, each time replacing the
* previously-loaded data.
* @param masterlist_path
* A string containing the relative or absolute path to the masterlist
* file that should be loaded.
* @param userlist_path
* A string containing the relative or absolute path to the userlist
* file that should be loaded, or `NULL`. If `NULL`, no userlist will
* be loaded.
*/
virtual void LoadLists(const std::string& masterlist_path,
const std::string& userlist_path) = 0;
/**
* @brief Evaluates all conditions and regular expression metadata
* entries.
* @details Repeated calls re-evaluate the metadata from scratch. This
* function affects the output of all the database access
* functions.
* @param language
* The language code that is used for message language comparisons.
*/
virtual void EvalLists(const LanguageCode language) = 0;
/**********************************************************************//**
* @name LOOT Functionality Functions
*************************************************************************/
/**@{*/
/**
* @brief Calculates a new load order for the game's installed plugins
* (including inactive plugins) and outputs the sorted order.
* @details Pulls metadata from the masterlist and userlist if they are
* loaded, and reads the contents of each plugin. No changes are
* applied to the load order used by the game. This function does
* not load or evaluate the masterlist or userlist.
* @param db
* The database the function acts on.
* @param sortedPlugins
* A pointer to an array of plugin filenames in their sorted load
* order.
* @param numPlugins
* A pointer to the size of the outputted array.
* @returns A return code.
*/
virtual std::vector<std::string> SortPlugins() = 0;
/**
* @brief Applies the given load order.
* @param db
* The database the function acts on.
* @param loadOrder
* An array of plugin filenames in the load order to be set.
* @param numPlugins
* The size of the inputted array.
* @returns A return code.
*/
virtual void ApplyLoadOrder(const std::vector<std::string>& loadOrder) = 0;
/**
* @brief Update the given masterlist.
* @details Uses Git to update the given masterlist to a given remote.
* If the masterlist doesn't exist, this will create it. This
* function also initialises a Git repository in the given
* masterlist's parent folder. If the masterlist was not already
* up-to-date, it will be re-loaded, but not re-evaluated.
*
* If a Git repository is already present, it will be used to
* perform a diff-only update, but if for any reason a
* fast-forward merge update is not possible, the existing
* repository will be deleted and a new repository cloned from
* the given remote.
* @param db
* The database the function acts on.
* @param masterlistPath
* A string containing the relative or absolute path to the masterlist
* file that should be updated. The filename must match the filename
* of the masterlist file in the given remote repository, otherwise it
* will not be updated correctly. Although LOOT itself expects this
* filename to be "masterlist.yaml", the API does not check for any
* specific filename.
* @param remoteURL
* The URL of the remote from which to fetch updates. This can also be
* a relative or absolute path to a local repository.
* @param remoteBranch
* The branch of the remote from which to apply updates. LOOT's
* official masterlists are versioned using separate branches for each
* new version of the masterlist syntax, so if you're using them,
* check their repositories to see which is the latest release branch.
* @param updated
* `true` if the masterlist was updated. `false` if no update was
* necessary, ie. it was already up-to-date. If `true`, the masterlist
* will have been re-loaded, but will need to be re-evaluated
* separately.
* @returns A return code.
*/
virtual bool UpdateMasterlist(const std::string& masterlist_path,
const std::string& remote_url,
const std::string& remote_branch) = 0;
/**
* @brief Get the given masterlist's revision.
* @details Getting a masterlist's revision is only possible if it is
* found inside a local Git repository.
* @param db
* The database the function acts on.
* @param masterlistPath
* A string containing the relative or absolute path to the masterlist
* file that should be queried.
* @param getShortID
* If `true`, the shortest unique hexadecimal revision hash that is at
* least 7 characters long will be outputted. Otherwise, the full 40
* character hash will be outputted.
* @param revisionID
* A pointer to a string containing the outputted revision hash for
* the masterlist. If the masterlist doesn't exist, or there is no Git
* repository at its location, this will be `NULL`.
* @param revisionDate
* A pointer to a string containing the ISO 8601 formatted revision
* date, ie. YYYY-MM-DD. If the masterlist doesn't exist, or there is
* no Git repository at its location, this will be `NULL`.
* @param isModified
* A pointer to a boolean that is `true` if the masterlist has been
* edited since the outputted revision, or `false` if it is at exactly
* the revision given.
* @returns A return code.
*/
virtual MasterlistInfo GetMasterlistRevision(const std::string& masterlist_path,
const bool get_short_id) = 0;
/**@}*/
/**********************************************************************//**
* @name Database Access Functions
*************************************************************************/
/**@{*/
/**
* @brief Outputs the Bash Tags suggested for addition and removal by the
* database for the given plugin.
* @details loot_get_tag_map() must be called before this to ensure that
* the Bash Tag UIDs outputted by this function can be matched up
* to name strings.
* @param db
* The database the function acts on.
* @param plugin
* The filename of the plugin to look up Bash Tag suggestions for.
* @param tags_added
* A pointer to the outputted array of UIDs of the Bash Tags suggested
* for addition to the specified plugin. `NULL` if no Bash Tag
* additions are suggested.
* @param numTags_added
* A pointer to the size of the tags_added array. `0` if `tags_added`
* is `NULL`.
* @param tags_removed
* A pointer to the outputted array of UIDs of the Bash Tags suggested
* for removal from the specified plugin. `NULL` if no Bash Tag
* removals are suggested.
* @param numTags_removed
* A pointer to the size of the `tags_removed` array. `0` if
* `tags_removed` is `null`.
* @param userlistModified
* `true` if the Bash Tag suggestions were modified by the data in the
* userlist, `false` otherwise.
* @returns A return code.
*/
virtual PluginTags GetPluginTags(const std::string& plugin) = 0;
/**
* @brief Outputs the messages associated with the given plugin in the
* database.
* @param db
* The database the function acts on.
* @param plugin
* The filename of the plugin to look up messages for.
* @param messages
* A pointer to the outputted array of messages associated with the
* specified plugin, given as loot_message structures. `NULL` if the
* plugin has no messages associated with it.
* @param numMessages
* A pointer to the size of the outputted array. If no messages are
* outputted, this will be `0`.
* @returns A return code.
*/
virtual std::vector<PluginMessage> GetPluginMessages(const std::string& plugin) = 0;
/**
* @brief Determines the database's knowledge of a plugin's dirtiness.
* @details Outputs whether the plugin should be cleaned or not, or if
* no data is available. The mechanism used to determine that
* a plugin should not be cleaned is not very reliable, and is
* likely to fail if `loot_eval_lists()` was called with a
* language other than English. As such, some plugins that should
* not be cleaned may have the `loot_needs_cleaning_unknown`
* code outputted.
* @param db
* The database the function acts on.
* @param plugin
* The plugin to look up dirty status information for.
* @param needsCleaning
* A pointer to a plugin cleanliness code.
* @returns A return code.
*/
virtual PluginCleanliness GetPluginCleanliness(const std::string& plugin) = 0;
/**
* @brief Writes a minimal metadata file that only contains plugins with
* Bash Tag suggestions and/or dirty info, plus the suggestions and
* info themselves.
* @param db
* The database the function acts on.
* @param outputFile
* The path to which the file shall be written.
* @param overwrite
* If `false` and `outputFile` already exists, no data will be
* written. Otherwise, data will be written.
* @returns A return code.
*/
virtual void WriteMinimalList(const std::string& outputFile,
const bool overwrite) = 0;
/**@}*/
};
}
#endif
+37
View File
@@ -0,0 +1,37 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-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_MASTERLIST_INFO
#define LOOT_MASTERLIST_INFO
#include <string>
namespace loot {
struct MasterlistInfo {
std::string revision_id;
std::string revision_date;
bool is_modified;
};
}
#endif
+36
View File
@@ -0,0 +1,36 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-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_PLUGIN_CLEANLINESS
#define LOOT_PLUGIN_CLEANLINESS
namespace loot {
enum struct PluginCleanliness : unsigned int {
clean,
dirty,
do_not_clean,
unknown,
};
}
#endif
+50
View File
@@ -0,0 +1,50 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-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_PLUGIN_MESSAGE
#define LOOT_PLUGIN_MESSAGE
#include "loot/message_type.h"
namespace loot {
/**
* @brief A structure that holds the type of a message and the message
* string itself.
*/
class PluginMessage {
public:
/**
* @var type
* The type of the message, specified using one of the message
* type codes.
* @var text
* The message string, which may be formatted using
* [GitHub Flavored Markdown]
* (https://help.github.com/articles/github-flavored-markdown).
*/
MessageType type;
std::string text;
};
}
#endif
+38
View File
@@ -0,0 +1,38 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-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_PLUGIN_TAGS
#define LOOT_PLUGIN_TAGS
#include <set>
#include <string>
namespace loot {
struct PluginTags {
std::set<std::string> added;
std::set<std::string> removed;
bool userlist_modified;
};
}
#endif
+12 -600
View File
File diff suppressed because it is too large Load Diff
+255
View File
@@ -0,0 +1,255 @@
/* 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/api_database.h"
#include <vector>
#include <unordered_map>
#include "backend/error.h"
#include "backend/game/game.h"
#include "backend/plugin/plugin_sorter.h"
namespace loot {
ApiDatabase::ApiDatabase(const GameType game, const std::string& gamePath, const std::string& gameLocalDataPath)
: game_(Game(GameType(game))) {
game_.SetGamePath(gamePath);
game_.Init(false, gameLocalDataPath);
}
///////////////////////////////////
// Database Loading Functions
///////////////////////////////////
void ApiDatabase::LoadLists(const std::string& masterlistPath,
const std::string& userlistPath) {
Masterlist temp;
MetadataList userTemp;
if (boost::filesystem::exists(masterlistPath)) {
temp.Load(masterlistPath);
} else {
throw Error(Error::Code::path_not_found, std::string("The given masterlist path does not exist: ") + masterlistPath);
}
if (!userlistPath.empty()) {
if (boost::filesystem::exists(userlistPath)) {
userTemp.Load(userlistPath);
} else {
throw Error(Error::Code::path_not_found, std::string("The given userlist path does not exist: ") + userlistPath);
}
}
game_.GetMasterlist() = temp;
unevaluatedMasterlist_ = temp;
game_.GetUserlist() = userTemp;
unevaluatedUserlist_ = userTemp;
}
void ApiDatabase::EvalLists(const LanguageCode language) {
// Clear caches before evaluating conditions.
game_.ClearCachedConditions();
Masterlist temp = unevaluatedMasterlist_;
MetadataList userTemp = unevaluatedUserlist_;
// Refresh active plugins before evaluating conditions.
temp.EvalAllConditions(game_, Language(LanguageCode(language)).GetCode());
userTemp.EvalAllConditions(game_, Language(LanguageCode(language)).GetCode());
game_.GetMasterlist() = temp;
game_.GetUserlist() = userTemp;
}
////////////////////////////////////
// LOOT Functionality Functions
////////////////////////////////////
std::vector<std::string> ApiDatabase::SortPlugins() {
// Always reload all the plugins.
game_.LoadPlugins(false);
//Sort plugins into their load order.
PluginSorter sorter;
auto list = sorter.Sort(game_, LanguageCode::english);
std::vector<std::string> loadOrder(list.size());
std::transform(begin(list), end(list), begin(loadOrder), [](const Plugin& plugin) {
return plugin.Name();
});
return loadOrder;
}
void ApiDatabase::ApplyLoadOrder(const std::vector<std::string>& loadOrder) {
game_.SetLoadOrder(loadOrder);
}
bool ApiDatabase::UpdateMasterlist(const std::string& masterlistPath,
const std::string& remoteURL,
const std::string& remoteBranch) {
if (!boost::filesystem::is_directory(boost::filesystem::path(masterlistPath).parent_path()))
throw Error(Error::Code::invalid_args, "Given masterlist path \"" + std::string(masterlistPath) + "\" does not have a valid parent directory.");
Masterlist masterlist;
return masterlist.Update(masterlistPath, remoteURL, remoteBranch);
}
MasterlistInfo ApiDatabase::GetMasterlistRevision(const std::string& masterlistPath,
const bool getShortID) {
MasterlistInfo apiMasterlistInfo;
apiMasterlistInfo.is_modified = false;
try {
Masterlist::Info info = Masterlist::GetInfo(masterlistPath, getShortID);
if (boost::ends_with(info.revision, " (edited)")) {
apiMasterlistInfo.revision_id = info.revision.substr(0, info.revision.length() - 9);
apiMasterlistInfo.revision_date = info.date.substr(0, info.date.length() - 9);
apiMasterlistInfo.is_modified = true;
} else {
apiMasterlistInfo.revision_id = info.revision;
apiMasterlistInfo.revision_date = info.date;
apiMasterlistInfo.is_modified = false;
}
} catch (Error &e) {
if (e.code() != Error::Code::ok)
throw;
}
return apiMasterlistInfo;
}
//////////////////////////
// DB Access Functions
//////////////////////////
PluginTags ApiDatabase::GetPluginTags(const std::string& plugin) {
PluginTags tags;
PluginMetadata pluginMetadata = game_.GetMasterlist().FindPlugin(PluginMetadata(plugin));
for (const auto &tag : pluginMetadata.Tags()) {
if (tag.IsAddition())
tags.added.insert(tag.Name());
else
tags.removed.insert(tag.Name());
}
pluginMetadata = game_.GetUserlist().FindPlugin(PluginMetadata(plugin));
tags.userlist_modified = !pluginMetadata.Tags().empty();
for (const auto &tag : pluginMetadata.Tags()) {
if (tag.IsAddition())
tags.added.insert(tag.Name());
else
tags.removed.insert(tag.Name());
}
return tags;
}
std::vector<PluginMessage> ApiDatabase::GetPluginMessages(const std::string& plugin) {
std::vector<PluginMessage> messages;
PluginMetadata pluginMetadata = game_.GetMasterlist().FindPlugin(PluginMetadata(plugin));
for (const auto& message : pluginMetadata.Messages()) {
PluginMessage pluginMessage;
pluginMessage.type = message.GetType();
pluginMessage.text = message.GetText();
messages.push_back(pluginMessage);
}
pluginMetadata = game_.GetUserlist().FindPlugin(PluginMetadata(plugin));
for (const auto& message : pluginMetadata.Messages()) {
PluginMessage pluginMessage;
pluginMessage.type = message.GetType();
pluginMessage.text = message.GetText();
messages.push_back(pluginMessage);
}
return messages;
}
PluginCleanliness ApiDatabase::GetPluginCleanliness(const std::string& plugin) {
// Is there any dirty info? Testing for applicability happens in loot_eval_lists().
if (!game_.GetMasterlist().FindPlugin(PluginMetadata(plugin)).DirtyInfo().empty()
|| !game_.GetUserlist().FindPlugin(PluginMetadata(plugin)).DirtyInfo().empty()) {
return PluginCleanliness::dirty;
}
// Is there a message beginning with the substring "Do not clean."?
// This isn't a very reliable system, because if the lists have been evaluated in some language
// other than English, the strings will be in different languages (and the API can't tell what they'd be)
// and the strings may be non-standard and begin with something other than "Do not clean." anyway.
std::list<Message> messages(game_.GetMasterlist().FindPlugin(PluginMetadata(plugin)).Messages());
for (const auto& message : messages) {
if (boost::starts_with(message.GetText(), "Do not clean")) {
return PluginCleanliness::do_not_clean;
}
}
messages = game_.GetUserlist().FindPlugin(PluginMetadata(plugin)).Messages();
for (const auto& message : messages) {
if (boost::starts_with(message.GetText(), "Do not clean")) {
return PluginCleanliness::do_not_clean;
}
}
return PluginCleanliness::unknown;
}
// 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.
void ApiDatabase::WriteMinimalList(const std::string& outputFile, const bool overwrite) {
if (!boost::filesystem::exists(boost::filesystem::path(outputFile).parent_path()))
throw Error(Error::Code::invalid_args, "Output directory does not exist.");
if (boost::filesystem::exists(outputFile) && !overwrite)
throw Error(Error::Code::path_write_fail, "Output file exists but overwrite is not set to true.");
Masterlist temp = game_.GetMasterlist();
std::unordered_set<PluginMetadata> minimalPlugins;
for (const auto &plugin : temp.Plugins()) {
PluginMetadata p(plugin.Name());
p.Tags(plugin.Tags());
p.DirtyInfo(plugin.DirtyInfo());
minimalPlugins.insert(p);
}
YAML::Emitter yout;
yout.SetIndent(2);
yout << YAML::BeginMap
<< YAML::Key << "plugins" << YAML::Value << minimalPlugins
<< YAML::EndMap;
boost::filesystem::path p(outputFile);
boost::filesystem::ofstream out(p);
if (out.fail())
throw Error(Error::Code::path_write_fail, "Couldn't open output file.");
out << yout.c_str();
out.close();
}
}
+73
View File
@@ -0,0 +1,73 @@
/* 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 <list>
#include <string>
#include <vector>
#include "backend/game/game.h"
#include "loot/database_interface.h"
namespace loot {
struct ApiDatabase : public DatabaseInterface {
ApiDatabase(const GameType clientGame,
const std::string& gamePath,
const std::string& gameLocalDataPath);
void LoadLists(const std::string& masterlist_path,
const std::string& userlist_path);
void EvalLists(const LanguageCode language);
std::vector<std::string> SortPlugins();
void ApplyLoadOrder(const std::vector<std::string>& loadOrder);
bool UpdateMasterlist(const std::string& masterlist_path,
const std::string& remote_url,
const std::string& remote_branch);
MasterlistInfo GetMasterlistRevision(const std::string& masterlist_path,
const bool get_short_id);
PluginTags GetPluginTags(const std::string& plugin);
std::vector<PluginMessage> GetPluginMessages(const std::string& plugin);
PluginCleanliness GetPluginCleanliness(const std::string& plugin);
void WriteMinimalList(const std::string& outputFile,
const bool overwrite);
private:
Game game_;
Masterlist unevaluatedMasterlist_;
MetadataList unevaluatedUserlist_;
};
}
#endif
-144
View File
@@ -1,144 +0,0 @@
/* 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 "backend/error.h"
loot_db::loot_db(const unsigned int clientGame, const std::string& gamePath, const boost::filesystem::path& gameLocalDataPath)
: Game(loot::GameType(clientGame)) {
this->SetGamePath(gamePath);
this->Init(false, gameLocalDataPath);
}
loot::Masterlist& loot_db::getUnevaluatedMasterlist() {
return unevaluatedMasterlist_;
}
loot::MetadataList& loot_db::getUnevaluatedUserlist() {
return unevaluatedUserlist_;
}
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::getBashTagMap() const {
return cBashTagMap;
}
unsigned int loot_db::getBashTagUid(const std::string& name) const {
auto it = bashTagMap.find(name);
if (it != end(bashTagMap))
return it->second;
throw loot::Error(loot::Error::Code::no_tag_map, "The Bash Tag \"" + name + "\" does not exist in the Bash Tag map.");
}
const std::vector<unsigned int>& loot_db::getAddedTagIds() const {
return addedTagIds;
}
const std::vector<unsigned int>& loot_db::getRemovedTagIds() const {
return removedTagIds;
}
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::setAddedTags(const std::set<std::string>& names) {
addedTagIds.clear();
for (const auto& name : names)
addedTagIds.push_back(getBashTagUid(name));
}
void loot_db::setRemovedTags(const std::set<std::string>& names) {
removedTagIds.clear();
for (const auto& name : names)
removedTagIds.push_back(getBashTagUid(name));
}
void loot_db::setPluginMessages(const std::list<loot::Message>& pluginMessages) {
cPluginMessages.resize(pluginMessages.size());
pluginMessageStrings.resize(pluginMessages.size());
size_t i = 0;
for (const auto& message : pluginMessages) {
pluginMessageStrings[i] = message.GetText();
cPluginMessages[i].type = static_cast<unsigned int>(message.GetType());
cPluginMessages[i].message = pluginMessageStrings[i].c_str();
++i;
}
}
void loot_db::addBashTagsToMap(std::set<std::string> names) {
for (const auto& name : names) {
// Try adding the Bash Tag to the map assuming it's not already in
// there, then use the UID in the returned value, as that will be
// equal to the value in the map, even if the Bash Tag was already
// present.
unsigned int uid = bashTagMap.size();
// If the tag already exists in the map, do
auto it = bashTagMap.emplace(name, uid).first;
if (it->second == cBashTagMap.size())
cBashTagMap.push_back(it->first.c_str());
else
cBashTagMap.at(it->second) = it->first.c_str();
}
}
void loot_db::clearBashTagMap() {
bashTagMap.clear();
cBashTagMap.clear();
}
void loot_db::clearArrays() {
pluginNames.clear();
cPluginNames.clear();
addedTagIds.clear();
removedTagIds.clear();
cPluginMessages.clear();
pluginMessageStrings.clear();
}
-110
View File
@@ -1,110 +0,0 @@
/* 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 <vector>
#include <unordered_map>
#include "backend/game/game.h"
#include "loot/api.h"
struct loot_db : public loot::Game {
loot_db(const unsigned int clientGame,
const std::string& gamePath,
const boost::filesystem::path& gameLocalDataPath);
loot::Masterlist& getUnevaluatedMasterlist();
loot::MetadataList& getUnevaluatedUserlist();
const char * getRevisionIdString() const;
const char * getRevisionDateString() const;
const std::vector<const char *>& getPluginNames() const;
const std::vector<const char *>& getBashTagMap() const;
unsigned int getBashTagUid(const std::string& name) const;
const std::vector<unsigned int>& getAddedTagIds() const;
const std::vector<unsigned int>& getRemovedTagIds() const;
const std::vector<loot_message>& getPluginMessages() const;
void setRevisionIdString(const std::string& str);
void setRevisionDateString(const std::string& str);
template<class T>
void setPluginNames(const T& plugins) {
// First take copies of the C++ strings to store.
pluginNames.resize(plugins.size());
std::transform(begin(plugins),
end(plugins),
begin(pluginNames),
[](const loot::PluginMetadata& plugin) {
return plugin.Name();
});
// 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 setAddedTags(const std::set<std::string>& names);
void setRemovedTags(const std::set<std::string>& names);
void setPluginMessages(const std::list<loot::Message>& pluginMessages);
void addBashTagsToMap(std::set<std::string> names);
void clearBashTagMap();
void clearArrays();
private:
loot::Masterlist unevaluatedMasterlist_;
loot::MetadataList unevaluatedUserlist_;
std::string revisionId;
std::string revisionDate;
std::vector<std::string> pluginNames;
std::vector<const char *> cPluginNames;
// For the Bash Tag map, a string is mapped to a UID that is also the
// index of the vector where the C string can be found.
std::unordered_map<std::string, unsigned int> bashTagMap;
std::vector<const char *> cBashTagMap;
std::vector<unsigned int> addedTagIds;
std::vector<unsigned int> removedTagIds;
std::vector<loot_message> cPluginMessages;
std::vector<std::string> pluginMessageStrings;
};
#endif
+4 -6
View File
@@ -32,11 +32,11 @@ along with LOOT. If not, see
namespace loot {
namespace test {
class ApiGameOperationsTest :
public ::testing::TestWithParam<unsigned int>,
public ::testing::TestWithParam<GameType>,
public CommonGameTestFixture {
protected:
ApiGameOperationsTest() :
CommonGameTestFixture(GetParam()),
CommonGameTestFixture(static_cast<unsigned int>(GetParam())),
db_(nullptr),
masterlistPath(localPath / "masterlist.yaml"),
noteMessage("Do not clean ITM records, they are intentional and required for the mod to function."),
@@ -48,14 +48,12 @@ protected:
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()));
db_ = CreateDatabase(GetParam(), dataPath.parent_path().string(), localPath.string());
}
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));
}
@@ -109,7 +107,7 @@ protected:
masterlist.close();
}
loot_db * db_;
std::shared_ptr<DatabaseInterface> db_;
const boost::filesystem::path masterlistPath;
+96
View File
@@ -0,0 +1,96 @@
/* 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_CREATE_DATABASE_TEST
#define LOOT_TESTS_API_CREATE_DATABASE_TEST
#include "loot/api.h"
#include <climits>
#include "tests/common_game_test_fixture.h"
namespace loot {
namespace test {
class CreateDatabaseTest :
public ::testing::TestWithParam<GameType>,
public CommonGameTestFixture {
protected:
CreateDatabaseTest() :
CommonGameTestFixture(static_cast<unsigned int>(GetParam())),
db_(nullptr) {}
void SetUp() {
setUp();
}
void TearDown() {
tearDown();
}
std::shared_ptr<DatabaseInterface> 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(,
CreateDatabaseTest,
::testing::Values(
GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
TEST_P(CreateDatabaseTest, shouldSucceedIfPassedValidParametersWithRelativePaths) {
EXPECT_NO_THROW(db_ = CreateDatabase(GetParam(), dataPath.parent_path().string(), localPath.string()));
EXPECT_NE(nullptr, db_);
}
TEST_P(CreateDatabaseTest, shouldSucceedIfPassedValidParametersWithAbsolutePaths) {
boost::filesystem::path game = boost::filesystem::current_path() / dataPath.parent_path();
boost::filesystem::path local = boost::filesystem::current_path() / localPath;
EXPECT_NO_THROW(db_ = CreateDatabase(GetParam(), dataPath.parent_path().string(), localPath.string()));
EXPECT_NE(nullptr, db_);
}
TEST_P(CreateDatabaseTest, shouldThrowIfPassedAGamePathThatDoesNotExist) {
EXPECT_ANY_THROW(CreateDatabase(GetParam(), missingPath.string(), localPath.string()));
}
TEST_P(CreateDatabaseTest, shouldThrowIfPassedALocalPathThatDoesNotExist) {
EXPECT_ANY_THROW(CreateDatabase(GetParam(), dataPath.parent_path().string(), missingPath.string()));
}
#ifdef _WIN32
TEST_P(CreateDatabaseTest, shouldReturnOkIfPassedAnEmptyLocalPathString) {
EXPECT_NO_THROW(db_ = CreateDatabase(GetParam(), dataPath.parent_path().string(), ""));
EXPECT_NE(nullptr, db_);
}
#endif
}
}
#endif
+485
View File
@@ -0,0 +1,485 @@
/* 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_DATABASE_INTERFACE_TEST
#define LOOT_TESTS_API_DATABASE_INTERFACE_TEST
#include "loot/api.h"
#include "tests/api/api_game_operations_test.h"
namespace loot {
namespace test {
class DatabaseInterfaceTest : public ApiGameOperationsTest {
protected:
DatabaseInterfaceTest() :
userlistPath_(localPath / "userlist.yaml"),
url_("https://github.com/loot/testing-metadata.git"),
branch_("2.x"),
minimalOutputPath_(localPath / "minimal.yml") {}
void SetUp() {
ApiGameOperationsTest::SetUp();
ASSERT_FALSE(boost::filesystem::exists(minimalOutputPath_));
}
void TearDown() {
if (boost::filesystem::exists(minimalOutputPath_)) {
boost::filesystem::permissions(minimalOutputPath_,
boost::filesystem::perms::add_perms
| boost::filesystem::perms::owner_write);
}
ApiGameOperationsTest::TearDown();
// The userlist may have been created during the test, so delete it.
ASSERT_NO_THROW(boost::filesystem::remove(userlistPath_));
// Also remove the ".git" folder if it has been created.
ASSERT_NO_THROW(boost::filesystem::remove_all(masterlistPath.parent_path() / ".git"));
ASSERT_NO_THROW(boost::filesystem::remove(minimalOutputPath_));
}
std::string GetExpectedMinimalContent() const {
using std::endl;
std::stringstream expectedContent;
expectedContent
<< "plugins:" << endl
<< " - name: '" << blankEsm << "'" << endl
<< " tag:" << endl
<< " - Actors.ACBS" << endl
<< " - Actors.AIData" << endl
<< " - -C.Water" << endl
<< " - name: '" << blankDifferentEsm << "'" << endl
<< " dirty:" << endl
<< " - crc: 0x7d22f9df" << endl
<< " utility: 'TES4Edit'" << endl
<< " udr: 4";
return expectedContent.str();
}
const boost::filesystem::path userlistPath_;
const boost::filesystem::path minimalOutputPath_;
const std::string url_;
const std::string branch_;
};
// 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(,
DatabaseInterfaceTest,
::testing::Values(
GameType::tes4,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
TEST_P(DatabaseInterfaceTest, loadListsShouldThrowIfNoMasterlistIsPresent) {
EXPECT_ANY_THROW(db_->LoadLists(masterlistPath.string(), ""));
}
TEST_P(DatabaseInterfaceTest, loadListsShouldThrowIfAMasterlistIsPresentButAUserlistDoesNotExistAtTheGivenPath) {
ASSERT_NO_THROW(GenerateMasterlist());
EXPECT_ANY_THROW(db_->LoadLists(masterlistPath.string(), userlistPath_.string()));
}
TEST_P(DatabaseInterfaceTest, loadListsShouldSucceedIfTheMasterlistIsPresentAndTheUserlistPathIsAnEmptyString) {
ASSERT_NO_THROW(GenerateMasterlist());
EXPECT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
}
TEST_P(DatabaseInterfaceTest, loadListsShouldSucceedIfTheMasterlistAndUserlistAreBothPresent) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(boost::filesystem::copy(masterlistPath, userlistPath_));
EXPECT_NO_THROW(db_->LoadLists(masterlistPath.string(), userlistPath_.string()));
}
TEST_P(DatabaseInterfaceTest, evalListsShouldReturnOkForAllLanguagesWithNoListsLoaded) {
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::english));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::english));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::spanish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::russian));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::french));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::chinese));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::polish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::brazilian_portuguese));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::finnish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::german));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::danish));
}
TEST_P(DatabaseInterfaceTest, evalListsShouldReturnOKForAllLanguagesWithAMasterlistLoaded) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::english));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::english));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::spanish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::russian));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::french));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::chinese));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::polish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::brazilian_portuguese));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::finnish));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::german));
EXPECT_NO_THROW(db_->EvalLists(LanguageCode::danish));
}
TEST_P(DatabaseInterfaceTest, sortPluginsShouldSucceedIfPassedValidArguments) {
std::vector<std::string> expectedOrder = {
masterFile,
blankEsm,
blankMasterDependentEsm,
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankMasterDependentEsp,
blankDifferentMasterDependentEsp,
blankEsp,
blankPluginDependentEsp,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
};
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
std::vector<std::string> actualOrder = db_->SortPlugins();
ASSERT_EQ(expectedOrder, actualOrder);
}
TEST_P(DatabaseInterfaceTest, applyLoadOrderShouldReturnOkIfLoadOrderGivenIsNotEmpty) {
std::vector<std::string> loadOrder = {
masterFile,
blankEsm,
blankMasterDependentEsm,
blankDifferentEsm,
blankDifferentMasterDependentEsm,
blankMasterDependentEsp,
blankDifferentMasterDependentEsp,
blankEsp,
blankPluginDependentEsp,
blankDifferentEsp,
blankDifferentPluginDependentEsp,
};
EXPECT_NO_THROW(db_->ApplyLoadOrder(loadOrder));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAnInvalidArgsErrorIfTheMasterlistPathGivenIsInvalid) {
EXPECT_ANY_THROW(db_->UpdateMasterlist(";//\?", url_, branch_));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAnInvalidArgsErrorIfTheMasterlistPathGivenIsEmpty) {
EXPECT_ANY_THROW(db_->UpdateMasterlist("", url_, branch_));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAGitErrorIfTheRepositoryUrlGivenCannotBeFound) {
EXPECT_ANY_THROW(db_->UpdateMasterlist(masterlistPath.string(), "https://github.com/loot/oblivion-does-not-exist.git", branch_));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAnInvalidArgsErrorIfTheRepositoryUrlGivenIsEmpty) {
EXPECT_ANY_THROW(db_->UpdateMasterlist(masterlistPath.string(), "", branch_));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAGitErrorIfTheRepositoryBranchGivenCannotBeFound) {
EXPECT_ANY_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, "missing-branch"));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldReturnAnInvalidArgsErrorIfTheRepositoryBranchGivenIsEmpty) {
EXPECT_ANY_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, ""));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldSucceedIfPassedValidParametersAndOutputTrueIfTheMasterlistWasUpdated) {
bool updated = false;
EXPECT_NO_THROW(updated = db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
EXPECT_TRUE(updated);
EXPECT_TRUE(boost::filesystem::exists(masterlistPath));
}
TEST_P(DatabaseInterfaceTest, updateMasterlistShouldSucceedIfCalledRepeatedlyButOnlyOutputTrueForTheFirstCall) {
bool updated = false;
EXPECT_NO_THROW(updated = db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
EXPECT_TRUE(updated);
EXPECT_NO_THROW(updated = db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
EXPECT_FALSE(updated);
EXPECT_TRUE(boost::filesystem::exists(masterlistPath));
}
TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldSucceedIfNoMasterlistIsPresent) {
MasterlistInfo info;
EXPECT_NO_THROW(info = db_->GetMasterlistRevision(masterlistPath.string(), false));
EXPECT_TRUE(info.revision_id.empty());
EXPECT_TRUE(info.revision_date.empty());
EXPECT_FALSE(info.is_modified);
}
TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldSucceedIfANonVersionControlledMasterlistIsPresent) {
ASSERT_NO_THROW(GenerateMasterlist());
MasterlistInfo info;
EXPECT_NO_THROW(info = db_->GetMasterlistRevision(masterlistPath.string(), false));
EXPECT_TRUE(info.revision_id.empty());
EXPECT_TRUE(info.revision_date.empty());
EXPECT_FALSE(info.is_modified);
}
TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldOutputLongStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsFalse) {
ASSERT_NO_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
MasterlistInfo info;
EXPECT_NO_THROW(info = db_->GetMasterlistRevision(masterlistPath.string(), false));
EXPECT_EQ(40, info.revision_id.length());
EXPECT_EQ(10, info.revision_date.length());
EXPECT_FALSE(info.is_modified);
}
TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldOutputShortStringsAndBooleanFalseIfAVersionControlledMasterlistIsPresentAndGetShortIdParameterIsTrue) {
ASSERT_NO_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
MasterlistInfo info;
EXPECT_NO_THROW(info = db_->GetMasterlistRevision(masterlistPath.string(), false));
EXPECT_GE(size_t(40), info.revision_id.length());
EXPECT_LE(size_t(7), info.revision_id.length());
EXPECT_EQ(10, info.revision_date.length());
EXPECT_FALSE(info.is_modified);
}
TEST_P(DatabaseInterfaceTest, getMasterlistRevisionShouldSucceedIfAnEditedVersionControlledMasterlistIsPresent) {
ASSERT_NO_THROW(db_->UpdateMasterlist(masterlistPath.string(), url_, branch_));
ASSERT_NO_THROW(GenerateMasterlist());
MasterlistInfo info;
EXPECT_NO_THROW(info = db_->GetMasterlistRevision(masterlistPath.string(), false));
EXPECT_EQ(40, info.revision_id.length());
EXPECT_EQ(10, info.revision_date.length());
EXPECT_TRUE(info.is_modified);
}
TEST_P(DatabaseInterfaceTest, getPluginTagsShouldReturnOkAndOutputEmptyNonModifiedArraysIfAPluginWithoutTagsIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
PluginTags tags;
EXPECT_NO_THROW(tags = db_->GetPluginTags(blankEsp));
EXPECT_TRUE(tags.added.empty());
EXPECT_TRUE(tags.removed.empty());
EXPECT_FALSE(tags.userlist_modified);
}
TEST_P(DatabaseInterfaceTest, getPluginTagsShouldReturnOkAndNonEmptyNonModifiedArraysIfAPluginWithTagsIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
PluginTags tags;
EXPECT_NO_THROW(tags = db_->GetPluginTags(blankEsm));
EXPECT_EQ(std::set<std::string>({
"Actors.ACBS",
"Actors.AIData",
}), tags.added);
EXPECT_EQ(std::set<std::string>({
"C.Water",
}), tags.removed);
EXPECT_FALSE(tags.userlist_modified);
}
TEST_P(DatabaseInterfaceTest, getPluginTagsShouldReturnOkAndNonEmptyModifiedArraysIfAPluginWithTagsIsQueriedAndMetadataWasAlsoLoadedFromAUserlist) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), masterlistPath.string()));
PluginTags tags;
EXPECT_NO_THROW(tags = db_->GetPluginTags(blankEsm));
EXPECT_EQ(std::set<std::string>({
"Actors.ACBS",
"Actors.AIData",
}), tags.added);
EXPECT_EQ(std::set<std::string>({
"C.Water",
}), tags.removed);
EXPECT_TRUE(tags.userlist_modified);
}
TEST_P(DatabaseInterfaceTest, getPluginTagsShouldOutputTheCorrectBashTagsForPluginsWhenMakingConsecutiveCalls) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
PluginTags tags;
EXPECT_NO_THROW(tags = db_->GetPluginTags(blankEsm));
EXPECT_EQ(std::set<std::string>({
"Actors.ACBS",
"Actors.AIData",
}), tags.added);
EXPECT_EQ(std::set<std::string>({
"C.Water",
}), tags.removed);
EXPECT_FALSE(tags.userlist_modified);
EXPECT_NO_THROW(tags = db_->GetPluginTags(blankEsp));
EXPECT_TRUE(tags.added.empty());
EXPECT_TRUE(tags.removed.empty());
EXPECT_FALSE(tags.userlist_modified);
}
TEST_P(DatabaseInterfaceTest, getPluginMessagesShouldReturnOkAndOutputANullArrayIfAPluginWithNoMessagesIsQueried) {
std::vector<PluginMessage> messages;
EXPECT_NO_THROW(messages = db_->GetPluginMessages(blankEsp));
EXPECT_TRUE(messages.empty());
}
TEST_P(DatabaseInterfaceTest, getPluginMessagesShouldReturnOkAndOutputANoteIfAPluginWithANoteMessageIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
std::vector<PluginMessage> messages;
EXPECT_NO_THROW(messages = db_->GetPluginMessages(blankEsm));
ASSERT_EQ(1, messages.size());
EXPECT_EQ(MessageType::say, messages[0].type);
EXPECT_EQ(noteMessage, messages[0].text);
}
TEST_P(DatabaseInterfaceTest, getPluginMessagesShouldReturnOkAndOutputAWarningIfAPluginWithAWarningMessageIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
std::vector<PluginMessage> messages;
EXPECT_NO_THROW(messages = db_->GetPluginMessages(blankDifferentEsm));
ASSERT_EQ(1, messages.size());
EXPECT_EQ(MessageType::warn, messages[0].type);
EXPECT_EQ(warningMessage, messages[0].text);
}
TEST_P(DatabaseInterfaceTest, getPluginMessagesShouldReturnOkAndOutputAnErrorIfAPluginWithAnErrorMessageIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
std::vector<PluginMessage> messages;
EXPECT_NO_THROW(messages = db_->GetPluginMessages(blankDifferentEsp));
ASSERT_EQ(1, messages.size());
EXPECT_EQ(MessageType::error, messages[0].type);
EXPECT_EQ(errorMessage, messages[0].text);
}
TEST_P(DatabaseInterfaceTest, getPluginMessagesShouldReturnOkAndOutputMultipleMessagesIfAPluginWithMultipleMessagesIsQueried) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
std::vector<PluginMessage> messages;
EXPECT_NO_THROW(messages = db_->GetPluginMessages(blankDifferentMasterDependentEsp));
ASSERT_EQ(3, messages.size());
EXPECT_EQ(MessageType::say, messages[0].type);
EXPECT_EQ(noteMessage, messages[0].text);
EXPECT_EQ(MessageType::warn, messages[1].type);
EXPECT_EQ(warningMessage, messages[1].text);
EXPECT_EQ(MessageType::error, messages[2].type);
EXPECT_EQ(errorMessage, messages[2].text);
}
TEST_P(DatabaseInterfaceTest, getPluginCleanlinessShouldReturnOkAndOutputUnknownForAPluginWithNoDirtyInfo) {
PluginCleanliness cleanliness;
EXPECT_NO_THROW(cleanliness = db_->GetPluginCleanliness(blankEsp));
EXPECT_EQ(PluginCleanliness::unknown, cleanliness);
}
TEST_P(DatabaseInterfaceTest, getPluginCleanlinessShouldReturnOkAndOutputYesForAPluginWithDirtyInfo) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
PluginCleanliness cleanliness;
EXPECT_NO_THROW(cleanliness = db_->GetPluginCleanliness(blankDifferentEsm));
EXPECT_EQ(PluginCleanliness::dirty, cleanliness);
}
TEST_P(DatabaseInterfaceTest, getPluginCleanlinessShouldReturnOkAndOutputNoForAPluginWithADoNotCleanMessage) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
PluginCleanliness cleanliness;
EXPECT_NO_THROW(cleanliness = db_->GetPluginCleanliness(blankEsm));
EXPECT_EQ(PluginCleanliness::do_not_clean, cleanliness);
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldReturnOkAndWriteToFileIfArgumentsGivenAreValid) {
EXPECT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), false));
EXPECT_TRUE(boost::filesystem::exists(minimalOutputPath_));
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldReturnAFileWriteErrorIfTheFileAlreadyExistsAndTheOverwriteArgumentIsFalse) {
ASSERT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), false));
ASSERT_TRUE(boost::filesystem::exists(minimalOutputPath_));
EXPECT_ANY_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), false));
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldReturnOkAndWriteToFileIfTheArgumentsAreValidAndTheOverwriteArgumentIsTrue) {
EXPECT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), true));
EXPECT_TRUE(boost::filesystem::exists(minimalOutputPath_));
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldReturnOkIfTheFileAlreadyExistsAndTheOverwriteArgumentIsTrue) {
ASSERT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), false));
ASSERT_TRUE(boost::filesystem::exists(minimalOutputPath_));
EXPECT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), true));
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldReturnAFileWriteErrorIfPathGivenExistsAndIsReadOnly) {
ASSERT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), false));
ASSERT_TRUE(boost::filesystem::exists(minimalOutputPath_));
boost::filesystem::permissions(minimalOutputPath_,
boost::filesystem::perms::remove_perms
| boost::filesystem::perms::owner_write);
EXPECT_ANY_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), true));
}
TEST_P(DatabaseInterfaceTest, writeMinimalListShouldWriteOnlyBashTagsAndDirtyInfo) {
ASSERT_NO_THROW(GenerateMasterlist());
ASSERT_NO_THROW(db_->LoadLists(masterlistPath.string(), ""));
EXPECT_NO_THROW(db_->WriteMinimalList(minimalOutputPath_.string(), true));
boost::filesystem::ifstream in(minimalOutputPath_);
std::stringstream content;
content << in.rdbuf();
EXPECT_EQ(GetExpectedMinimalContent(), content.str());
}
}
}
#endif
+44
View File
@@ -0,0 +1,44 @@
/* 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_IS_COMPATIBLE_TEST
#define LOOT_TESTS_API_IS_COMPATIBLE_TEST
#include "loot/api.h"
#include <gtest/gtest.h>
namespace loot {
namespace test {
TEST(IsCompatible, shouldReturnTrueWithEqualMajorAndMinorVersionsAndUnequalPatchVersion) {
EXPECT_TRUE(IsCompatible(LootVersion::major, LootVersion::minor, LootVersion::patch + 1));
}
TEST(IsCompatible, shouldReturnFalseWithEqualMajorVersionAndUnequalMinorAndPatchVersions) {
EXPECT_FALSE(IsCompatible(LootVersion::major, LootVersion::minor + 1, LootVersion::patch + 1));
}
}
}
#endif
@@ -1,78 +0,0 @@
/* 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/api.h"
#include "tests/api/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
@@ -1,105 +0,0 @@
/* 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/api.h"
#include <climits>
#include "tests/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
@@ -1,327 +0,0 @@
/* 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(MessageType::warn, "Test 1"),
Message(MessageType::error, "Test 2"),
}));
EXPECT_EQ(2, db_->getPluginMessages().size());
EXPECT_EQ(static_cast<unsigned int>(MessageType::warn), db_->getPluginMessages()[0].type);
EXPECT_STREQ("Test 1", db_->getPluginMessages()[0].message);
EXPECT_EQ(static_cast<unsigned int>(MessageType::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(MessageType::warn, "Test 1"),
Message(MessageType::error, "Test 2"),
}));
db_->setPluginMessages(std::list<Message>({
Message(MessageType::error, "Test 3"),
Message(MessageType::warn, "Test 4"),
Message(MessageType::say, "Test 5"),
}));
EXPECT_EQ(3, db_->getPluginMessages().size());
EXPECT_EQ(static_cast<unsigned int>(MessageType::error), db_->getPluginMessages()[0].type);
EXPECT_STREQ("Test 3", db_->getPluginMessages()[0].message);
EXPECT_EQ(static_cast<unsigned int>(MessageType::warn), db_->getPluginMessages()[1].type);
EXPECT_STREQ("Test 4", db_->getPluginMessages()[1].message);
EXPECT_EQ(static_cast<unsigned int>(MessageType::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(MessageType::warn, "Test 1"),
Message(MessageType::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
@@ -1,88 +0,0 @@
/* 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/api.h"
#include "tests/api/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

Some files were not shown because too many files have changed in this diff Show More