diff options
Diffstat (limited to 'tests/core')
-rw-r--r-- | tests/core/io/test_marshalls.h | 99 | ||||
-rw-r--r-- | tests/core/string/test_fuzzy_search.h | 83 | ||||
-rw-r--r-- | tests/core/string/test_string.h | 19 | ||||
-rw-r--r-- | tests/core/string/test_translation.h | 2 | ||||
-rw-r--r-- | tests/core/string/test_translation_server.h | 88 |
5 files changed, 268 insertions, 23 deletions
diff --git a/tests/core/io/test_marshalls.h b/tests/core/io/test_marshalls.h index de8d6e1406..6716984681 100644 --- a/tests/core/io/test_marshalls.h +++ b/tests/core/io/test_marshalls.h @@ -160,7 +160,7 @@ TEST_CASE("[Marshalls] NIL Variant encoding") { uint8_t buffer[4]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 4, "Length == 4 bytes for header"); + CHECK_MESSAGE(r_len == 4, "Length == 4 bytes for header."); CHECK_MESSAGE(buffer[0] == 0x00, "Variant::NIL"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -174,7 +174,7 @@ TEST_CASE("[Marshalls] INT 32 bit Variant encoding") { uint8_t buffer[8]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for int32_t"); + CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for `int32_t`."); CHECK_MESSAGE(buffer[0] == 0x02, "Variant::INT"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -192,7 +192,7 @@ TEST_CASE("[Marshalls] INT 64 bit Variant encoding") { uint8_t buffer[12]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for int64_t"); + CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for `int64_t`."); CHECK_MESSAGE(buffer[0] == 0x02, "Variant::INT"); CHECK(buffer[1] == 0x00); CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FLAG_64"); @@ -214,7 +214,7 @@ TEST_CASE("[Marshalls] FLOAT single precision Variant encoding") { uint8_t buffer[8]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for float"); + CHECK_MESSAGE(r_len == 8, "Length == 4 bytes for header + 4 bytes for `float`."); CHECK_MESSAGE(buffer[0] == 0x03, "Variant::FLOAT"); CHECK(buffer[1] == 0x00); CHECK(buffer[2] == 0x00); @@ -232,7 +232,7 @@ TEST_CASE("[Marshalls] FLOAT double precision Variant encoding") { uint8_t buffer[12]; CHECK(encode_variant(variant, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for double"); + CHECK_MESSAGE(r_len == 12, "Length == 4 bytes for header + 8 bytes for `double`."); CHECK_MESSAGE(buffer[0] == 0x03, "Variant::FLOAT"); CHECK(buffer[1] == 0x00); CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FLAG_64"); @@ -335,10 +335,10 @@ TEST_CASE("[Marshalls] Typed array encoding") { uint8_t buffer[24]; CHECK(encode_variant(array, buffer, r_len) == OK); - CHECK_MESSAGE(r_len == 24, "Length == 4 bytes for header + 4 bytes for array type + 4 bytes for array size + 12 bytes for element"); + CHECK_MESSAGE(r_len == 24, "Length == 4 bytes for header + 4 bytes for array type + 4 bytes for array size + 12 bytes for element."); CHECK_MESSAGE(buffer[0] == 0x1c, "Variant::ARRAY"); CHECK(buffer[1] == 0x00); - CHECK_MESSAGE(buffer[2] == 0x01, "HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN"); + CHECK_MESSAGE(buffer[2] == 0x01, "CONTAINER_TYPE_KIND_BUILTIN"); CHECK(buffer[3] == 0x00); // Check array type. CHECK_MESSAGE(buffer[4] == 0x02, "Variant::INT"); @@ -370,7 +370,7 @@ TEST_CASE("[Marshalls] Typed array decoding") { Variant variant; int r_len; uint8_t buffer[] = { - 0x1c, 0x00, 0x01, 0x00, // Variant::ARRAY, HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN + 0x1c, 0x00, 0x01, 0x00, // Variant::ARRAY, CONTAINER_TYPE_KIND_BUILTIN 0x02, 0x00, 0x00, 0x00, // Array type (Variant::INT). 0x01, 0x00, 0x00, 0x00, // Array size. 0x02, 0x00, 0x01, 0x00, // Element type (Variant::INT, HEADER_DATA_FLAG_64). @@ -386,6 +386,89 @@ TEST_CASE("[Marshalls] Typed array decoding") { CHECK(array[0] == Variant(uint64_t(0x0f123456789abcdef))); } +TEST_CASE("[Marshalls] Typed dicttionary encoding") { + int r_len; + Dictionary dictionary; + dictionary.set_typed(Variant::INT, StringName(), Ref<Script>(), Variant::INT, StringName(), Ref<Script>()); + dictionary[Variant(uint64_t(0x0f123456789abcdef))] = Variant(uint64_t(0x0f123456789abcdef)); + uint8_t buffer[40]; + + CHECK(encode_variant(dictionary, buffer, r_len) == OK); + CHECK_MESSAGE(r_len == 40, "Length == 4 bytes for header + 8 bytes for dictionary type + 4 bytes for dictionary size + 24 bytes for key-value pair."); + CHECK_MESSAGE(buffer[0] == 0x1b, "Variant::DICTIONARY"); + CHECK(buffer[1] == 0x00); + CHECK_MESSAGE(buffer[2] == 0x05, "key: CONTAINER_TYPE_KIND_BUILTIN | value: CONTAINER_TYPE_KIND_BUILTIN"); + CHECK(buffer[3] == 0x00); + // Check dictionary key type. + CHECK_MESSAGE(buffer[4] == 0x02, "Variant::INT"); + CHECK(buffer[5] == 0x00); + CHECK(buffer[6] == 0x00); + CHECK(buffer[7] == 0x00); + // Check dictionary value type. + CHECK_MESSAGE(buffer[8] == 0x02, "Variant::INT"); + CHECK(buffer[9] == 0x00); + CHECK(buffer[10] == 0x00); + CHECK(buffer[11] == 0x00); + // Check dictionary size. + CHECK(buffer[12] == 0x01); + CHECK(buffer[13] == 0x00); + CHECK(buffer[14] == 0x00); + CHECK(buffer[15] == 0x00); + // Check key type. + CHECK_MESSAGE(buffer[16] == 0x02, "Variant::INT"); + CHECK(buffer[17] == 0x00); + CHECK_MESSAGE(buffer[18] == 0x01, "HEADER_DATA_FLAG_64"); + CHECK(buffer[19] == 0x00); + // Check key value. + CHECK(buffer[20] == 0xef); + CHECK(buffer[21] == 0xcd); + CHECK(buffer[22] == 0xab); + CHECK(buffer[23] == 0x89); + CHECK(buffer[24] == 0x67); + CHECK(buffer[25] == 0x45); + CHECK(buffer[26] == 0x23); + CHECK(buffer[27] == 0xf1); + // Check value type. + CHECK_MESSAGE(buffer[28] == 0x02, "Variant::INT"); + CHECK(buffer[29] == 0x00); + CHECK_MESSAGE(buffer[30] == 0x01, "HEADER_DATA_FLAG_64"); + CHECK(buffer[31] == 0x00); + // Check value value. + CHECK(buffer[32] == 0xef); + CHECK(buffer[33] == 0xcd); + CHECK(buffer[34] == 0xab); + CHECK(buffer[35] == 0x89); + CHECK(buffer[36] == 0x67); + CHECK(buffer[37] == 0x45); + CHECK(buffer[38] == 0x23); + CHECK(buffer[39] == 0xf1); +} + +TEST_CASE("[Marshalls] Typed dictionary decoding") { + Variant variant; + int r_len; + uint8_t buffer[] = { + 0x1b, 0x00, 0x05, 0x00, // Variant::DICTIONARY, key: CONTAINER_TYPE_KIND_BUILTIN | value: CONTAINER_TYPE_KIND_BUILTIN + 0x02, 0x00, 0x00, 0x00, // Dictionary key type (Variant::INT). + 0x02, 0x00, 0x00, 0x00, // Dictionary value type (Variant::INT). + 0x01, 0x00, 0x00, 0x00, // Dictionary size. + 0x02, 0x00, 0x01, 0x00, // Key type (Variant::INT, HEADER_DATA_FLAG_64). + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0xf1, // Key value. + 0x02, 0x00, 0x01, 0x00, // Value type (Variant::INT, HEADER_DATA_FLAG_64). + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0xf1, // Value value. + }; + + CHECK(decode_variant(variant, buffer, 40, &r_len) == OK); + CHECK(r_len == 40); + CHECK(variant.get_type() == Variant::DICTIONARY); + Dictionary dictionary = variant; + CHECK(dictionary.get_typed_key_builtin() == Variant::INT); + CHECK(dictionary.get_typed_value_builtin() == Variant::INT); + CHECK(dictionary.size() == 1); + CHECK(dictionary.has(Variant(uint64_t(0x0f123456789abcdef)))); + CHECK(dictionary[Variant(uint64_t(0x0f123456789abcdef))] == Variant(uint64_t(0x0f123456789abcdef))); +} + } // namespace TestMarshalls #endif // TEST_MARSHALLS_H diff --git a/tests/core/string/test_fuzzy_search.h b/tests/core/string/test_fuzzy_search.h new file mode 100644 index 0000000000..d647ebdd1a --- /dev/null +++ b/tests/core/string/test_fuzzy_search.h @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* test_fuzzy_search.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_FUZZY_SEARCH_H +#define TEST_FUZZY_SEARCH_H + +#include "core/string/fuzzy_search.h" +#include "tests/test_macros.h" + +namespace TestFuzzySearch { + +struct FuzzySearchTestCase { + String query; + String expected; +}; + +// Ideally each of these test queries should represent a different aspect, and potentially bottleneck, of the search process. +const FuzzySearchTestCase test_cases[] = { + // Short query, many matches, few adjacent characters + { "///gd", "./menu/hud/hud.gd" }, + // Filename match with typo + { "sm.png", "./entity/blood_sword/sam.png" }, + // Multipart filename word matches + { "ham ", "./entity/game_trap/ha_missed_me.wav" }, + // Single word token matches + { "push background", "./entity/background_zone1/background/push.png" }, + // Long token matches + { "background_freighter background png", "./entity/background_freighter/background/background.png" }, + // Many matches, many short tokens + { "menu menu characters wav", "./menu/menu/characters/smoker/0.wav" }, + // Maximize total matches + { "entity gd", "./entity/entity_man.gd" } +}; + +Vector<String> load_test_data() { + Ref<FileAccess> fp = FileAccess::open(TestUtils::get_data_path("fuzzy_search/project_dir_tree.txt"), FileAccess::READ); + REQUIRE(fp.is_valid()); + return fp->get_as_utf8_string().split("\n"); +} + +TEST_CASE("[FuzzySearch] Test fuzzy search results") { + FuzzySearch search; + Vector<FuzzySearchResult> results; + Vector<String> targets = load_test_data(); + + for (FuzzySearchTestCase test_case : test_cases) { + search.set_query(test_case.query); + search.search_all(targets, results); + CHECK_GT(results.size(), 0); + CHECK_EQ(results[0].target, test_case.expected); + } +} + +} //namespace TestFuzzySearch + +#endif // TEST_FUZZY_SEARCH_H diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index 49afc55c64..9adc97e845 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -389,6 +389,19 @@ TEST_CASE("[String] Find") { MULTICHECK_STRING_INT_EQ(s, rfind, "", 15, -1); } +TEST_CASE("[String] Find character") { + String s = "racecar"; + CHECK_EQ(s.find_char('r'), 0); + CHECK_EQ(s.find_char('r', 1), 6); + CHECK_EQ(s.find_char('e'), 3); + CHECK_EQ(s.find_char('e', 4), -1); + + CHECK_EQ(s.rfind_char('r'), 6); + CHECK_EQ(s.rfind_char('r', 5), 0); + CHECK_EQ(s.rfind_char('e'), 3); + CHECK_EQ(s.rfind_char('e', 2), -1); +} + TEST_CASE("[String] Find case insensitive") { String s = "Pretty Whale Whale"; MULTICHECK_STRING_EQ(s, findn, "WHA", 7); @@ -1254,6 +1267,12 @@ TEST_CASE("[String] is_subsequence_of") { CHECK(String("Sub").is_subsequence_ofn(a)); } +TEST_CASE("[String] is_lowercase") { + CHECK(String("abcd1234 !@#$%^&*()_-=+,.<>/\\|[]{};':\"`~").is_lowercase()); + CHECK(String("").is_lowercase()); + CHECK(!String("abc_ABC").is_lowercase()); +} + TEST_CASE("[String] match") { CHECK(String("img1.png").match("*.png")); CHECK(!String("img1.jpeg").match("*.png")); diff --git a/tests/core/string/test_translation.h b/tests/core/string/test_translation.h index 7c389191e3..2b1069d40c 100644 --- a/tests/core/string/test_translation.h +++ b/tests/core/string/test_translation.h @@ -161,7 +161,7 @@ TEST_CASE("[TranslationCSV] CSV import") { List<String> gen_files; - Error result = import_csv_translation->import(TestUtils::get_data_path("translations.csv"), + Error result = import_csv_translation->import(0, TestUtils::get_data_path("translations.csv"), "", options, nullptr, &gen_files); CHECK(result == OK); CHECK(gen_files.size() == 4); diff --git a/tests/core/string/test_translation_server.h b/tests/core/string/test_translation_server.h index ac1599f2e8..6668a7b57b 100644 --- a/tests/core/string/test_translation_server.h +++ b/tests/core/string/test_translation_server.h @@ -37,27 +37,37 @@ namespace TestTranslationServer { TEST_CASE("[TranslationServer] Translation operations") { - Ref<Translation> t = memnew(Translation); - t->set_locale("uk"); - t->add_message("Good Morning", String::utf8("Добрий ранок")); + Ref<Translation> t1 = memnew(Translation); + t1->set_locale("uk"); + t1->add_message("Good Morning", String(U"Добрий ранок")); + + Ref<Translation> t2 = memnew(Translation); + t2->set_locale("uk"); + t2->add_message("Hello Godot", String(U"你好戈多")); TranslationServer *ts = TranslationServer::get_singleton(); + // Adds translation for UK locale for the first time. int l_count_before = ts->get_loaded_locales().size(); - ts->add_translation(t); + ts->add_translation(t1); int l_count_after = ts->get_loaded_locales().size(); - // Newly created Translation object should be added to the list, so the counter should increase, too. CHECK(l_count_after > l_count_before); - Ref<Translation> trans = ts->get_translation_object("uk"); - CHECK(trans.is_valid()); + // Adds translation for UK locale again. + ts->add_translation(t2); + CHECK_EQ(ts->get_loaded_locales().size(), l_count_after); + + // Removing that translation. + ts->remove_translation(t2); + CHECK_EQ(ts->get_loaded_locales().size(), l_count_after); + + CHECK(ts->get_translation_object("uk").is_valid()); ts->set_locale("uk"); CHECK(ts->translate("Good Morning") == String::utf8("Добрий ранок")); - ts->remove_translation(t); - trans = ts->get_translation_object("uk"); - CHECK(trans.is_null()); + ts->remove_translation(t1); + CHECK(ts->get_translation_object("uk").is_null()); // If no suitable Translation object has been found - the original message should be returned. CHECK(ts->translate("Good Morning") == "Good Morning"); } @@ -110,18 +120,50 @@ TEST_CASE("[TranslationServer] Comparing locales") { locale_a = "sr-Latn-CS"; locale_b = "sr-Latn-RS"; - // Two elements from locales match. + // Script matches (+1) but country doesn't (-1). res = ts->compare_locales(locale_a, locale_b); - CHECK(res == 2); + CHECK(res == 5); locale_a = "uz-Cyrl-UZ"; locale_b = "uz-Latn-UZ"; - // Two elements match, but they are not sequentual. + // Country matches (+1) but script doesn't (-1). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 5); + + locale_a = "aa-Latn-ER"; + locale_b = "aa-Latn-ER-saaho"; + + // Script and country match (+2) with variant on one locale (+0). res = ts->compare_locales(locale_a, locale_b); - CHECK(res == 2); + CHECK(res == 7); + + locale_a = "uz-Cyrl-UZ"; + locale_b = "uz-Latn-KG"; + + // Both script and country mismatched (-2). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 3); + + locale_a = "es-ES"; + locale_b = "es-AR"; + + // Mismatched country (-1). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 4); + + locale_a = "es"; + locale_b = "es-AR"; + + // No country for one locale (+0). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 5); locale_a = "es-EC"; locale_b = "fr-LU"; @@ -130,6 +172,24 @@ TEST_CASE("[TranslationServer] Comparing locales") { res = ts->compare_locales(locale_a, locale_b); CHECK(res == 0); + + locale_a = "zh-HK"; + locale_b = "zh"; + + // In full standardization, zh-HK becomes zh_Hant_HK and zh becomes + // zh_Hans_CN. Both script and country mismatch (-2). + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 3); + + locale_a = "zh-CN"; + locale_b = "zh"; + + // In full standardization, zh and zh-CN both become zh_Hans_CN for an + // exact match. + res = ts->compare_locales(locale_a, locale_b); + + CHECK(res == 10); } } // namespace TestTranslationServer |