From e61171bdbe2ab94bc14048195fa397177068ec06 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Mon, 28 Apr 2025 17:52:21 +0100 Subject: [PATCH] Split metadata class test files in two So that the classes that are part of the public API get treated as interface tests, and the YAML serialisation and deserialisation are tested as internal tests. --- cmake/tests.cmake | 28 +- src/tests/api/interface/main.cpp | 9 + .../metadata/conditional_metadata_test.h | 4 +- .../metadata/file_test.h | 176 +------- .../metadata/group_test.h | 117 +----- .../metadata/location_test.h | 68 +-- .../metadata/message_content_test.h | 47 +-- .../metadata/message_test.h | 342 +-------------- .../metadata/plugin_cleaning_data_test.h | 123 +----- .../interface/metadata/plugin_metadata_test.h | 395 ++++++++++++++++++ .../metadata/tag_test.h | 114 +---- src/tests/api/internals/main.cpp | 17 +- .../api/internals/metadata/yaml/file_test.h | 201 +++++++++ .../api/internals/metadata/yaml/group_test.h | 142 +++++++ .../internals/metadata/yaml/location_test.h | 93 +++++ .../metadata/yaml/message_content_test.h | 74 ++++ .../internals/metadata/yaml/message_test.h | 371 ++++++++++++++++ .../metadata/yaml/plugin_cleaning_data_test.h | 157 +++++++ .../{ => yaml}/plugin_metadata_test.h | 360 +--------------- .../api/internals/metadata/yaml/tag_test.h | 139 ++++++ 20 files changed, 1633 insertions(+), 1344 deletions(-) rename src/tests/api/{internals => interface}/metadata/conditional_metadata_test.h (95%) rename src/tests/api/{internals => interface}/metadata/file_test.h (65%) rename src/tests/api/{internals => interface}/metadata/group_test.h (74%) rename src/tests/api/{internals => interface}/metadata/location_test.h (78%) rename src/tests/api/{internals => interface}/metadata/message_content_test.h (87%) rename src/tests/api/{internals => interface}/metadata/message_test.h (53%) rename src/tests/api/{internals => interface}/metadata/plugin_cleaning_data_test.h (75%) create mode 100644 src/tests/api/interface/metadata/plugin_metadata_test.h rename src/tests/api/{internals => interface}/metadata/tag_test.h (68%) create mode 100644 src/tests/api/internals/metadata/yaml/file_test.h create mode 100644 src/tests/api/internals/metadata/yaml/group_test.h create mode 100644 src/tests/api/internals/metadata/yaml/location_test.h create mode 100644 src/tests/api/internals/metadata/yaml/message_content_test.h create mode 100644 src/tests/api/internals/metadata/yaml/message_test.h create mode 100644 src/tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h rename src/tests/api/internals/metadata/{ => yaml}/plugin_metadata_test.h (52%) create mode 100644 src/tests/api/internals/metadata/yaml/tag_test.h diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 2584fe26..328074c0 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -44,15 +44,14 @@ set(LIBLOOT_SRC_TESTS_INTERNALS_H_FILES "${CMAKE_SOURCE_DIR}/src/tests/api/internals/helpers/crc_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/internals/helpers/text_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/condition_evaluator_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/conditional_metadata_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/file_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/group_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/location_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/message_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/message_content_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/plugin_cleaning_data_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/plugin_metadata_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/tag_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/file_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/group_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/location_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/message_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/message_content_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/plugin_metadata_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/internals/metadata/yaml/tag_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/internals/plugin_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/internals/sorting/group_sort_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/internals/sorting/plugin_sort_test.h" @@ -68,7 +67,16 @@ set(LIBLOOT_SRC_TESTS_INTERFACE_H_FILES "${CMAKE_SOURCE_DIR}/src/tests/api/interface/create_game_handle_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/interface/database_interface_test.h" "${CMAKE_SOURCE_DIR}/src/tests/api/interface/game_interface_test.h" - "${CMAKE_SOURCE_DIR}/src/tests/api/interface/is_compatible_test.h") + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/is_compatible_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/conditional_metadata_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/file_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/group_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/location_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/message_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/message_content_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/plugin_cleaning_data_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/plugin_metadata_test.h" + "${CMAKE_SOURCE_DIR}/src/tests/api/interface/metadata/tag_test.h") source_group(TREE "${CMAKE_SOURCE_DIR}/src/tests/api/internals" PREFIX "Source Files" diff --git a/src/tests/api/interface/main.cpp b/src/tests/api/interface/main.cpp index af00ddfd..9e42be34 100644 --- a/src/tests/api/interface/main.cpp +++ b/src/tests/api/interface/main.cpp @@ -25,6 +25,15 @@ #include #include "loot/api.h" +#include "tests/api/interface/metadata/conditional_metadata_test.h" +#include "tests/api/interface/metadata/file_test.h" +#include "tests/api/interface/metadata/group_test.h" +#include "tests/api/interface/metadata/location_test.h" +#include "tests/api/interface/metadata/message_content_test.h" +#include "tests/api/interface/metadata/message_test.h" +#include "tests/api/interface/metadata/plugin_cleaning_data_test.h" +#include "tests/api/interface/metadata/plugin_metadata_test.h" +#include "tests/api/interface/metadata/tag_test.h" #include "tests/api/interface/create_game_handle_test.h" #include "tests/api/interface/database_interface_test.h" #include "tests/api/interface/game_interface_test.h" diff --git a/src/tests/api/internals/metadata/conditional_metadata_test.h b/src/tests/api/interface/metadata/conditional_metadata_test.h similarity index 95% rename from src/tests/api/internals/metadata/conditional_metadata_test.h rename to src/tests/api/interface/metadata/conditional_metadata_test.h index 4fdf0012..2cb4ceb9 100644 --- a/src/tests/api/internals/metadata/conditional_metadata_test.h +++ b/src/tests/api/interface/metadata/conditional_metadata_test.h @@ -22,8 +22,8 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_CONDITIONAL_METADATA_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_CONDITIONAL_METADATA_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_CONDITIONAL_METADATA_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_CONDITIONAL_METADATA_TEST #include "loot/metadata/conditional_metadata.h" #include "tests/common_game_test_fixture.h" diff --git a/src/tests/api/internals/metadata/file_test.h b/src/tests/api/interface/metadata/file_test.h similarity index 65% rename from src/tests/api/internals/metadata/file_test.h rename to src/tests/api/interface/metadata/file_test.h index b630ccdc..16aa2e1d 100644 --- a/src/tests/api/internals/metadata/file_test.h +++ b/src/tests/api/interface/metadata/file_test.h @@ -22,16 +22,14 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_FILE_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_FILE_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_FILE_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_FILE_TEST #include -#include "api/metadata/yaml/file.h" #include "loot/metadata/file.h" -namespace loot { -namespace test { +namespace loot::test { TEST(File, defaultConstructorShouldInitialiseEmptyStrings) { File file; @@ -381,174 +379,6 @@ TEST(File, getDisplayNameShouldReturnDisplayString) { EXPECT_EQ("display", file.GetDisplayName()); } - -TEST(File, emittingAsYamlShouldSingleQuoteValues) { - File file("name1", - "display1", - "condition1", - {MessageContent("english", "en")}, - "constraint1"); - YAML::Emitter emitter; - emitter << file; - std::string expected = "name: '" + std::string(file.GetName()) + - "'\ncondition: '" + file.GetCondition() + - "'\ndisplay: '" + file.GetDisplayName() + - "'\nconstraint: '" + file.GetConstraint() + - "'\ndetail: '" + file.GetDetail()[0].GetText() + "'"; - - EXPECT_EQ(expected, emitter.c_str()); -} - -TEST(File, emittingAsYamlShouldOutputAsAScalarIfOnlyTheNameStringIsNotEmpty) { - File file("file.esp"); - YAML::Emitter emitter; - emitter << file; - - EXPECT_EQ("'" + std::string(file.GetName()) + "'", emitter.c_str()); -} - -TEST(File, emittingAsYamlShouldOmitEmptyConditionAndConstraintStrings) { - File file("name1", "display1"); - YAML::Emitter emitter; - emitter << file; - std::string expected = "name: '" + std::string(file.GetName()) + - "'\ndisplay: '" + file.GetDisplayName() + "'"; - - EXPECT_EQ(expected, emitter.c_str()); -} - -TEST( - File, - emittingAsYamlShouldWriteDetailAsAListIfTheVectorContainsMoreThanOneElement) { - File file("", - "", - "", - {MessageContent("english", "en"), MessageContent("french", "fr")}); - YAML::Emitter emitter; - emitter << file; - std::string expected = - "name: ''\n" - "detail:\n" - " - lang: en\n" - " text: 'english'\n" - " - lang: fr\n" - " text: 'french'"; - - EXPECT_EQ(expected, emitter.c_str()); -} - -TEST(File, encodingAsYamlShouldStoreDataCorrectly) { - auto detail = {MessageContent("english", "en"), - MessageContent("french", "fr")}; - File file("name1", "display1", "condition1", detail, "constraint1"); - YAML::Node node; - node = file; - - EXPECT_EQ(std::string(file.GetName()), node["name"].as()); - EXPECT_EQ(file.GetDisplayName(), node["display"].as()); - EXPECT_EQ(file.GetCondition(), node["condition"].as()); - EXPECT_EQ(file.GetDetail(), node["detail"].as>()); - EXPECT_EQ(file.GetConstraint(), node["constraint"].as()); -} - -TEST(File, encodingAsYamlShouldOmitEmptyFields) { - File file("file.esp"); - YAML::Node node; - node = file; - - EXPECT_EQ(std::string(file.GetName()), node["name"].as()); - EXPECT_FALSE(node["display"]); - EXPECT_FALSE(node["condition"]); - EXPECT_FALSE(node["detail"]); -} - -TEST(File, decodingFromYamlShouldSetDataCorrectly) { - YAML::Node node = YAML::Load( - "{name: name1, display: display1, condition: 'file(\"Foo.esp\")', " - "detail: 'details', constraint: 'file(\"Bar.esp\")'}"); - File file = node.as(); - - std::vector expectedDetail = { - MessageContent("details", "en")}; - - EXPECT_EQ(node["name"].as(), std::string(file.GetName())); - EXPECT_EQ(node["display"].as(), file.GetDisplayName()); - EXPECT_EQ(node["condition"].as(), file.GetCondition()); - EXPECT_EQ(expectedDetail, file.GetDetail()); - EXPECT_EQ(node["constraint"].as(), file.GetConstraint()); -} - -TEST(File, - decodingFromYamlWithMissingConditionFieldShouldLeaveConditionStringEmpty) { - YAML::Node node = YAML::Load("{name: name1, display: display1}"); - File file = node.as(); - - EXPECT_EQ(node["name"].as(), std::string(file.GetName())); - EXPECT_EQ(node["display"].as(), file.GetDisplayName()); - EXPECT_TRUE(file.GetCondition().empty()); - EXPECT_TRUE(file.GetDetail().empty()); - EXPECT_TRUE(file.GetConstraint().empty()); -} - -TEST(File, decodingFromYamlWithAListOfMessageContentDetailsShouldReadThemAll) { - YAML::Node node = YAML::Load( - "{name: name1, display: display1, condition: 'file(\"Foo.esp\")', " - "detail: [{text: english, lang: en}, {text: french, lang: fr}]}"); - File file = node.as(); - - std::vector expectedDetail = {MessageContent("english", "en"), - MessageContent("french", "fr")}; - - EXPECT_EQ(expectedDetail, file.GetDetail()); -} - -TEST(File, decodingFromYamlShouldNotThrowIfTheOnlyDetailStringIsNotEnglish) { - YAML::Node node = YAML::Load( - "name: name1\n" - "detail:\n" - " - lang: fr\n" - " text: content1"); - - EXPECT_NO_THROW(node.as()); -} - -TEST( - File, - decodingFromYamlShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { - YAML::Node node = YAML::Load( - "name: name1\n" - "detail:\n" - " - lang: de\n" - " text: content1\n" - " - lang: fr\n" - " text: content2"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST(File, decodingFromYamlScalarShouldLeaveDisplayNameAndConditionEmpty) { - YAML::Node node = YAML::Load("name1"); - File file = node.as(); - - EXPECT_EQ(node.as(), std::string(file.GetName())); - EXPECT_TRUE(file.GetDisplayName().empty()); - EXPECT_TRUE(file.GetCondition().empty()); - EXPECT_TRUE(file.GetDetail().empty()); - EXPECT_TRUE(file.GetConstraint().empty()); -} - -TEST(File, decodingFromYamlShouldThrowIfAnInvalidMapIsGiven) { - YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST(File, decodingFromYamlShouldThrowIfAListIsGiven) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/metadata/group_test.h b/src/tests/api/interface/metadata/group_test.h similarity index 74% rename from src/tests/api/internals/metadata/group_test.h rename to src/tests/api/interface/metadata/group_test.h index 10e7c1e1..f3cd21fb 100644 --- a/src/tests/api/internals/metadata/group_test.h +++ b/src/tests/api/interface/metadata/group_test.h @@ -22,16 +22,14 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_GROUP_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_GROUP_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_GROUP_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_GROUP_TEST #include -#include "api/metadata/yaml/group.h" #include "loot/metadata/group.h" -namespace loot { -namespace test { +namespace loot::test { TEST(Group, defaultConstructorShouldCreateDefaultGroup) { Group group; @@ -350,115 +348,6 @@ TEST( EXPECT_FALSE(group1 >= group2); EXPECT_TRUE(group2 >= group1); } - -TEST(Group, emittingAsYamlShouldOmitAfterKeyIfAfterGroupsIsEmpty) { - Group group; - - YAML::Emitter emitter; - emitter << group; - - EXPECT_STREQ("name: 'default'", emitter.c_str()); -} - -TEST(Group, emittingAsYamlShouldIncludeDescriptionKeyIfDescriptionIsNotEmpty) { - Group group("group1", {}, "test"); - - YAML::Emitter emitter; - emitter << group; - - EXPECT_STREQ( - "name: 'group1'\n" - "description: 'test'", - emitter.c_str()); -} - -TEST(Group, emittingAsYamlShouldIncludeAfterKeyIfAfterGroupsIsNotEmpty) { - Group group("group1", {"other_group"}); - - YAML::Emitter emitter; - emitter << group; - - EXPECT_STREQ( - "name: 'group1'\n" - "after:\n" - " - other_group", - emitter.c_str()); -} - -TEST(Group, encodingAsYamlShouldOmitDescriptionKeyIfDescriptionIsEmpty) { - Group group; - YAML::Node node; - node = group; - - EXPECT_EQ("default", node["name"].as()); - EXPECT_FALSE(node["description"]); -} - -TEST(Group, encodingAsYamlShouldIncludeDescriptionKeyIfDescriptionIsNotEmpty) { - Group group("group1", {}, "test"); - YAML::Node node; - node = group; - - EXPECT_EQ("group1", node["name"].as()); - EXPECT_EQ("test", node["description"].as()); -} - -TEST(Group, encodingAsYamlShouldOmitAfterKeyIfAfterGroupsIsEmpty) { - Group group; - YAML::Node node; - node = group; - - EXPECT_EQ("default", node["name"].as()); - EXPECT_FALSE(node["after"]); -} - -TEST(Group, encodingAsYamlShouldIncludeAfterKeyIfAfterGroupsIsNotEmpty) { - Group group("group1", {"other_group"}); - YAML::Node node; - node = group; - - std::vector expectedAfterGroups = {"other_group"}; - EXPECT_EQ("group1", node["name"].as()); - EXPECT_EQ(expectedAfterGroups, node["after"].as>()); -} - -TEST(Group, decodingFromYamlShouldSetGivenName) { - YAML::Node node = YAML::Load("{name: group1}"); - Group group = node.as(); - - EXPECT_EQ("group1", group.GetName()); - EXPECT_TRUE(group.GetAfterGroups().empty()); -} - -TEST(Group, decodingFromYamlShouldSetDescriptionIfOneIsGiven) { - YAML::Node node = YAML::Load("{name: group1, description: test}"); - Group group = node.as(); - - EXPECT_EQ("group1", group.GetName()); - EXPECT_EQ("test", group.GetDescription()); -} - -TEST(Group, decodingFromYamlShouldSetAfterGroupsIfAnyAreGiven) { - YAML::Node node = YAML::Load("{name: group1, after: [ other_group ]}"); - Group group = node.as(); - - std::vector expectedAfterGroups = {"other_group"}; - EXPECT_EQ("group1", group.GetName()); - EXPECT_EQ(expectedAfterGroups, group.GetAfterGroups()); -} - -TEST(Group, decodingFromYamlShouldThrowIfTheNameKeyIsMissing) { - YAML::Node node = YAML::Load("{after: []}"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST(Group, decodingFromYamlShouldThrowIfAListIsGiven) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/metadata/location_test.h b/src/tests/api/interface/metadata/location_test.h similarity index 78% rename from src/tests/api/internals/metadata/location_test.h rename to src/tests/api/interface/metadata/location_test.h index edc761e6..3a00cc5f 100644 --- a/src/tests/api/internals/metadata/location_test.h +++ b/src/tests/api/interface/metadata/location_test.h @@ -22,16 +22,14 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_LOCATION_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_LOCATION_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_LOCATION_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_LOCATION_TEST #include -#include "api/metadata/yaml/location.h" #include "loot/metadata/location.h" -namespace loot { -namespace test { +namespace loot::test { TEST(Location, defaultConstructorShouldInitialiseEmptyStrings) { Location location; @@ -234,66 +232,6 @@ TEST( EXPECT_TRUE(location2 >= location1); EXPECT_FALSE(location1 >= location2); } - -TEST(Location, emittingAsYamlShouldOutputAScalarIfTheNameStringIsEmpty) { - Location location("http://www.example.com"); - YAML::Emitter emitter; - emitter << location; - - EXPECT_EQ("'" + location.GetURL() + "'", emitter.c_str()); -} - -TEST(Location, emittingAsYamlShouldOutputAMapIfTheNameStringIsNotEmpty) { - Location location("http://www.example.com", "example"); - YAML::Emitter emitter; - emitter << location; - - EXPECT_EQ( - "link: '" + location.GetURL() + "'\nname: '" + location.GetName() + "'", - emitter.c_str()); -} - -TEST(Location, encodingAsYamlShouldStoreDataCorrectly) { - Location location("http://www.example.com", "example"); - YAML::Node node; - node = location; - - EXPECT_EQ(location.GetURL(), node["link"].as()); - EXPECT_EQ(location.GetName(), node["name"].as()); -} - -TEST(Location, encodingAsYamlShouldOmitEmptyFields) { - Location location("http://www.example.com"); - YAML::Node node; - node = location; - - EXPECT_EQ(location.GetURL(), node["link"].as()); - EXPECT_FALSE(node["name"]); -} - -TEST(Location, decodingFromYamlShouldSetDataCorrectly) { - YAML::Node node = YAML::Load("{link: http://www.example.com, name: example}"); - Location location = node.as(); - - EXPECT_EQ(node["link"].as(), location.GetURL()); - EXPECT_EQ(node["name"].as(), location.GetName()); -} - -TEST(Location, - decodingFromYamlScalarShouldSetUrlToScalarValueAndLeaveNameEmpty) { - YAML::Node node = YAML::Load("http://www.example.com"); - Location location = node.as(); - - EXPECT_EQ(node.as(), location.GetURL()); - EXPECT_TRUE(location.GetName().empty()); -} - -TEST(Location, decodingFromYamlShouldThrowIfAListIsGiven) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/metadata/message_content_test.h b/src/tests/api/interface/metadata/message_content_test.h similarity index 87% rename from src/tests/api/internals/metadata/message_content_test.h rename to src/tests/api/interface/metadata/message_content_test.h index d17db0de..00826bf8 100644 --- a/src/tests/api/internals/metadata/message_content_test.h +++ b/src/tests/api/interface/metadata/message_content_test.h @@ -22,16 +22,14 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_CONTENT_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_CONTENT_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_MESSAGE_CONTENT_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_MESSAGE_CONTENT_TEST #include -#include "api/metadata/yaml/message_content.h" #include "loot/metadata/message_content.h" -namespace loot { -namespace test { +namespace loot::test { const std::string french = "fr"; TEST(MessageContent, defaultConstructorShouldSetEmptyEnglishLanguageString) { @@ -330,45 +328,6 @@ TEST( EXPECT_EQ("pt_PT", content.value().GetLanguage()); EXPECT_EQ("test3", content.value().GetText()); } - -TEST(MessageContent, emittingAsYamlShouldOutputDataCorrectly) { - MessageContent content("content", french); - YAML::Emitter emitter; - emitter << content; - - EXPECT_EQ("lang: " + french + "\ntext: '" + content.GetText() + "'", - emitter.c_str()); -} - -TEST(MessageContent, encodingAsYamlShouldOutputDataCorrectly) { - MessageContent content("content", french); - YAML::Node node; - node = content; - - EXPECT_EQ(content.GetText(), node["text"].as()); - EXPECT_EQ(french, node["lang"].as()); -} - -TEST(MessageContent, decodingFromYamlShouldSetDataCorrectly) { - YAML::Node node = YAML::Load("{text: content, lang: fr}"); - MessageContent content = node.as(); - - EXPECT_EQ("content", content.GetText()); - EXPECT_EQ(french, content.GetLanguage()); -} - -TEST(MessageContent, decodingFromYamlScalarShouldThrow) { - YAML::Node node = YAML::Load("scalar"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST(MessageContent, decodingFromYamlListShouldThrow) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/metadata/message_test.h b/src/tests/api/interface/metadata/message_test.h similarity index 53% rename from src/tests/api/internals/metadata/message_test.h rename to src/tests/api/interface/metadata/message_test.h index 8f12ca32..b55bc196 100644 --- a/src/tests/api/internals/metadata/message_test.h +++ b/src/tests/api/interface/metadata/message_test.h @@ -22,16 +22,13 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_MESSAGE_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_MESSAGE_TEST -#include "api/game/game.h" -#include "api/metadata/yaml/message.h" #include "loot/metadata/message.h" #include "tests/common_game_test_fixture.h" -namespace loot { -namespace test { +namespace loot::test { class MessageTest : public CommonGameTestFixture { protected: MessageTest() : CommonGameTestFixture(GameType::tes4) {} @@ -343,339 +340,6 @@ TEST_F( EXPECT_FALSE(message1 >= message2); EXPECT_TRUE(message2 >= message1); } - -TEST_F(MessageTest, emittingAsYamlShouldOutputNoteMessageTypeCorrectly) { - Message message(MessageType::say, "content1"); - YAML::Emitter emitter; - emitter << message; - - EXPECT_STREQ( - "type: say\n" - "content: 'content1'", - emitter.c_str()); -} - -TEST_F(MessageTest, emittingAsYamlShouldOutputWarnMessageTypeCorrectly) { - Message message(MessageType::warn, "content1"); - YAML::Emitter emitter; - emitter << message; - - EXPECT_STREQ( - "type: warn\n" - "content: 'content1'", - emitter.c_str()); -} - -TEST_F(MessageTest, emittingAsYamlShouldOutputErrorMessageTypeCorrectly) { - Message message(MessageType::error, "content1"); - YAML::Emitter emitter; - emitter << message; - - EXPECT_STREQ( - "type: error\n" - "content: 'content1'", - emitter.c_str()); -} - -TEST_F(MessageTest, emittingAsYamlShouldOutputConditionIfItIsNotEmpty) { - Message message(MessageType::say, "content1", "condition1"); - YAML::Emitter emitter; - emitter << message; - - EXPECT_STREQ( - "type: say\n" - "content: 'content1'\n" - "condition: 'condition1'", - emitter.c_str()); -} - -TEST_F(MessageTest, emittingAsYamlShouldOutputMultipleContentStringsAsAList) { - Message message(MessageType::say, - MessageContents({MessageContent("content1"), - MessageContent("content2", french)})); - YAML::Emitter emitter; - emitter << message; - - EXPECT_STREQ( - "type: say\n" - "content:\n" - " - lang: en\n" - " text: 'content1'\n" - " - lang: fr\n" - " text: 'content2'", - emitter.c_str()); -} - -TEST_F(MessageTest, encodingAsYamlShouldStoreNoteMessageTypeCorrectly) { - Message message(MessageType::say, "content1"); - YAML::Node node; - node = message; - - EXPECT_EQ("say", node["type"].as()); -} - -TEST_F(MessageTest, encodingAsYamlShouldStoreWarningMessageTypeCorrectly) { - Message message(MessageType::warn, "content1"); - YAML::Node node; - node = message; - - EXPECT_EQ("warn", node["type"].as()); -} - -TEST_F(MessageTest, encodingAsYamlShouldStoreErrorMessageTypeCorrectly) { - Message message(MessageType::error, "content1"); - YAML::Node node; - node = message; - - EXPECT_EQ("error", node["type"].as()); -} - -TEST_F(MessageTest, encodingAsYamlShouldOmitConditionFieldIfItIsEmpty) { - Message message(MessageType::say, "content1"); - YAML::Node node; - node = message; - - EXPECT_FALSE(node["condition"]); -} - -TEST_F(MessageTest, encodingAsYamlShouldStoreConditionFieldIfItIsNotEmpty) { - Message message(MessageType::say, "content1", "condition1"); - YAML::Node node; - node = message; - - EXPECT_EQ("condition1", node["condition"].as()); -} - -TEST_F(MessageTest, encodingAsYamlShouldStoreASingleContentStringInAVector) { - Message message(MessageType::say, "content1"); - YAML::Node node; - node = message; - - EXPECT_EQ(message.GetContent(), node["content"].as()); -} - -TEST_F(MessageTest, encodingAsYamlShouldMultipleContentStringsInAVector) { - MessageContents contents({ - MessageContent("content1"), - MessageContent("content2", french), - }); - Message message(MessageType::say, contents); - YAML::Node node; - node = message; - - EXPECT_EQ(contents, node["content"].as()); -} - -TEST_F(MessageTest, decodingFromYamlShouldSetNoteTypeCorrectly) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content1"); - Message message = node.as(); - - EXPECT_EQ(MessageType::say, message.GetType()); -} - -TEST_F(MessageTest, decodingFromYamlShouldSetWarningTypeCorrectly) { - YAML::Node node = YAML::Load( - "type: warn\n" - "content: content1"); - Message message = node.as(); - - EXPECT_EQ(MessageType::warn, message.GetType()); -} - -TEST_F(MessageTest, decodingFromYamlShouldSetErrorTypeCorrectly) { - YAML::Node node = YAML::Load( - "type: error\n" - "content: content1"); - Message message = node.as(); - - EXPECT_EQ(MessageType::error, message.GetType()); -} - -TEST_F(MessageTest, decodingFromYamlShouldHandleAnUnrecognisedTypeAsANote) { - YAML::Node node = YAML::Load( - "type: invalid\n" - "content: content1"); - Message message = node.as(); - - EXPECT_EQ(MessageType::say, message.GetType()); -} - -TEST_F(MessageTest, - decodingFromYamlShouldLeaveTheConditionEmptyIfNoneIsPresent) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content1"); - Message message = node.as(); - - EXPECT_TRUE(message.GetCondition().empty()); -} - -TEST_F(MessageTest, decodingFromYamlShouldStoreANonEmptyConditionField) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content1\n" - "condition: 'file(\"Foo.esp\")'"); - Message message = node.as(); - - EXPECT_EQ("file(\"Foo.esp\")", message.GetCondition()); -} - -TEST_F(MessageTest, decodingFromYamlShouldStoreAScalarContentValueCorrectly) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content1\n"); - Message message = node.as(); - MessageContents expectedContent({MessageContent("content1")}); - - EXPECT_EQ(expectedContent, message.GetContent()); -} - -TEST_F(MessageTest, decodingFromYamlShouldStoreAListOfContentStringsCorrectly) { - YAML::Node node = YAML::Load( - "type: say\n" - "content:\n" - " - lang: en\n" - " text: content1\n" - " - lang: fr\n" - " text: content2"); - Message message = node.as(); - - EXPECT_EQ(MessageContents({ - MessageContent("content1"), - MessageContent("content2", french), - }), - message.GetContent()); -} - -TEST_F(MessageTest, - decodingFromYamlShouldNotThrowIfTheOnlyContentStringIsNotEnglish) { - YAML::Node node = YAML::Load( - "type: say\n" - "content:\n" - " - lang: fr\n" - " text: content1"); - - EXPECT_NO_THROW(Message message = node.as()); -} - -TEST_F( - MessageTest, - decodingFromYamlShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { - YAML::Node node = YAML::Load( - "type: say\n" - "content:\n" - " - lang: de\n" - " text: content1\n" - " - lang: fr\n" - " text: content2"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST_F( - MessageTest, - decodingFromYamlShouldApplySubstitutionsWhenThereIsOnlyOneContentString) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: con{0}tent1\n" - "subs:\n" - " - sub1"); - Message message = node.as(); - - EXPECT_EQ(MessageContents({MessageContent("consub1tent1")}), - message.GetContent()); -} - -TEST_F(MessageTest, - decodingFromYamlShouldApplySubstitutionsToAllContentStrings) { - YAML::Node node = YAML::Load( - "type: say\n" - "content:\n" - " - lang: en\n" - " text: content1 {0}\n" - " - lang: fr\n" - " text: content2 {0}\n" - "subs:\n" - " - sub"); - Message message = node.as(); - - EXPECT_EQ(MessageContents({ - MessageContent("content1 sub"), - MessageContent("content2 sub", french), - }), - message.GetContent()); -} - -TEST_F( - MessageTest, - decodingFromYamlShouldThrowIfTheContentStringExpectsMoreSubstitutionsThanExist) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: '{0} {1}'\n" - "subs:\n" - " - sub1"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -// Don't throw because no subs are given, so none are expected in the content -// string. -TEST_F(MessageTest, - decodingFromYamlShouldIgnoreSubstitutionSyntaxIfNoSubstitutionsExist) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: con{0}tent1\n"); - Message message = node.as(); - - EXPECT_EQ(MessageContents({MessageContent("con{0}tent1")}), - message.GetContent()); -} - -TEST_F(MessageTest, decodingFromYamlShouldAcceptPercentagePlaceholderSyntax) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content %1% %2% %3% %4% %5% %6% %7% %8% %9% %10% %11%\n" - "subs:\n" - " - a\n" - " - b\n" - " - c\n" - " - d\n" - " - e\n" - " - f\n" - " - g\n" - " - h\n" - " - i\n" - " - j\n" - " - k"); - Message message = node.as(); - - ASSERT_EQ(1, message.GetContent().size()); - EXPECT_EQ("content a b c d e f g h i j k", message.GetContent()[0].GetText()); -} - -TEST_F(MessageTest, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { - YAML::Node node = YAML::Load( - "type: say\n" - "content: content1\n" - "condition: invalid"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST_F(MessageTest, decodingFromYamlShouldThrowIfAScalarIsGiven) { - YAML::Node node = YAML::Load("scalar"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST_F(MessageTest, decodingFromYamlShouldThrowIfAListIsGiven) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/metadata/plugin_cleaning_data_test.h b/src/tests/api/interface/metadata/plugin_cleaning_data_test.h similarity index 75% rename from src/tests/api/internals/metadata/plugin_cleaning_data_test.h rename to src/tests/api/interface/metadata/plugin_cleaning_data_test.h index ac017c02..0d8a6d9c 100644 --- a/src/tests/api/internals/metadata/plugin_cleaning_data_test.h +++ b/src/tests/api/interface/metadata/plugin_cleaning_data_test.h @@ -22,16 +22,13 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_PLUGIN_CLEANING_DATA -#define LOOT_TESTS_API_INTERNALS_METADATA_PLUGIN_CLEANING_DATA +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_PLUGIN_CLEANING_DATA_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_PLUGIN_CLEANING_DATA_TEST -#include "api/game/game.h" -#include "api/metadata/yaml/plugin_cleaning_data.h" #include "loot/metadata/plugin_cleaning_data.h" #include "tests/common_game_test_fixture.h" -namespace loot { -namespace test { +namespace loot::test { class PluginCleaningDataTest : public CommonGameTestFixture { protected: PluginCleaningDataTest() : @@ -311,120 +308,6 @@ TEST_F( EXPECT_FALSE(info1 > info2); EXPECT_TRUE(info2 > info1); } - -TEST_F(PluginCleaningDataTest, emittingAsYamlShouldOutputAllNonZeroCounts) { - PluginCleaningData info(0x12345678, "cleaner", info_, 2, 10, 30); - YAML::Emitter emitter; - emitter << info; - - EXPECT_STREQ( - "crc: 0x12345678\nutil: 'cleaner'\ndetail: 'info'\nitm: 2\nudr: 10\nnav: " - "30", - emitter.c_str()); -} - -TEST_F(PluginCleaningDataTest, emittingAsYamlShouldOmitAllZeroCounts) { - PluginCleaningData info(0x12345678, "cleaner", info_, 0, 0, 0); - YAML::Emitter emitter; - emitter << info; - - EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\ndetail: 'info'", - emitter.c_str()); -} - -TEST_F(PluginCleaningDataTest, encodingAsYamlShouldOmitAllZeroCountFields) { - PluginCleaningData info(0x12345678, "cleaner", info_, 0, 0, 0); - YAML::Node node; - node = info; - - EXPECT_EQ(0x12345678u, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_EQ(info_, node["detail"].as>()); - EXPECT_FALSE(node["itm"]); - EXPECT_FALSE(node["udr"]); - EXPECT_FALSE(node["nav"]); -} - -TEST_F(PluginCleaningDataTest, - encodingAsYamlShouldOutputAllNonZeroCountFields) { - PluginCleaningData info(0x12345678, "cleaner", info_, 2, 10, 30); - YAML::Node node; - node = info; - - EXPECT_EQ(0x12345678u, node["crc"].as()); - EXPECT_EQ("cleaner", node["util"].as()); - EXPECT_EQ(info_, node["detail"].as>()); - EXPECT_EQ(2u, node["itm"].as()); - EXPECT_EQ(10u, node["udr"].as()); - EXPECT_EQ(30u, node["nav"].as()); -} - -TEST_F(PluginCleaningDataTest, - decodingFromYamlShouldLeaveMissingFieldsWithZeroValues) { - YAML::Node node = YAML::Load("{crc: 0x12345678, util: cleaner}"); - PluginCleaningData info = node.as(); - - EXPECT_EQ(0x12345678u, info.GetCRC()); - EXPECT_TRUE(info.GetDetail().empty()); - EXPECT_EQ(0u, info.GetITMCount()); - EXPECT_EQ(0u, info.GetDeletedReferenceCount()); - EXPECT_EQ(0u, info.GetDeletedNavmeshCount()); - EXPECT_EQ("cleaner", info.GetCleaningUtility()); -} - -TEST_F(PluginCleaningDataTest, decodingFromYamlShouldStoreAllNonZeroCounts) { - YAML::Node node = YAML::Load( - "{crc: 0x12345678, util: cleaner, detail: info, itm: 2, udr: 10, nav: " - "30}"); - PluginCleaningData info = node.as(); - - EXPECT_EQ(0x12345678u, info.GetCRC()); - EXPECT_EQ(info_, info.GetDetail()); - EXPECT_EQ(2u, info.GetITMCount()); - EXPECT_EQ(10u, info.GetDeletedReferenceCount()); - EXPECT_EQ(30u, info.GetDeletedNavmeshCount()); - EXPECT_EQ("cleaner", info.GetCleaningUtility()); -} - -TEST_F(PluginCleaningDataTest, - decodingFromYamlShouldNotThrowIfTheOnlyDetailStringIsNotEnglish) { - YAML::Node node = YAML::Load( - "crc: 0x12345678\n" - "util: cleaner\n" - "detail:\n" - " - lang: fr\n" - " text: content1"); - - EXPECT_NO_THROW(node.as()); -} - -TEST_F( - PluginCleaningDataTest, - decodingFromYamlShouldThrowIfMultipleDetailStringsAreGivenAndNoneAreEnglish) { - YAML::Node node = YAML::Load( - "crc: 0x12345678\n" - "util: cleaner\n" - "detail:\n" - " - lang: de\n" - " text: content1\n" - " - lang: fr\n" - " text: content2"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST_F(PluginCleaningDataTest, decodingFromYamlScalarShouldThrow) { - YAML::Node node = YAML::Load("scalar"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST_F(PluginCleaningDataTest, decodingFromYamlListShouldThrow) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/interface/metadata/plugin_metadata_test.h b/src/tests/api/interface/metadata/plugin_metadata_test.h new file mode 100644 index 00000000..54f7dfd7 --- /dev/null +++ b/src/tests/api/interface/metadata/plugin_metadata_test.h @@ -0,0 +1,395 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_PLUGIN_METADATA_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_PLUGIN_METADATA_TEST + +#include "loot/metadata/plugin_metadata.h" +#include "tests/common_game_test_fixture.h" + +namespace loot::test { +class PluginMetadataTest : public CommonGameTestFixture { +protected: + PluginMetadataTest() : + CommonGameTestFixture(GameType::tes5), + info_(std::vector({ + MessageContent("info"), + })) {} + + const std::vector info_; +}; + +TEST_F( + PluginMetadataTest, + defaultConstructorShouldLeaveNameEmptyAndEnableMetadataAndLeaveGroupUnset) { + PluginMetadata plugin; + + EXPECT_TRUE(plugin.GetName().empty()); + EXPECT_FALSE(plugin.GetGroup()); +} + +TEST_F( + PluginMetadataTest, + stringConstructorShouldSetNameToGivenStringAndEnableMetadataAndLeaveGroupUnset) { + PluginMetadata plugin(blankEsm); + + EXPECT_EQ(blankEsm, plugin.GetName()); + EXPECT_FALSE(plugin.GetGroup()); +} + +TEST_F(PluginMetadataTest, + nameMatchesShouldUseCaseInsensitiveNameComparisonForNonRegexNames) { + PluginMetadata plugin(blankEsm); + + EXPECT_TRUE(plugin.NameMatches(boost::to_lower_copy(blankEsm))); + EXPECT_FALSE(plugin.NameMatches(blankDifferentEsm)); +} + +TEST_F(PluginMetadataTest, + nameMatchesShouldTreatGivenPluginNameStringsAsLiterals) { + PluginMetadata plugin(blankEsm); + std::string regex = "blan.\\.esm"; + + EXPECT_FALSE(plugin.NameMatches(regex)); +} + +TEST_F(PluginMetadataTest, + nameMatchesShouldUseCaseInsensitiveRegexMatchingForARegexName) { + PluginMetadata plugin("Blan.\\.esm"); + + EXPECT_TRUE(plugin.NameMatches(boost::to_lower_copy(blankEsm))); + EXPECT_FALSE(plugin.NameMatches(blankDifferentEsm)); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldNotChangeName) { + PluginMetadata plugin1(blankEsm); + PluginMetadata plugin2(blankDifferentEsm); + + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(blankEsm, plugin1.GetName()); +} + +TEST_F(PluginMetadataTest, + mergeMetadataShouldNotUseMergedGroupIfItAndCurrentGroupAreBothExplicit) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.SetGroup("group1"); + plugin2.SetGroup("group2"); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ("group1", plugin1.GetGroup()); +} + +TEST_F(PluginMetadataTest, + mergeMetadataShouldNotUseMergedGroupIfItAndCurrentGroupAreBothImplicit) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.MergeMetadata(plugin2); + + EXPECT_FALSE(plugin1.GetGroup().has_value()); +} + +TEST_F( + PluginMetadataTest, + mergeMetadataShouldNotUseMergedGroupIfItIsImplicitAndCurrentGroupIsExplicit) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin1.SetGroup("group1"); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ("group1", plugin1.GetGroup()); +} + +TEST_F( + PluginMetadataTest, + mergeMetadataShouldUseMergedGroupIfItIsExplicitAndCurrentGroupIsImplicit) { + PluginMetadata plugin1; + PluginMetadata plugin2; + + plugin2.SetGroup("group2"); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ("group2", plugin1.GetGroup()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeLoadAfterData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.SetLoadAfterFiles({file1}); + plugin2.SetLoadAfterFiles({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({file1, file2}), plugin1.GetLoadAfterFiles()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeRequirementData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.SetRequirements({file1}); + plugin2.SetRequirements({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({file1, file2}), plugin1.GetRequirements()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeIncompatibilityData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + File file1(blankEsm); + File file2(blankDifferentEsm); + + plugin1.SetIncompatibilities({file1}); + plugin2.SetIncompatibilities({file1, file2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({file1, file2}), plugin1.GetIncompatibilities()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeMessages) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Message message(MessageType::say, "content"); + + plugin1.SetMessages({message}); + plugin2.SetMessages({message}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({message, message}), plugin1.GetMessages()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeTags) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Tag tag1("Relev"); + Tag tag2("Relev", false); + Tag tag3("Delev"); + + plugin1.SetTags({tag1}); + plugin2.SetTags({tag1, tag2, tag3}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({tag1, tag2, tag3}), plugin1.GetTags()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeDirtyInfoData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + PluginCleaningData info1(0x5, "utility", info_, 1, 2, 3); + PluginCleaningData info2(0xA, "utility", info_, 1, 2, 3); + + plugin1.SetDirtyInfo({info1}); + plugin2.SetDirtyInfo({info1, info2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({info1, info2}), + plugin1.GetDirtyInfo()); +} +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeCleanInfoData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + PluginCleaningData info1(0x5, "utility"); + PluginCleaningData info2(0xA, "utility"); + + plugin1.SetCleanInfo({info1}); + plugin2.SetCleanInfo({info1, info2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({info1, info2}), + plugin1.GetCleanInfo()); +} + +TEST_F(PluginMetadataTest, mergeMetadataShouldMergeLocationData) { + PluginMetadata plugin1; + PluginMetadata plugin2; + Location location1("http://www.example.com/1"); + Location location2("http://www.example.com/2"); + + plugin1.SetLocations({location1}); + plugin2.SetLocations({location1, location2}); + plugin1.MergeMetadata(plugin2); + + EXPECT_EQ(std::vector({location1, location2}), + plugin1.GetLocations()); +} + +TEST_F(PluginMetadataTest, unsetGroupShouldLeaveNoGroupValueSet) { + PluginMetadata plugin; + EXPECT_FALSE(plugin.GetGroup().has_value()); + + plugin.SetGroup("test"); + EXPECT_EQ("test", plugin.GetGroup().value()); + + plugin.UnsetGroup(); + EXPECT_FALSE(plugin.GetGroup().has_value()); +} + +TEST_F(PluginMetadataTest, + hasNameOnlyShouldBeTrueForADefaultConstructedPluginMetadataObject) { + PluginMetadata plugin; + + EXPECT_TRUE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, + hasNameOnlyShouldBeTrueForAPluginMetadataObjectConstructedWithAName) { + PluginMetadata plugin(blankEsp); + + EXPECT_TRUE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfTheGroupIsExplicit) { + PluginMetadata plugin; + plugin.SetGroup("group"); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLoadAfterMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.SetLoadAfterFiles({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, + hasNameOnlyShouldBeFalseIfRequirementMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.SetRequirements({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, + hasNameOnlyShouldBeFalseIfIncompatibilityMetadataExists) { + PluginMetadata plugin(blankEsp); + plugin.SetIncompatibilities({File(blankEsm)}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfMessagesExist) { + PluginMetadata plugin(blankEsp); + plugin.SetMessages({Message(MessageType::say, "content")}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfTagsExist) { + PluginMetadata plugin(blankEsp); + plugin.SetTags({Tag("Relev")}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfDirtyInfoExists) { + PluginMetadata plugin(blankEsp); + plugin.SetDirtyInfo({PluginCleaningData(5, "utility", info_, 0, 1, 2)}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfCleanInfoExists) { + PluginMetadata plugin(blankEsp); + plugin.SetCleanInfo({PluginCleaningData(5, "utility")}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLocationsExist) { + PluginMetadata plugin(blankEsp); + plugin.SetLocations({Location("http://www.example.com")}); + + EXPECT_FALSE(plugin.HasNameOnly()); +} + +TEST_F(PluginMetadataTest, isRegexPluginShouldBeFalseForAnEmptyPluginName) { + PluginMetadata plugin; + + EXPECT_FALSE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, isRegexPluginShouldBeFalseForAnExactPluginFilename) { + PluginMetadata plugin(blankEsm); + + EXPECT_FALSE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + isRegexPluginShouldBeTrueIfThePluginNameContainsAColon) { + PluginMetadata plugin("Blank:.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + isRegexPluginShouldBeTrueIfThePluginNameContainsABackslash) { + PluginMetadata plugin("Blank\\.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + isRegexPluginShouldBeTrueIfThePluginNameContainsAnAsterisk) { + PluginMetadata plugin("Blank*.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + isRegexPluginShouldBeTrueIfThePluginNameContainsAQuestionMark) { + PluginMetadata plugin("Blank?.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + isRegexPluginShouldBeTrueIfThePluginNameContainsAVerticalBar) { + PluginMetadata plugin("Blank|.esm"); + + EXPECT_TRUE(plugin.IsRegexPlugin()); +} + +TEST_F(PluginMetadataTest, + asYamlShouldReturnAStringContainingTheMetadataEmittedAsYaml) { + PluginMetadata plugin(blankEsm); + plugin.SetLoadAfterFiles({File(blankEsm)}); + + EXPECT_EQ( + "name: 'Blank.esm'\n" + "after: ['Blank.esm']", + plugin.AsYaml()); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/tag_test.h b/src/tests/api/interface/metadata/tag_test.h similarity index 68% rename from src/tests/api/internals/metadata/tag_test.h rename to src/tests/api/interface/metadata/tag_test.h index 01a2bd01..39836935 100644 --- a/src/tests/api/internals/metadata/tag_test.h +++ b/src/tests/api/interface/metadata/tag_test.h @@ -22,16 +22,14 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_TAG_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_TAG_TEST +#ifndef LOOT_TESTS_API_INTERFACE_METADATA_TAG_TEST +#define LOOT_TESTS_API_INTERFACE_METADATA_TAG_TEST #include -#include "api/metadata/yaml/tag.h" #include "loot/metadata/tag.h" -namespace loot { -namespace test { +namespace loot::test { TEST(Tag, defaultConstructorShouldSetEmptyNameAndConditionStringsForATagAddition) { Tag tag; @@ -284,112 +282,6 @@ TEST( EXPECT_FALSE(tag1 >= tag2); EXPECT_TRUE(tag2 >= tag1); } - -TEST( - Tag, - emittingAsYamlShouldOutputOnlyTheNameStringIfTheTagIsAnAdditionWithNoCondition) { - Tag tag("name1"); - YAML::Emitter emitter; - emitter << tag; - - EXPECT_EQ(tag.GetName(), emitter.c_str()); -} - -TEST( - Tag, - emittingAsYamlShouldOutputOnlyTheNameStringPrefixedWithAHyphenIfTheTagIsARemovalWithNoCondition) { - Tag tag("name1", false); - YAML::Emitter emitter; - emitter << tag; - - EXPECT_EQ("-" + tag.GetName(), emitter.c_str()); -} - -TEST(Tag, emittingAsYamlShouldOutputAMapIfTheTagHasACondition) { - Tag tag("name1", false, "condition1"); - YAML::Emitter emitter; - emitter << tag; - - EXPECT_STREQ("name: -name1\ncondition: 'condition1'", emitter.c_str()); -} - -TEST(Tag, - encodingAsYamlShouldOmitTheConditionFieldIfTheConditionStringIsEmpty) { - Tag tag; - YAML::Node node; - node = tag; - - EXPECT_FALSE(node["condition"]); -} - -TEST(Tag, encodingAsYamlShouldOutputTheNameFieldCorrectly) { - Tag tag("name1"); - YAML::Node node; - node = tag; - - EXPECT_EQ(tag.GetName(), node["name"].as()); -} - -TEST( - Tag, - encodingAsYamlShouldOutputTheNameFieldWithAHyphenPrefixIfTheTagIsARemoval) { - Tag tag("name1", false); - YAML::Node node; - node = tag; - - EXPECT_EQ("-" + tag.GetName(), node["name"].as()); -} - -TEST( - Tag, - encodingAsYamlShouldOutputTheConditionFieldIfTheConditionStringIsNotEmpty) { - Tag tag("name1", true, "condition1"); - YAML::Node node; - node = tag; - - EXPECT_EQ(tag.GetName(), node["name"].as()); - EXPECT_EQ(tag.GetCondition(), node["condition"].as()); -} - -TEST(Tag, decodingFromYamlScalarShouldSetNameCorrectly) { - YAML::Node node = YAML::Load("name1"); - Tag tag = node.as(); - - EXPECT_EQ("name1", tag.GetName()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("", tag.GetCondition()); -} - -TEST(Tag, decodingFromYamlScalarShouldSetAdditionStateCorrectly) { - YAML::Node node = YAML::Load("-name1"); - Tag tag = node.as(); - - EXPECT_EQ("name1", tag.GetName()); - EXPECT_FALSE(tag.IsAddition()); - EXPECT_EQ("", tag.GetCondition()); -} - -TEST(Tag, decodingFromYamlMapShouldSetDataCorrectly) { - YAML::Node node = YAML::Load("{name: name1, condition: 'file(\"Foo.esp\")'}"); - Tag tag = node.as(); - - EXPECT_EQ("name1", tag.GetName()); - EXPECT_TRUE(tag.IsAddition()); - EXPECT_EQ("file(\"Foo.esp\")", tag.GetCondition()); -} - -TEST(Tag, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { - YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} - -TEST(Tag, decodingFromYamlListShouldThrow) { - YAML::Node node = YAML::Load("[0, 1, 2]"); - - EXPECT_THROW(node.as(), YAML::RepresentationException); -} -} } #endif diff --git a/src/tests/api/internals/main.cpp b/src/tests/api/internals/main.cpp index 8e0cdc71..0850b60e 100644 --- a/src/tests/api/internals/main.cpp +++ b/src/tests/api/internals/main.cpp @@ -29,15 +29,14 @@ #include "tests/api/internals/helpers/crc_test.h" #include "tests/api/internals/helpers/text_test.h" #include "tests/api/internals/metadata/condition_evaluator_test.h" -#include "tests/api/internals/metadata/conditional_metadata_test.h" -#include "tests/api/internals/metadata/file_test.h" -#include "tests/api/internals/metadata/group_test.h" -#include "tests/api/internals/metadata/location_test.h" -#include "tests/api/internals/metadata/message_content_test.h" -#include "tests/api/internals/metadata/message_test.h" -#include "tests/api/internals/metadata/plugin_cleaning_data_test.h" -#include "tests/api/internals/metadata/plugin_metadata_test.h" -#include "tests/api/internals/metadata/tag_test.h" +#include "tests/api/internals/metadata/yaml/file_test.h" +#include "tests/api/internals/metadata/yaml/group_test.h" +#include "tests/api/internals/metadata/yaml/location_test.h" +#include "tests/api/internals/metadata/yaml/message_content_test.h" +#include "tests/api/internals/metadata/yaml/message_test.h" +#include "tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h" +#include "tests/api/internals/metadata/yaml/plugin_metadata_test.h" +#include "tests/api/internals/metadata/yaml/tag_test.h" #include "tests/api/internals/metadata_list_test.h" #include "tests/api/internals/plugin_test.h" #include "tests/api/internals/sorting/group_sort_test.h" diff --git a/src/tests/api/internals/metadata/yaml/file_test.h b/src/tests/api/internals/metadata/yaml/file_test.h new file mode 100644 index 00000000..d00986f6 --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/file_test.h @@ -0,0 +1,201 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_FILE_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_FILE_TEST + +#include + +#include "api/metadata/yaml/file.h" + +namespace loot::test { +TEST(File, emittingAsYamlShouldSingleQuoteValues) { + File file("name1", + "display1", + "condition1", + {MessageContent("english", "en")}, + "constraint1"); + YAML::Emitter emitter; + emitter << file; + std::string expected = "name: '" + std::string(file.GetName()) + + "'\ncondition: '" + file.GetCondition() + + "'\ndisplay: '" + file.GetDisplayName() + + "'\nconstraint: '" + file.GetConstraint() + + "'\ndetail: '" + file.GetDetail()[0].GetText() + "'"; + + EXPECT_EQ(expected, emitter.c_str()); +} + +TEST(File, emittingAsYamlShouldOutputAsAScalarIfOnlyTheNameStringIsNotEmpty) { + File file("file.esp"); + YAML::Emitter emitter; + emitter << file; + + EXPECT_EQ("'" + std::string(file.GetName()) + "'", emitter.c_str()); +} + +TEST(File, emittingAsYamlShouldOmitEmptyConditionAndConstraintStrings) { + File file("name1", "display1"); + YAML::Emitter emitter; + emitter << file; + std::string expected = "name: '" + std::string(file.GetName()) + + "'\ndisplay: '" + file.GetDisplayName() + "'"; + + EXPECT_EQ(expected, emitter.c_str()); +} + +TEST( + File, + emittingAsYamlShouldWriteDetailAsAListIfTheVectorContainsMoreThanOneElement) { + File file("", + "", + "", + {MessageContent("english", "en"), MessageContent("french", "fr")}); + YAML::Emitter emitter; + emitter << file; + std::string expected = + "name: ''\n" + "detail:\n" + " - lang: en\n" + " text: 'english'\n" + " - lang: fr\n" + " text: 'french'"; + + EXPECT_EQ(expected, emitter.c_str()); +} + +TEST(File, encodingAsYamlShouldStoreDataCorrectly) { + auto detail = {MessageContent("english", "en"), + MessageContent("french", "fr")}; + File file("name1", "display1", "condition1", detail, "constraint1"); + YAML::Node node; + node = file; + + EXPECT_EQ(std::string(file.GetName()), node["name"].as()); + EXPECT_EQ(file.GetDisplayName(), node["display"].as()); + EXPECT_EQ(file.GetCondition(), node["condition"].as()); + EXPECT_EQ(file.GetDetail(), node["detail"].as>()); + EXPECT_EQ(file.GetConstraint(), node["constraint"].as()); +} + +TEST(File, encodingAsYamlShouldOmitEmptyFields) { + File file("file.esp"); + YAML::Node node; + node = file; + + EXPECT_EQ(std::string(file.GetName()), node["name"].as()); + EXPECT_FALSE(node["display"]); + EXPECT_FALSE(node["condition"]); + EXPECT_FALSE(node["detail"]); +} + +TEST(File, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load( + "{name: name1, display: display1, condition: 'file(\"Foo.esp\")', " + "detail: 'details', constraint: 'file(\"Bar.esp\")'}"); + File file = node.as(); + + std::vector expectedDetail = { + MessageContent("details", "en")}; + + EXPECT_EQ(node["name"].as(), std::string(file.GetName())); + EXPECT_EQ(node["display"].as(), file.GetDisplayName()); + EXPECT_EQ(node["condition"].as(), file.GetCondition()); + EXPECT_EQ(expectedDetail, file.GetDetail()); + EXPECT_EQ(node["constraint"].as(), file.GetConstraint()); +} + +TEST(File, + decodingFromYamlWithMissingConditionFieldShouldLeaveConditionStringEmpty) { + YAML::Node node = YAML::Load("{name: name1, display: display1}"); + File file = node.as(); + + EXPECT_EQ(node["name"].as(), std::string(file.GetName())); + EXPECT_EQ(node["display"].as(), file.GetDisplayName()); + EXPECT_TRUE(file.GetCondition().empty()); + EXPECT_TRUE(file.GetDetail().empty()); + EXPECT_TRUE(file.GetConstraint().empty()); +} + +TEST(File, decodingFromYamlWithAListOfMessageContentDetailsShouldReadThemAll) { + YAML::Node node = YAML::Load( + "{name: name1, display: display1, condition: 'file(\"Foo.esp\")', " + "detail: [{text: english, lang: en}, {text: french, lang: fr}]}"); + File file = node.as(); + + std::vector expectedDetail = {MessageContent("english", "en"), + MessageContent("french", "fr")}; + + EXPECT_EQ(expectedDetail, file.GetDetail()); +} + +TEST(File, decodingFromYamlShouldNotThrowIfTheOnlyDetailStringIsNotEnglish) { + YAML::Node node = YAML::Load( + "name: name1\n" + "detail:\n" + " - lang: fr\n" + " text: content1"); + + EXPECT_NO_THROW(node.as()); +} + +TEST( + File, + decodingFromYamlShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { + YAML::Node node = YAML::Load( + "name: name1\n" + "detail:\n" + " - lang: de\n" + " text: content1\n" + " - lang: fr\n" + " text: content2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST(File, decodingFromYamlScalarShouldLeaveDisplayNameAndConditionEmpty) { + YAML::Node node = YAML::Load("name1"); + File file = node.as(); + + EXPECT_EQ(node.as(), std::string(file.GetName())); + EXPECT_TRUE(file.GetDisplayName().empty()); + EXPECT_TRUE(file.GetCondition().empty()); + EXPECT_TRUE(file.GetDetail().empty()); + EXPECT_TRUE(file.GetConstraint().empty()); +} + +TEST(File, decodingFromYamlShouldThrowIfAnInvalidMapIsGiven) { + YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST(File, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/yaml/group_test.h b/src/tests/api/internals/metadata/yaml/group_test.h new file mode 100644 index 00000000..90e44358 --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/group_test.h @@ -0,0 +1,142 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_GROUP_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_GROUP_TEST + +#include + +#include "api/metadata/yaml/group.h" + +namespace loot::test { +TEST(Group, emittingAsYamlShouldOmitAfterKeyIfAfterGroupsIsEmpty) { + Group group; + + YAML::Emitter emitter; + emitter << group; + + EXPECT_STREQ("name: 'default'", emitter.c_str()); +} + +TEST(Group, emittingAsYamlShouldIncludeDescriptionKeyIfDescriptionIsNotEmpty) { + Group group("group1", {}, "test"); + + YAML::Emitter emitter; + emitter << group; + + EXPECT_STREQ( + "name: 'group1'\n" + "description: 'test'", + emitter.c_str()); +} + +TEST(Group, emittingAsYamlShouldIncludeAfterKeyIfAfterGroupsIsNotEmpty) { + Group group("group1", {"other_group"}); + + YAML::Emitter emitter; + emitter << group; + + EXPECT_STREQ( + "name: 'group1'\n" + "after:\n" + " - other_group", + emitter.c_str()); +} + +TEST(Group, encodingAsYamlShouldOmitDescriptionKeyIfDescriptionIsEmpty) { + Group group; + YAML::Node node; + node = group; + + EXPECT_EQ("default", node["name"].as()); + EXPECT_FALSE(node["description"]); +} + +TEST(Group, encodingAsYamlShouldIncludeDescriptionKeyIfDescriptionIsNotEmpty) { + Group group("group1", {}, "test"); + YAML::Node node; + node = group; + + EXPECT_EQ("group1", node["name"].as()); + EXPECT_EQ("test", node["description"].as()); +} + +TEST(Group, encodingAsYamlShouldOmitAfterKeyIfAfterGroupsIsEmpty) { + Group group; + YAML::Node node; + node = group; + + EXPECT_EQ("default", node["name"].as()); + EXPECT_FALSE(node["after"]); +} + +TEST(Group, encodingAsYamlShouldIncludeAfterKeyIfAfterGroupsIsNotEmpty) { + Group group("group1", {"other_group"}); + YAML::Node node; + node = group; + + std::vector expectedAfterGroups = {"other_group"}; + EXPECT_EQ("group1", node["name"].as()); + EXPECT_EQ(expectedAfterGroups, node["after"].as>()); +} + +TEST(Group, decodingFromYamlShouldSetGivenName) { + YAML::Node node = YAML::Load("{name: group1}"); + Group group = node.as(); + + EXPECT_EQ("group1", group.GetName()); + EXPECT_TRUE(group.GetAfterGroups().empty()); +} + +TEST(Group, decodingFromYamlShouldSetDescriptionIfOneIsGiven) { + YAML::Node node = YAML::Load("{name: group1, description: test}"); + Group group = node.as(); + + EXPECT_EQ("group1", group.GetName()); + EXPECT_EQ("test", group.GetDescription()); +} + +TEST(Group, decodingFromYamlShouldSetAfterGroupsIfAnyAreGiven) { + YAML::Node node = YAML::Load("{name: group1, after: [ other_group ]}"); + Group group = node.as(); + + std::vector expectedAfterGroups = {"other_group"}; + EXPECT_EQ("group1", group.GetName()); + EXPECT_EQ(expectedAfterGroups, group.GetAfterGroups()); +} + +TEST(Group, decodingFromYamlShouldThrowIfTheNameKeyIsMissing) { + YAML::Node node = YAML::Load("{after: []}"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST(Group, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/yaml/location_test.h b/src/tests/api/internals/metadata/yaml/location_test.h new file mode 100644 index 00000000..5142e99f --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/location_test.h @@ -0,0 +1,93 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_LOCATION_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_LOCATION_TEST + +#include + +#include "api/metadata/yaml/location.h" + +namespace loot::test { +TEST(Location, emittingAsYamlShouldOutputAScalarIfTheNameStringIsEmpty) { + Location location("http://www.example.com"); + YAML::Emitter emitter; + emitter << location; + + EXPECT_EQ("'" + location.GetURL() + "'", emitter.c_str()); +} + +TEST(Location, emittingAsYamlShouldOutputAMapIfTheNameStringIsNotEmpty) { + Location location("http://www.example.com", "example"); + YAML::Emitter emitter; + emitter << location; + + EXPECT_EQ( + "link: '" + location.GetURL() + "'\nname: '" + location.GetName() + "'", + emitter.c_str()); +} + +TEST(Location, encodingAsYamlShouldStoreDataCorrectly) { + Location location("http://www.example.com", "example"); + YAML::Node node; + node = location; + + EXPECT_EQ(location.GetURL(), node["link"].as()); + EXPECT_EQ(location.GetName(), node["name"].as()); +} + +TEST(Location, encodingAsYamlShouldOmitEmptyFields) { + Location location("http://www.example.com"); + YAML::Node node; + node = location; + + EXPECT_EQ(location.GetURL(), node["link"].as()); + EXPECT_FALSE(node["name"]); +} + +TEST(Location, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{link: http://www.example.com, name: example}"); + Location location = node.as(); + + EXPECT_EQ(node["link"].as(), location.GetURL()); + EXPECT_EQ(node["name"].as(), location.GetName()); +} + +TEST(Location, + decodingFromYamlScalarShouldSetUrlToScalarValueAndLeaveNameEmpty) { + YAML::Node node = YAML::Load("http://www.example.com"); + Location location = node.as(); + + EXPECT_EQ(node.as(), location.GetURL()); + EXPECT_TRUE(location.GetName().empty()); +} + +TEST(Location, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/yaml/message_content_test.h b/src/tests/api/internals/metadata/yaml/message_content_test.h new file mode 100644 index 00000000..bf154267 --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/message_content_test.h @@ -0,0 +1,74 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_MESSAGE_CONTENT_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_MESSAGE_CONTENT_TEST + +#include + +#include "api/metadata/yaml/message_content.h" + +namespace loot::test { +const std::string french = "fr"; + +TEST(MessageContent, emittingAsYamlShouldOutputDataCorrectly) { + MessageContent content("content", french); + YAML::Emitter emitter; + emitter << content; + + EXPECT_EQ("lang: " + french + "\ntext: '" + content.GetText() + "'", + emitter.c_str()); +} + +TEST(MessageContent, encodingAsYamlShouldOutputDataCorrectly) { + MessageContent content("content", french); + YAML::Node node; + node = content; + + EXPECT_EQ(content.GetText(), node["text"].as()); + EXPECT_EQ(french, node["lang"].as()); +} + +TEST(MessageContent, decodingFromYamlShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{text: content, lang: fr}"); + MessageContent content = node.as(); + + EXPECT_EQ("content", content.GetText()); + EXPECT_EQ(french, content.GetLanguage()); +} + +TEST(MessageContent, decodingFromYamlScalarShouldThrow) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST(MessageContent, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/yaml/message_test.h b/src/tests/api/internals/metadata/yaml/message_test.h new file mode 100644 index 00000000..bea735fe --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/message_test.h @@ -0,0 +1,371 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_MESSAGE_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_MESSAGE_TEST + +#include "api/metadata/yaml/message.h" +#include "tests/common_game_test_fixture.h" + +namespace loot::test { +class MessageTest : public CommonGameTestFixture { +protected: + MessageTest() : CommonGameTestFixture(GameType::tes4) {} + typedef std::vector MessageContents; +}; + +TEST_F(MessageTest, emittingAsYamlShouldOutputNoteMessageTypeCorrectly) { + Message message(MessageType::say, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ( + "type: say\n" + "content: 'content1'", + emitter.c_str()); +} + +TEST_F(MessageTest, emittingAsYamlShouldOutputWarnMessageTypeCorrectly) { + Message message(MessageType::warn, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ( + "type: warn\n" + "content: 'content1'", + emitter.c_str()); +} + +TEST_F(MessageTest, emittingAsYamlShouldOutputErrorMessageTypeCorrectly) { + Message message(MessageType::error, "content1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ( + "type: error\n" + "content: 'content1'", + emitter.c_str()); +} + +TEST_F(MessageTest, emittingAsYamlShouldOutputConditionIfItIsNotEmpty) { + Message message(MessageType::say, "content1", "condition1"); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ( + "type: say\n" + "content: 'content1'\n" + "condition: 'condition1'", + emitter.c_str()); +} + +TEST_F(MessageTest, emittingAsYamlShouldOutputMultipleContentStringsAsAList) { + Message message(MessageType::say, + MessageContents({MessageContent("content1"), + MessageContent("content2", french)})); + YAML::Emitter emitter; + emitter << message; + + EXPECT_STREQ( + "type: say\n" + "content:\n" + " - lang: en\n" + " text: 'content1'\n" + " - lang: fr\n" + " text: 'content2'", + emitter.c_str()); +} + +TEST_F(MessageTest, encodingAsYamlShouldStoreNoteMessageTypeCorrectly) { + Message message(MessageType::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("say", node["type"].as()); +} + +TEST_F(MessageTest, encodingAsYamlShouldStoreWarningMessageTypeCorrectly) { + Message message(MessageType::warn, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("warn", node["type"].as()); +} + +TEST_F(MessageTest, encodingAsYamlShouldStoreErrorMessageTypeCorrectly) { + Message message(MessageType::error, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ("error", node["type"].as()); +} + +TEST_F(MessageTest, encodingAsYamlShouldOmitConditionFieldIfItIsEmpty) { + Message message(MessageType::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_FALSE(node["condition"]); +} + +TEST_F(MessageTest, encodingAsYamlShouldStoreConditionFieldIfItIsNotEmpty) { + Message message(MessageType::say, "content1", "condition1"); + YAML::Node node; + node = message; + + EXPECT_EQ("condition1", node["condition"].as()); +} + +TEST_F(MessageTest, encodingAsYamlShouldStoreASingleContentStringInAVector) { + Message message(MessageType::say, "content1"); + YAML::Node node; + node = message; + + EXPECT_EQ(message.GetContent(), node["content"].as()); +} + +TEST_F(MessageTest, encodingAsYamlShouldMultipleContentStringsInAVector) { + MessageContents contents({ + MessageContent("content1"), + MessageContent("content2", french), + }); + Message message(MessageType::say, contents); + YAML::Node node; + node = message; + + EXPECT_EQ(contents, node["content"].as()); +} + +TEST_F(MessageTest, decodingFromYamlShouldSetNoteTypeCorrectly) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(MessageType::say, message.GetType()); +} + +TEST_F(MessageTest, decodingFromYamlShouldSetWarningTypeCorrectly) { + YAML::Node node = YAML::Load( + "type: warn\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(MessageType::warn, message.GetType()); +} + +TEST_F(MessageTest, decodingFromYamlShouldSetErrorTypeCorrectly) { + YAML::Node node = YAML::Load( + "type: error\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(MessageType::error, message.GetType()); +} + +TEST_F(MessageTest, decodingFromYamlShouldHandleAnUnrecognisedTypeAsANote) { + YAML::Node node = YAML::Load( + "type: invalid\n" + "content: content1"); + Message message = node.as(); + + EXPECT_EQ(MessageType::say, message.GetType()); +} + +TEST_F(MessageTest, + decodingFromYamlShouldLeaveTheConditionEmptyIfNoneIsPresent) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content1"); + Message message = node.as(); + + EXPECT_TRUE(message.GetCondition().empty()); +} + +TEST_F(MessageTest, decodingFromYamlShouldStoreANonEmptyConditionField) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content1\n" + "condition: 'file(\"Foo.esp\")'"); + Message message = node.as(); + + EXPECT_EQ("file(\"Foo.esp\")", message.GetCondition()); +} + +TEST_F(MessageTest, decodingFromYamlShouldStoreAScalarContentValueCorrectly) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content1\n"); + Message message = node.as(); + MessageContents expectedContent({MessageContent("content1")}); + + EXPECT_EQ(expectedContent, message.GetContent()); +} + +TEST_F(MessageTest, decodingFromYamlShouldStoreAListOfContentStringsCorrectly) { + YAML::Node node = YAML::Load( + "type: say\n" + "content:\n" + " - lang: en\n" + " text: content1\n" + " - lang: fr\n" + " text: content2"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({ + MessageContent("content1"), + MessageContent("content2", french), + }), + message.GetContent()); +} + +TEST_F(MessageTest, + decodingFromYamlShouldNotThrowIfTheOnlyContentStringIsNotEnglish) { + YAML::Node node = YAML::Load( + "type: say\n" + "content:\n" + " - lang: fr\n" + " text: content1"); + + EXPECT_NO_THROW(Message message = node.as()); +} + +TEST_F( + MessageTest, + decodingFromYamlShouldThrowIfMultipleContentStringsAreGivenAndNoneAreEnglish) { + YAML::Node node = YAML::Load( + "type: say\n" + "content:\n" + " - lang: de\n" + " text: content1\n" + " - lang: fr\n" + " text: content2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST_F( + MessageTest, + decodingFromYamlShouldApplySubstitutionsWhenThereIsOnlyOneContentString) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: con{0}tent1\n" + "subs:\n" + " - sub1"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({MessageContent("consub1tent1")}), + message.GetContent()); +} + +TEST_F(MessageTest, + decodingFromYamlShouldApplySubstitutionsToAllContentStrings) { + YAML::Node node = YAML::Load( + "type: say\n" + "content:\n" + " - lang: en\n" + " text: content1 {0}\n" + " - lang: fr\n" + " text: content2 {0}\n" + "subs:\n" + " - sub"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({ + MessageContent("content1 sub"), + MessageContent("content2 sub", french), + }), + message.GetContent()); +} + +TEST_F( + MessageTest, + decodingFromYamlShouldThrowIfTheContentStringExpectsMoreSubstitutionsThanExist) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: '{0} {1}'\n" + "subs:\n" + " - sub1"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +// Don't throw because no subs are given, so none are expected in the content +// string. +TEST_F(MessageTest, + decodingFromYamlShouldIgnoreSubstitutionSyntaxIfNoSubstitutionsExist) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: con{0}tent1\n"); + Message message = node.as(); + + EXPECT_EQ(MessageContents({MessageContent("con{0}tent1")}), + message.GetContent()); +} + +TEST_F(MessageTest, decodingFromYamlShouldAcceptPercentagePlaceholderSyntax) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content %1% %2% %3% %4% %5% %6% %7% %8% %9% %10% %11%\n" + "subs:\n" + " - a\n" + " - b\n" + " - c\n" + " - d\n" + " - e\n" + " - f\n" + " - g\n" + " - h\n" + " - i\n" + " - j\n" + " - k"); + Message message = node.as(); + + ASSERT_EQ(1, message.GetContent().size()); + EXPECT_EQ("content a b c d e f g h i j k", message.GetContent()[0].GetText()); +} + +TEST_F(MessageTest, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { + YAML::Node node = YAML::Load( + "type: say\n" + "content: content1\n" + "condition: invalid"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST_F(MessageTest, decodingFromYamlShouldThrowIfAScalarIsGiven) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST_F(MessageTest, decodingFromYamlShouldThrowIfAListIsGiven) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h b/src/tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h new file mode 100644 index 00000000..e10d9749 --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/plugin_cleaning_data_test.h @@ -0,0 +1,157 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_PLUGIN_CLEANING_DATA_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_PLUGIN_CLEANING_DATA_TEST + +#include "api/metadata/yaml/plugin_cleaning_data.h" +#include "tests/common_game_test_fixture.h" + +namespace loot::test { +class PluginCleaningDataTest : public CommonGameTestFixture { +protected: + PluginCleaningDataTest() : + CommonGameTestFixture(GameType::tes4), + info_(std::vector({ + MessageContent("info"), + })) {} + + const std::vector info_; +}; + +TEST_F(PluginCleaningDataTest, emittingAsYamlShouldOutputAllNonZeroCounts) { + PluginCleaningData info(0x12345678, "cleaner", info_, 2, 10, 30); + YAML::Emitter emitter; + emitter << info; + + EXPECT_STREQ( + "crc: 0x12345678\nutil: 'cleaner'\ndetail: 'info'\nitm: 2\nudr: 10\nnav: " + "30", + emitter.c_str()); +} + +TEST_F(PluginCleaningDataTest, emittingAsYamlShouldOmitAllZeroCounts) { + PluginCleaningData info(0x12345678, "cleaner", info_, 0, 0, 0); + YAML::Emitter emitter; + emitter << info; + + EXPECT_STREQ("crc: 0x12345678\nutil: 'cleaner'\ndetail: 'info'", + emitter.c_str()); +} + +TEST_F(PluginCleaningDataTest, encodingAsYamlShouldOmitAllZeroCountFields) { + PluginCleaningData info(0x12345678, "cleaner", info_, 0, 0, 0); + YAML::Node node; + node = info; + + EXPECT_EQ(0x12345678u, node["crc"].as()); + EXPECT_EQ("cleaner", node["util"].as()); + EXPECT_EQ(info_, node["detail"].as>()); + EXPECT_FALSE(node["itm"]); + EXPECT_FALSE(node["udr"]); + EXPECT_FALSE(node["nav"]); +} + +TEST_F(PluginCleaningDataTest, + encodingAsYamlShouldOutputAllNonZeroCountFields) { + PluginCleaningData info(0x12345678, "cleaner", info_, 2, 10, 30); + YAML::Node node; + node = info; + + EXPECT_EQ(0x12345678u, node["crc"].as()); + EXPECT_EQ("cleaner", node["util"].as()); + EXPECT_EQ(info_, node["detail"].as>()); + EXPECT_EQ(2u, node["itm"].as()); + EXPECT_EQ(10u, node["udr"].as()); + EXPECT_EQ(30u, node["nav"].as()); +} + +TEST_F(PluginCleaningDataTest, + decodingFromYamlShouldLeaveMissingFieldsWithZeroValues) { + YAML::Node node = YAML::Load("{crc: 0x12345678, util: cleaner}"); + PluginCleaningData info = node.as(); + + EXPECT_EQ(0x12345678u, info.GetCRC()); + EXPECT_TRUE(info.GetDetail().empty()); + EXPECT_EQ(0u, info.GetITMCount()); + EXPECT_EQ(0u, info.GetDeletedReferenceCount()); + EXPECT_EQ(0u, info.GetDeletedNavmeshCount()); + EXPECT_EQ("cleaner", info.GetCleaningUtility()); +} + +TEST_F(PluginCleaningDataTest, decodingFromYamlShouldStoreAllNonZeroCounts) { + YAML::Node node = YAML::Load( + "{crc: 0x12345678, util: cleaner, detail: info, itm: 2, udr: 10, nav: " + "30}"); + PluginCleaningData info = node.as(); + + EXPECT_EQ(0x12345678u, info.GetCRC()); + EXPECT_EQ(info_, info.GetDetail()); + EXPECT_EQ(2u, info.GetITMCount()); + EXPECT_EQ(10u, info.GetDeletedReferenceCount()); + EXPECT_EQ(30u, info.GetDeletedNavmeshCount()); + EXPECT_EQ("cleaner", info.GetCleaningUtility()); +} + +TEST_F(PluginCleaningDataTest, + decodingFromYamlShouldNotThrowIfTheOnlyDetailStringIsNotEnglish) { + YAML::Node node = YAML::Load( + "crc: 0x12345678\n" + "util: cleaner\n" + "detail:\n" + " - lang: fr\n" + " text: content1"); + + EXPECT_NO_THROW(node.as()); +} + +TEST_F( + PluginCleaningDataTest, + decodingFromYamlShouldThrowIfMultipleDetailStringsAreGivenAndNoneAreEnglish) { + YAML::Node node = YAML::Load( + "crc: 0x12345678\n" + "util: cleaner\n" + "detail:\n" + " - lang: de\n" + " text: content1\n" + " - lang: fr\n" + " text: content2"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST_F(PluginCleaningDataTest, decodingFromYamlScalarShouldThrow) { + YAML::Node node = YAML::Load("scalar"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST_F(PluginCleaningDataTest, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif diff --git a/src/tests/api/internals/metadata/plugin_metadata_test.h b/src/tests/api/internals/metadata/yaml/plugin_metadata_test.h similarity index 52% rename from src/tests/api/internals/metadata/plugin_metadata_test.h rename to src/tests/api/internals/metadata/yaml/plugin_metadata_test.h index 2a50962a..37facffa 100644 --- a/src/tests/api/internals/metadata/plugin_metadata_test.h +++ b/src/tests/api/internals/metadata/yaml/plugin_metadata_test.h @@ -22,15 +22,13 @@ along with LOOT. If not, see . */ -#ifndef LOOT_TESTS_API_INTERNALS_METADATA_PLUGIN_METADATA_TEST -#define LOOT_TESTS_API_INTERNALS_METADATA_PLUGIN_METADATA_TEST +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_PLUGIN_METADATA_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_PLUGIN_METADATA_TEST #include "api/metadata/yaml/plugin_metadata.h" -#include "loot/metadata/plugin_metadata.h" #include "tests/common_game_test_fixture.h" -namespace loot { -namespace test { +namespace loot::test { class PluginMetadataTest : public CommonGameTestFixture { protected: PluginMetadataTest() : @@ -42,357 +40,6 @@ protected: const std::vector info_; }; -TEST_F( - PluginMetadataTest, - defaultConstructorShouldLeaveNameEmptyAndEnableMetadataAndLeaveGroupUnset) { - PluginMetadata plugin; - - EXPECT_TRUE(plugin.GetName().empty()); - EXPECT_FALSE(plugin.GetGroup()); -} - -TEST_F( - PluginMetadataTest, - stringConstructorShouldSetNameToGivenStringAndEnableMetadataAndLeaveGroupUnset) { - PluginMetadata plugin(blankEsm); - - EXPECT_EQ(blankEsm, plugin.GetName()); - EXPECT_FALSE(plugin.GetGroup()); -} - -TEST_F(PluginMetadataTest, - nameMatchesShouldUseCaseInsensitiveNameComparisonForNonRegexNames) { - PluginMetadata plugin(blankEsm); - - EXPECT_TRUE(plugin.NameMatches(boost::to_lower_copy(blankEsm))); - EXPECT_FALSE(plugin.NameMatches(blankDifferentEsm)); -} - -TEST_F(PluginMetadataTest, - nameMatchesShouldTreatGivenPluginNameStringsAsLiterals) { - PluginMetadata plugin(blankEsm); - std::string regex = "blan.\\.esm"; - - EXPECT_FALSE(plugin.NameMatches(regex)); -} - -TEST_F(PluginMetadataTest, - nameMatchesShouldUseCaseInsensitiveRegexMatchingForARegexName) { - PluginMetadata plugin("Blan.\\.esm"); - - EXPECT_TRUE(plugin.NameMatches(boost::to_lower_copy(blankEsm))); - EXPECT_FALSE(plugin.NameMatches(blankDifferentEsm)); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldNotChangeName) { - PluginMetadata plugin1(blankEsm); - PluginMetadata plugin2(blankDifferentEsm); - - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(blankEsm, plugin1.GetName()); -} - -TEST_F(PluginMetadataTest, - mergeMetadataShouldNotUseMergedGroupIfItAndCurrentGroupAreBothExplicit) { - PluginMetadata plugin1; - PluginMetadata plugin2; - - plugin1.SetGroup("group1"); - plugin2.SetGroup("group2"); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ("group1", plugin1.GetGroup()); -} - -TEST_F(PluginMetadataTest, - mergeMetadataShouldNotUseMergedGroupIfItAndCurrentGroupAreBothImplicit) { - PluginMetadata plugin1; - PluginMetadata plugin2; - - plugin1.MergeMetadata(plugin2); - - EXPECT_FALSE(plugin1.GetGroup().has_value()); -} - -TEST_F( - PluginMetadataTest, - mergeMetadataShouldNotUseMergedGroupIfItIsImplicitAndCurrentGroupIsExplicit) { - PluginMetadata plugin1; - PluginMetadata plugin2; - - plugin1.SetGroup("group1"); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ("group1", plugin1.GetGroup()); -} - -TEST_F( - PluginMetadataTest, - mergeMetadataShouldUseMergedGroupIfItIsExplicitAndCurrentGroupIsImplicit) { - PluginMetadata plugin1; - PluginMetadata plugin2; - - plugin2.SetGroup("group2"); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ("group2", plugin1.GetGroup()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeLoadAfterData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - File file1(blankEsm); - File file2(blankDifferentEsm); - - plugin1.SetLoadAfterFiles({file1}); - plugin2.SetLoadAfterFiles({file1, file2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({file1, file2}), plugin1.GetLoadAfterFiles()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeRequirementData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - File file1(blankEsm); - File file2(blankDifferentEsm); - - plugin1.SetRequirements({file1}); - plugin2.SetRequirements({file1, file2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({file1, file2}), plugin1.GetRequirements()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeIncompatibilityData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - File file1(blankEsm); - File file2(blankDifferentEsm); - - plugin1.SetIncompatibilities({file1}); - plugin2.SetIncompatibilities({file1, file2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({file1, file2}), plugin1.GetIncompatibilities()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeMessages) { - PluginMetadata plugin1; - PluginMetadata plugin2; - Message message(MessageType::say, "content"); - - plugin1.SetMessages({message}); - plugin2.SetMessages({message}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({message, message}), plugin1.GetMessages()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeTags) { - PluginMetadata plugin1; - PluginMetadata plugin2; - Tag tag1("Relev"); - Tag tag2("Relev", false); - Tag tag3("Delev"); - - plugin1.SetTags({tag1}); - plugin2.SetTags({tag1, tag2, tag3}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({tag1, tag2, tag3}), plugin1.GetTags()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeDirtyInfoData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - PluginCleaningData info1(0x5, "utility", info_, 1, 2, 3); - PluginCleaningData info2(0xA, "utility", info_, 1, 2, 3); - - plugin1.SetDirtyInfo({info1}); - plugin2.SetDirtyInfo({info1, info2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({info1, info2}), - plugin1.GetDirtyInfo()); -} -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeCleanInfoData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - PluginCleaningData info1(0x5, "utility"); - PluginCleaningData info2(0xA, "utility"); - - plugin1.SetCleanInfo({info1}); - plugin2.SetCleanInfo({info1, info2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({info1, info2}), - plugin1.GetCleanInfo()); -} - -TEST_F(PluginMetadataTest, mergeMetadataShouldMergeLocationData) { - PluginMetadata plugin1; - PluginMetadata plugin2; - Location location1("http://www.example.com/1"); - Location location2("http://www.example.com/2"); - - plugin1.SetLocations({location1}); - plugin2.SetLocations({location1, location2}); - plugin1.MergeMetadata(plugin2); - - EXPECT_EQ(std::vector({location1, location2}), - plugin1.GetLocations()); -} - -TEST_F(PluginMetadataTest, unsetGroupShouldLeaveNoGroupValueSet) { - PluginMetadata plugin; - EXPECT_FALSE(plugin.GetGroup().has_value()); - - plugin.SetGroup("test"); - EXPECT_EQ("test", plugin.GetGroup().value()); - - plugin.UnsetGroup(); - EXPECT_FALSE(plugin.GetGroup().has_value()); -} - -TEST_F(PluginMetadataTest, - hasNameOnlyShouldBeTrueForADefaultConstructedPluginMetadataObject) { - PluginMetadata plugin; - - EXPECT_TRUE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, - hasNameOnlyShouldBeTrueForAPluginMetadataObjectConstructedWithAName) { - PluginMetadata plugin(blankEsp); - - EXPECT_TRUE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfTheGroupIsExplicit) { - PluginMetadata plugin; - plugin.SetGroup("group"); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLoadAfterMetadataExists) { - PluginMetadata plugin(blankEsp); - plugin.SetLoadAfterFiles({File(blankEsm)}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, - hasNameOnlyShouldBeFalseIfRequirementMetadataExists) { - PluginMetadata plugin(blankEsp); - plugin.SetRequirements({File(blankEsm)}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, - hasNameOnlyShouldBeFalseIfIncompatibilityMetadataExists) { - PluginMetadata plugin(blankEsp); - plugin.SetIncompatibilities({File(blankEsm)}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfMessagesExist) { - PluginMetadata plugin(blankEsp); - plugin.SetMessages({Message(MessageType::say, "content")}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfTagsExist) { - PluginMetadata plugin(blankEsp); - plugin.SetTags({Tag("Relev")}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfDirtyInfoExists) { - PluginMetadata plugin(blankEsp); - plugin.SetDirtyInfo({PluginCleaningData(5, "utility", info_, 0, 1, 2)}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfCleanInfoExists) { - PluginMetadata plugin(blankEsp); - plugin.SetCleanInfo({PluginCleaningData(5, "utility")}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, hasNameOnlyShouldBeFalseIfLocationsExist) { - PluginMetadata plugin(blankEsp); - plugin.SetLocations({Location("http://www.example.com")}); - - EXPECT_FALSE(plugin.HasNameOnly()); -} - -TEST_F(PluginMetadataTest, isRegexPluginShouldBeFalseForAnEmptyPluginName) { - PluginMetadata plugin; - - EXPECT_FALSE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, isRegexPluginShouldBeFalseForAnExactPluginFilename) { - PluginMetadata plugin(blankEsm); - - EXPECT_FALSE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - isRegexPluginShouldBeTrueIfThePluginNameContainsAColon) { - PluginMetadata plugin("Blank:.esm"); - - EXPECT_TRUE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - isRegexPluginShouldBeTrueIfThePluginNameContainsABackslash) { - PluginMetadata plugin("Blank\\.esm"); - - EXPECT_TRUE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - isRegexPluginShouldBeTrueIfThePluginNameContainsAnAsterisk) { - PluginMetadata plugin("Blank*.esm"); - - EXPECT_TRUE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - isRegexPluginShouldBeTrueIfThePluginNameContainsAQuestionMark) { - PluginMetadata plugin("Blank?.esm"); - - EXPECT_TRUE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - isRegexPluginShouldBeTrueIfThePluginNameContainsAVerticalBar) { - PluginMetadata plugin("Blank|.esm"); - - EXPECT_TRUE(plugin.IsRegexPlugin()); -} - -TEST_F(PluginMetadataTest, - asYamlShouldReturnAStringContainingTheMetadataEmittedAsYaml) { - PluginMetadata plugin(blankEsm); - plugin.SetLoadAfterFiles({File(blankEsm)}); - - EXPECT_EQ( - "name: 'Blank.esm'\n" - "after: ['Blank.esm']", - plugin.AsYaml()); -} - TEST_F(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithNoMetadataAsABlankString) { PluginMetadata plugin(blankEsm); @@ -740,6 +387,5 @@ TEST_F(PluginMetadataTest, decodingFromAYamlListShouldThrow) { EXPECT_THROW(node.as(), YAML::RepresentationException); } } -} #endif diff --git a/src/tests/api/internals/metadata/yaml/tag_test.h b/src/tests/api/internals/metadata/yaml/tag_test.h new file mode 100644 index 00000000..66508771 --- /dev/null +++ b/src/tests/api/internals/metadata/yaml/tag_test.h @@ -0,0 +1,139 @@ +/* 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 +. +*/ + +#ifndef LOOT_TESTS_API_INTERNALS_METADATA_YAML_TAG_TEST +#define LOOT_TESTS_API_INTERNALS_METADATA_YAML_TAG_TEST + +#include + +#include "api/metadata/yaml/tag.h" + +namespace loot::test { +TEST( + Tag, + emittingAsYamlShouldOutputOnlyTheNameStringIfTheTagIsAnAdditionWithNoCondition) { + Tag tag("name1"); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_EQ(tag.GetName(), emitter.c_str()); +} + +TEST( + Tag, + emittingAsYamlShouldOutputOnlyTheNameStringPrefixedWithAHyphenIfTheTagIsARemovalWithNoCondition) { + Tag tag("name1", false); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_EQ("-" + tag.GetName(), emitter.c_str()); +} + +TEST(Tag, emittingAsYamlShouldOutputAMapIfTheTagHasACondition) { + Tag tag("name1", false, "condition1"); + YAML::Emitter emitter; + emitter << tag; + + EXPECT_STREQ("name: -name1\ncondition: 'condition1'", emitter.c_str()); +} + +TEST(Tag, + encodingAsYamlShouldOmitTheConditionFieldIfTheConditionStringIsEmpty) { + Tag tag; + YAML::Node node; + node = tag; + + EXPECT_FALSE(node["condition"]); +} + +TEST(Tag, encodingAsYamlShouldOutputTheNameFieldCorrectly) { + Tag tag("name1"); + YAML::Node node; + node = tag; + + EXPECT_EQ(tag.GetName(), node["name"].as()); +} + +TEST( + Tag, + encodingAsYamlShouldOutputTheNameFieldWithAHyphenPrefixIfTheTagIsARemoval) { + Tag tag("name1", false); + YAML::Node node; + node = tag; + + EXPECT_EQ("-" + tag.GetName(), node["name"].as()); +} + +TEST( + Tag, + encodingAsYamlShouldOutputTheConditionFieldIfTheConditionStringIsNotEmpty) { + Tag tag("name1", true, "condition1"); + YAML::Node node; + node = tag; + + EXPECT_EQ(tag.GetName(), node["name"].as()); + EXPECT_EQ(tag.GetCondition(), node["condition"].as()); +} + +TEST(Tag, decodingFromYamlScalarShouldSetNameCorrectly) { + YAML::Node node = YAML::Load("name1"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.GetName()); + EXPECT_TRUE(tag.IsAddition()); + EXPECT_EQ("", tag.GetCondition()); +} + +TEST(Tag, decodingFromYamlScalarShouldSetAdditionStateCorrectly) { + YAML::Node node = YAML::Load("-name1"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.GetName()); + EXPECT_FALSE(tag.IsAddition()); + EXPECT_EQ("", tag.GetCondition()); +} + +TEST(Tag, decodingFromYamlMapShouldSetDataCorrectly) { + YAML::Node node = YAML::Load("{name: name1, condition: 'file(\"Foo.esp\")'}"); + Tag tag = node.as(); + + EXPECT_EQ("name1", tag.GetName()); + EXPECT_TRUE(tag.IsAddition()); + EXPECT_EQ("file(\"Foo.esp\")", tag.GetCondition()); +} + +TEST(Tag, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) { + YAML::Node node = YAML::Load("{name: name1, condition: invalid}"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} + +TEST(Tag, decodingFromYamlListShouldThrow) { + YAML::Node node = YAML::Load("[0, 1, 2]"); + + EXPECT_THROW(node.as(), YAML::RepresentationException); +} +} + +#endif