summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core/object/test_class_db.h14
-rw-r--r--tests/core/object/test_object.h2
-rw-r--r--tests/core/os/test_os.h4
-rw-r--r--tests/core/string/test_string.h290
-rw-r--r--tests/core/templates/test_local_vector.h11
-rw-r--r--tests/core/variant/test_dictionary.h2
-rw-r--r--tests/scene/test_sprite_frames.h5
-rw-r--r--tests/scene/test_timer.h217
-rw-r--r--tests/test_macros.h67
-rw-r--r--tests/test_main.cpp7
10 files changed, 462 insertions, 157 deletions
diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h
index 5623c1d495..fb62d0f056 100644
--- a/tests/core/object/test_class_db.h
+++ b/tests/core/object/test_class_db.h
@@ -550,8 +550,6 @@ void add_exposed_classes(Context &r_context) {
for (const MethodInfo &E : method_list) {
const MethodInfo &method_info = E;
- int argc = method_info.arguments.size();
-
if (method_info.name.is_empty()) {
continue;
}
@@ -613,8 +611,9 @@ void add_exposed_classes(Context &r_context) {
method.return_type.name = Variant::get_type_name(return_info.type);
}
- for (int i = 0; i < argc; i++) {
- PropertyInfo arg_info = method_info.arguments[i];
+ int i = 0;
+ for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
+ const PropertyInfo &arg_info = *itr;
String orig_arg_name = arg_info.name;
@@ -686,10 +685,9 @@ void add_exposed_classes(Context &r_context) {
TEST_FAIL_COND(!String(signal.name).is_valid_identifier(),
"Signal name is not a valid identifier: '", exposed_class.name, ".", signal.name, "'.");
- int argc = method_info.arguments.size();
-
- for (int i = 0; i < argc; i++) {
- PropertyInfo arg_info = method_info.arguments[i];
+ int i = 0;
+ for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
+ const PropertyInfo &arg_info = *itr;
String orig_arg_name = arg_info.name;
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 3a3013a102..d714d71416 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -142,7 +142,7 @@ TEST_CASE("[Object] Core getters") {
inheritance_list.size() == 1,
"The inheritance list should consist of Object only");
CHECK_MESSAGE(
- inheritance_list[0] == "Object",
+ inheritance_list.front()->get() == "Object",
"The inheritance list should consist of Object only");
}
diff --git a/tests/core/os/test_os.h b/tests/core/os/test_os.h
index 63f8b18238..6ee0ff82e7 100644
--- a/tests/core/os/test_os.h
+++ b/tests/core/os/test_os.h
@@ -79,8 +79,8 @@ TEST_CASE("[OS] Non-UTF-8 environment variables") {
TEST_CASE("[OS] Command line arguments") {
List<String> arguments = OS::get_singleton()->get_cmdline_args();
bool found = false;
- for (int i = 0; i < arguments.size(); i++) {
- if (arguments[i] == "--test") {
+ for (const String &arg : arguments) {
+ if (arg == "--test") {
found = true;
break;
}
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 64f03e5879..18828c3b70 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -360,18 +360,37 @@ TEST_CASE("[String] Substr") {
TEST_CASE("[String] Find") {
String s = "Pretty Woman Woman";
- CHECK(s.find("tty") == 3);
- CHECK(s.find("Wo", 9) == 13);
- CHECK(s.find("Revenge of the Monster Truck") == -1);
- CHECK(s.rfind("man") == 15);
+ MULTICHECK_STRING_EQ(s, find, "tty", 3);
+ MULTICHECK_STRING_EQ(s, find, "Revenge of the Monster Truck", -1);
+ MULTICHECK_STRING_INT_EQ(s, find, "Wo", 9, 13);
+ MULTICHECK_STRING_EQ(s, find, "", -1);
+ MULTICHECK_STRING_EQ(s, find, "Pretty Woman Woman", 0);
+ MULTICHECK_STRING_EQ(s, find, "WOMAN", -1);
+ MULTICHECK_STRING_INT_EQ(s, find, "", 9, -1);
+
+ MULTICHECK_STRING_EQ(s, rfind, "", -1);
+ MULTICHECK_STRING_EQ(s, rfind, "foo", -1);
+ MULTICHECK_STRING_EQ(s, rfind, "Pretty Woman Woman", 0);
+ MULTICHECK_STRING_EQ(s, rfind, "man", 15);
+ MULTICHECK_STRING_EQ(s, rfind, "WOMAN", -1);
+ MULTICHECK_STRING_INT_EQ(s, rfind, "", 15, -1);
}
TEST_CASE("[String] Find no case") {
String s = "Pretty Whale Whale";
- CHECK(s.findn("WHA") == 7);
- CHECK(s.findn("WHA", 9) == 13);
- CHECK(s.findn("Revenge of the Monster SawFish") == -1);
- CHECK(s.rfindn("WHA") == 13);
+ MULTICHECK_STRING_EQ(s, findn, "WHA", 7);
+ MULTICHECK_STRING_INT_EQ(s, findn, "WHA", 9, 13);
+ MULTICHECK_STRING_EQ(s, findn, "Revenge of the Monster SawFish", -1);
+ MULTICHECK_STRING_EQ(s, findn, "", -1);
+ MULTICHECK_STRING_EQ(s, findn, "wha", 7);
+ MULTICHECK_STRING_EQ(s, findn, "Wha", 7);
+ MULTICHECK_STRING_INT_EQ(s, findn, "", 3, -1);
+
+ MULTICHECK_STRING_EQ(s, rfindn, "WHA", 13);
+ MULTICHECK_STRING_EQ(s, rfindn, "", -1);
+ MULTICHECK_STRING_EQ(s, rfindn, "wha", 13);
+ MULTICHECK_STRING_EQ(s, rfindn, "Wha", 13);
+ MULTICHECK_STRING_INT_EQ(s, rfindn, "", 13, -1);
}
TEST_CASE("[String] Find MK") {
@@ -392,11 +411,9 @@ TEST_CASE("[String] Find MK") {
TEST_CASE("[String] Find and replace") {
String s = "Happy Birthday, Anna!";
- s = s.replace("Birthday", "Halloween");
- CHECK(s == "Happy Halloween, Anna!");
-
- s = s.replace_first("H", "W");
- CHECK(s == "Wappy Halloween, Anna!");
+ MULTICHECK_STRING_STRING_EQ(s, replace, "Birthday", "Halloween", "Happy Halloween, Anna!");
+ MULTICHECK_STRING_STRING_EQ(s, replace_first, "y", "Y", "HappY Birthday, Anna!");
+ MULTICHECK_STRING_STRING_EQ(s, replacen, "Y", "Y", "HappY BirthdaY, Anna!");
}
TEST_CASE("[String] Insertion") {
@@ -557,51 +574,76 @@ TEST_CASE("[String] String to float") {
TEST_CASE("[String] Slicing") {
String s = "Mars,Jupiter,Saturn,Uranus";
-
const char *slices[4] = { "Mars", "Jupiter", "Saturn", "Uranus" };
- for (int i = 0; i < s.get_slice_count(","); i++) {
- CHECK(s.get_slice(",", i) == slices[i]);
- }
+ MULTICHECK_GET_SLICE(s, ",", slices);
+}
+
+TEST_CASE("[String] Begins with") {
+ // Test cases for true:
+ MULTICHECK_STRING_EQ(String("res://foobar"), begins_with, "res://", true);
+ MULTICHECK_STRING_EQ(String("abc"), begins_with, "abc", true);
+ MULTICHECK_STRING_EQ(String("abc"), begins_with, "", true);
+ MULTICHECK_STRING_EQ(String(""), begins_with, "", true);
+
+ // Test cases for false:
+ MULTICHECK_STRING_EQ(String("res"), begins_with, "res://", false);
+ MULTICHECK_STRING_EQ(String("abcdef"), begins_with, "foo", false);
+ MULTICHECK_STRING_EQ(String("abc"), begins_with, "ax", false);
+ MULTICHECK_STRING_EQ(String(""), begins_with, "abc", false);
+
+ // Test "const char *" version also with nullptr.
+ String s("foo");
+ bool state = s.begins_with(nullptr) == false;
+ CHECK_MESSAGE(state, "nullptr check failed");
+
+ String empty("");
+ state = empty.begins_with(nullptr) == false;
+ CHECK_MESSAGE(state, "nullptr check with empty string failed");
+}
+
+TEST_CASE("[String] Ends with") {
+ // Test cases for true:
+ MULTICHECK_STRING_EQ(String("res://foobar"), ends_with, "foobar", true);
+ MULTICHECK_STRING_EQ(String("abc"), ends_with, "abc", true);
+ MULTICHECK_STRING_EQ(String("abc"), ends_with, "", true);
+ MULTICHECK_STRING_EQ(String(""), ends_with, "", true);
+
+ // Test cases for false:
+ MULTICHECK_STRING_EQ(String("res"), ends_with, "res://", false);
+ MULTICHECK_STRING_EQ(String("abcdef"), ends_with, "foo", false);
+ MULTICHECK_STRING_EQ(String("abc"), ends_with, "ax", false);
+ MULTICHECK_STRING_EQ(String(""), ends_with, "abc", false);
+
+ // Test "const char *" version also with nullptr.
+ String s("foo");
+ bool state = s.ends_with(nullptr) == false;
+ CHECK_MESSAGE(state, "nullptr check failed");
+
+ String empty("");
+ state = empty.ends_with(nullptr) == false;
+ CHECK_MESSAGE(state, "nullptr check with empty string failed");
}
TEST_CASE("[String] Splitting") {
String s = "Mars,Jupiter,Saturn,Uranus";
- Vector<String> l;
-
const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" };
- const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" };
- const char *slices_3[4] = { "t", "e", "s", "t" };
-
- l = s.split(",", true, 2);
- CHECK(l.size() == 3);
- for (int i = 0; i < l.size(); i++) {
- CHECK(l[i] == slices_l[i]);
- }
+ MULTICHECK_SPLIT(s, split, ",", true, 2, slices_l, 3);
- l = s.rsplit(",", true, 2);
- CHECK(l.size() == 3);
- for (int i = 0; i < l.size(); i++) {
- CHECK(l[i] == slices_r[i]);
- }
+ const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" };
+ MULTICHECK_SPLIT(s, rsplit, ",", true, 2, slices_r, 3);
s = "test";
- l = s.split();
- CHECK(l.size() == 4);
- for (int i = 0; i < l.size(); i++) {
- CHECK(l[i] == slices_3[i]);
- }
+ const char *slices_3[4] = { "t", "e", "s", "t" };
+ MULTICHECK_SPLIT(s, split, "", true, 0, slices_3, 4);
s = "";
- l = s.split();
- CHECK(l.size() == 1);
- CHECK(l[0] == "");
-
- l = s.split("", false);
- CHECK(l.size() == 0);
+ const char *slices_4[1] = { "" };
+ MULTICHECK_SPLIT(s, split, "", true, 0, slices_4, 1);
+ MULTICHECK_SPLIT(s, split, "", false, 0, slices_4, 0);
s = "Mars Jupiter Saturn Uranus";
const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" };
- l = s.split_spaces();
+ Vector<String> l = s.split_spaces();
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices_s[i]);
}
@@ -644,69 +686,6 @@ TEST_CASE("[String] Splitting") {
}
}
-struct test_27_data {
- char const *data;
- char const *part;
- bool expected;
-};
-
-TEST_CASE("[String] Begins with") {
- test_27_data tc[] = {
- // Test cases for true:
- { "res://foobar", "res://", true },
- { "abc", "abc", true },
- { "abc", "", true },
- { "", "", true },
- // Test cases for false:
- { "res", "res://", false },
- { "abcdef", "foo", false },
- { "abc", "ax", false },
- { "", "abc", false }
- };
- size_t count = sizeof(tc) / sizeof(tc[0]);
- bool state = true;
- for (size_t i = 0; i < count; ++i) {
- String s = tc[i].data;
- state = s.begins_with(tc[i].part) == tc[i].expected;
- CHECK_MESSAGE(state, "first check failed at: ", i);
-
- String sb = tc[i].part;
- state = s.begins_with(sb) == tc[i].expected;
- CHECK_MESSAGE(state, "second check failed at: ", i);
- }
-
- // Test "const char *" version also with nullptr.
- String s("foo");
- state = s.begins_with(nullptr) == false;
- CHECK_MESSAGE(state, "nullptr check failed");
-
- String empty("");
- state = empty.begins_with(nullptr) == false;
- CHECK_MESSAGE(state, "nullptr check with empty string failed");
-}
-
-TEST_CASE("[String] Ends with") {
- test_27_data tc[] = {
- // test cases for true:
- { "res://foobar", "foobar", true },
- { "abc", "abc", true },
- { "abc", "", true },
- { "", "", true },
- // test cases for false:
- { "res", "res://", false },
- { "", "abc", false },
- { "abcdef", "foo", false },
- { "abc", "xc", false }
- };
- size_t count = sizeof(tc) / sizeof(tc[0]);
- for (size_t i = 0; i < count; ++i) {
- String s = tc[i].data;
- String sb = tc[i].part;
- bool state = s.ends_with(sb) == tc[i].expected;
- CHECK_MESSAGE(state, "check failed at: ", i);
- }
-}
-
TEST_CASE("[String] format") {
const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\"";
@@ -1498,39 +1477,62 @@ TEST_CASE("[String] Cyrillic to_lower()") {
}
TEST_CASE("[String] Count and countn functionality") {
-#define COUNT_TEST(x) \
- { \
- bool success = x; \
- state = state && success; \
- }
+ String s = String("");
+ MULTICHECK_STRING_EQ(s, count, "Test", 0);
- bool state = true;
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, count, "", 0);
- COUNT_TEST(String("").count("Test") == 0);
- COUNT_TEST(String("Test").count("") == 0);
- COUNT_TEST(String("Test").count("test") == 0);
- COUNT_TEST(String("Test").count("TEST") == 0);
- COUNT_TEST(String("TEST").count("TEST") == 1);
- COUNT_TEST(String("Test").count("Test") == 1);
- COUNT_TEST(String("aTest").count("Test") == 1);
- COUNT_TEST(String("Testa").count("Test") == 1);
- COUNT_TEST(String("TestTestTest").count("Test") == 3);
- COUNT_TEST(String("TestTestTest").count("TestTest") == 1);
- COUNT_TEST(String("TestGodotTestGodotTestGodot").count("Test") == 3);
-
- COUNT_TEST(String("TestTestTestTest").count("Test", 4, 8) == 1);
- COUNT_TEST(String("TestTestTestTest").count("Test", 4, 12) == 2);
- COUNT_TEST(String("TestTestTestTest").count("Test", 4, 16) == 3);
- COUNT_TEST(String("TestTestTestTest").count("Test", 4) == 3);
-
- COUNT_TEST(String("Test").countn("test") == 1);
- COUNT_TEST(String("Test").countn("TEST") == 1);
- COUNT_TEST(String("testTest-Testatest").countn("tEst") == 4);
- COUNT_TEST(String("testTest-TeStatest").countn("tEsT", 4, 16) == 2);
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, count, "test", 0);
- CHECK(state);
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, count, "TEST", 0);
+
+ s = "TEST";
+ MULTICHECK_STRING_EQ(s, count, "TEST", 1);
+
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, count, "Test", 1);
+
+ s = "aTest";
+ MULTICHECK_STRING_EQ(s, count, "Test", 1);
+
+ s = "Testa";
+ MULTICHECK_STRING_EQ(s, count, "Test", 1);
+
+ s = "TestTestTest";
+ MULTICHECK_STRING_EQ(s, count, "Test", 3);
+
+ s = "TestTestTest";
+ MULTICHECK_STRING_EQ(s, count, "TestTest", 1);
+
+ s = "TestGodotTestGodotTestGodot";
+ MULTICHECK_STRING_EQ(s, count, "Test", 3);
+
+ s = "TestTestTestTest";
+ MULTICHECK_STRING_INT_INT_EQ(s, count, "Test", 4, 8, 1);
+
+ s = "TestTestTestTest";
+ MULTICHECK_STRING_INT_INT_EQ(s, count, "Test", 4, 12, 2);
+
+ s = "TestTestTestTest";
+ MULTICHECK_STRING_INT_INT_EQ(s, count, "Test", 4, 16, 3);
+
+ s = "TestTestTestTest";
+ MULTICHECK_STRING_INT_EQ(s, count, "Test", 4, 3);
+
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, countn, "test", 1);
+
+ s = "Test";
+ MULTICHECK_STRING_EQ(s, countn, "TEST", 1);
+
+ s = "testTest-Testatest";
+ MULTICHECK_STRING_EQ(s, countn, "tEst", 4);
-#undef COUNT_TEST
+ s = "testTest-TeStatest";
+ MULTICHECK_STRING_INT_INT_EQ(s, countn, "tEsT", 4, 16, 2);
}
TEST_CASE("[String] Bigrams") {
@@ -1703,9 +1705,19 @@ TEST_CASE("[String] Strip edges") {
TEST_CASE("[String] Trim") {
String s = "aaaTestbbb";
- CHECK(s.trim_prefix("aaa") == "Testbbb");
- CHECK(s.trim_suffix("bbb") == "aaaTest");
- CHECK(s.trim_suffix("Test") == s);
+ MULTICHECK_STRING_EQ(s, trim_prefix, "aaa", "Testbbb");
+ MULTICHECK_STRING_EQ(s, trim_prefix, "Test", s);
+ MULTICHECK_STRING_EQ(s, trim_prefix, "", s);
+ MULTICHECK_STRING_EQ(s, trim_prefix, "aaaTestbbb", "");
+ MULTICHECK_STRING_EQ(s, trim_prefix, "bbb", s);
+ MULTICHECK_STRING_EQ(s, trim_prefix, "AAA", s);
+
+ MULTICHECK_STRING_EQ(s, trim_suffix, "bbb", "aaaTest");
+ MULTICHECK_STRING_EQ(s, trim_suffix, "Test", s);
+ MULTICHECK_STRING_EQ(s, trim_suffix, "", s);
+ MULTICHECK_STRING_EQ(s, trim_suffix, "aaaTestbbb", "");
+ MULTICHECK_STRING_EQ(s, trim_suffix, "aaa", s);
+ MULTICHECK_STRING_EQ(s, trim_suffix, "BBB", s);
}
TEST_CASE("[String] Right/Left") {
diff --git a/tests/core/templates/test_local_vector.h b/tests/core/templates/test_local_vector.h
index 2873a9a028..c9544c625b 100644
--- a/tests/core/templates/test_local_vector.h
+++ b/tests/core/templates/test_local_vector.h
@@ -63,7 +63,7 @@ TEST_CASE("[LocalVector] Push Back.") {
CHECK(vector[4] == 4);
}
-TEST_CASE("[LocalVector] Find.") {
+TEST_CASE("[LocalVector] Find, has.") {
LocalVector<int> vector;
vector.push_back(3);
vector.push_back(1);
@@ -85,6 +85,15 @@ TEST_CASE("[LocalVector] Find.") {
CHECK(vector.find(-1) == -1);
CHECK(vector.find(5) == -1);
+
+ CHECK(vector.has(0));
+ CHECK(vector.has(1));
+ CHECK(vector.has(2));
+ CHECK(vector.has(3));
+ CHECK(vector.has(4));
+
+ CHECK(!vector.has(-1));
+ CHECK(!vector.has(5));
}
TEST_CASE("[LocalVector] Remove.") {
diff --git a/tests/core/variant/test_dictionary.h b/tests/core/variant/test_dictionary.h
index 5bc56075da..aba20972d9 100644
--- a/tests/core/variant/test_dictionary.h
+++ b/tests/core/variant/test_dictionary.h
@@ -105,7 +105,7 @@ TEST_CASE("[Dictionary] get_key_lists()") {
map[1] = 3;
map.get_key_list(ptr);
CHECK(keys.size() == 1);
- CHECK(int(keys[0]) == 1);
+ CHECK(int(keys.front()->get()) == 1);
map[2] = 4;
map.get_key_list(ptr);
CHECK(keys.size() == 3);
diff --git a/tests/scene/test_sprite_frames.h b/tests/scene/test_sprite_frames.h
index bf127cd42c..55854b90e4 100644
--- a/tests/scene/test_sprite_frames.h
+++ b/tests/scene/test_sprite_frames.h
@@ -74,9 +74,10 @@ TEST_CASE("[SpriteFrames] Animation addition, list getter, renaming, removal, an
sname_list.size() == test_names.size(),
"StringName List getter returned list of expected size");
- for (int i = 0; i < test_names.size(); i++) {
+ int idx = 0;
+ for (List<StringName>::ConstIterator itr = sname_list.begin(); itr != sname_list.end(); ++itr, ++idx) {
CHECK_MESSAGE(
- sname_list[i] == StringName(test_names[i]),
+ *itr == StringName(test_names[idx]),
"StringName List getter returned expected values");
}
diff --git a/tests/scene/test_timer.h b/tests/scene/test_timer.h
new file mode 100644
index 0000000000..913ed92de5
--- /dev/null
+++ b/tests/scene/test_timer.h
@@ -0,0 +1,217 @@
+/**************************************************************************/
+/* test_timer.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_TIMER_H
+#define TEST_TIMER_H
+
+#include "scene/main/timer.h"
+
+#include "tests/test_macros.h"
+
+namespace TestTimer {
+
+TEST_CASE("[SceneTree][Timer] Check Timer Setters and Getters") {
+ Timer *test_timer = memnew(Timer);
+
+ SUBCASE("[Timer] Timer set and get wait time") {
+ // check default
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 1.0));
+
+ test_timer->set_wait_time(50.0);
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 50.0));
+
+ test_timer->set_wait_time(42.0);
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 42.0));
+
+ // wait time remains unchanged if we attempt to set it negative or zero
+ ERR_PRINT_OFF;
+ test_timer->set_wait_time(-22.0);
+ ERR_PRINT_ON;
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 42.0));
+
+ ERR_PRINT_OFF;
+ test_timer->set_wait_time(0.0);
+ ERR_PRINT_ON;
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 42.0));
+ }
+
+ SUBCASE("[Timer] Timer set and get one shot") {
+ // check default
+ CHECK(test_timer->is_one_shot() == false);
+
+ test_timer->set_one_shot(true);
+ CHECK(test_timer->is_one_shot() == true);
+
+ test_timer->set_one_shot(false);
+ CHECK(test_timer->is_one_shot() == false);
+ }
+
+ SUBCASE("[Timer] Timer set and get autostart") {
+ // check default
+ CHECK(test_timer->has_autostart() == false);
+
+ test_timer->set_autostart(true);
+ CHECK(test_timer->has_autostart() == true);
+
+ test_timer->set_autostart(false);
+ CHECK(test_timer->has_autostart() == false);
+ }
+
+ SUBCASE("[Timer] Timer start and stop") {
+ test_timer->set_autostart(false);
+ }
+
+ SUBCASE("[Timer] Timer set and get paused") {
+ // check default
+ CHECK(test_timer->is_paused() == false);
+
+ test_timer->set_paused(true);
+ CHECK(test_timer->is_paused() == true);
+
+ test_timer->set_paused(false);
+ CHECK(test_timer->is_paused() == false);
+ }
+
+ memdelete(test_timer);
+}
+
+TEST_CASE("[SceneTree][Timer] Check Timer Start and Stop") {
+ Timer *test_timer = memnew(Timer);
+
+ SUBCASE("[Timer] Timer start and stop") {
+ SceneTree::get_singleton()->get_root()->add_child(test_timer);
+
+ test_timer->start(5.0);
+
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 5.0));
+ CHECK(Math::is_equal_approx(test_timer->get_time_left(), 5.0));
+
+ test_timer->start(-2.0);
+
+ // the wait time and time left remains unchanged when started with a negative start time
+ CHECK(Math::is_equal_approx(test_timer->get_wait_time(), 5.0));
+ CHECK(Math::is_equal_approx(test_timer->get_time_left(), 5.0));
+
+ test_timer->stop();
+ CHECK(test_timer->is_processing() == false);
+ CHECK(test_timer->has_autostart() == false);
+ }
+
+ memdelete(test_timer);
+}
+
+TEST_CASE("[SceneTree][Timer] Check Timer process callback") {
+ Timer *test_timer = memnew(Timer);
+
+ SUBCASE("[Timer] Timer process callback") {
+ // check default
+ CHECK(test_timer->get_timer_process_callback() == Timer::TimerProcessCallback::TIMER_PROCESS_IDLE);
+
+ test_timer->set_timer_process_callback(Timer::TimerProcessCallback::TIMER_PROCESS_PHYSICS);
+ CHECK(test_timer->get_timer_process_callback() == Timer::TimerProcessCallback::TIMER_PROCESS_PHYSICS);
+
+ test_timer->set_timer_process_callback(Timer::TimerProcessCallback::TIMER_PROCESS_IDLE);
+ CHECK(test_timer->get_timer_process_callback() == Timer::TimerProcessCallback::TIMER_PROCESS_IDLE);
+ }
+
+ memdelete(test_timer);
+}
+
+TEST_CASE("[SceneTree][Timer] Check Timer timeout signal") {
+ Timer *test_timer = memnew(Timer);
+ SceneTree::get_singleton()->get_root()->add_child(test_timer);
+
+ test_timer->set_process(true);
+ test_timer->set_physics_process(true);
+
+ SUBCASE("[Timer] Timer process timeout signal must be emitted") {
+ SIGNAL_WATCH(test_timer, SNAME("timeout"));
+ test_timer->start(0.1);
+
+ SceneTree::get_singleton()->process(0.2);
+
+ Array signal_args;
+ signal_args.push_back(Array());
+
+ SIGNAL_CHECK(SNAME("timeout"), signal_args);
+
+ SIGNAL_UNWATCH(test_timer, SNAME("timeout"));
+ }
+
+ SUBCASE("[Timer] Timer process timeout signal must not be emitted") {
+ SIGNAL_WATCH(test_timer, SNAME("timeout"));
+ test_timer->start(0.1);
+
+ SceneTree::get_singleton()->process(0.05);
+
+ Array signal_args;
+ signal_args.push_back(Array());
+
+ SIGNAL_CHECK_FALSE(SNAME("timeout"));
+
+ SIGNAL_UNWATCH(test_timer, SNAME("timeout"));
+ }
+
+ test_timer->set_timer_process_callback(Timer::TimerProcessCallback::TIMER_PROCESS_PHYSICS);
+
+ SUBCASE("[Timer] Timer physics process timeout signal must be emitted") {
+ SIGNAL_WATCH(test_timer, SNAME("timeout"));
+ test_timer->start(0.1);
+
+ SceneTree::get_singleton()->physics_process(0.2);
+
+ Array signal_args;
+ signal_args.push_back(Array());
+
+ SIGNAL_CHECK(SNAME("timeout"), signal_args);
+
+ SIGNAL_UNWATCH(test_timer, SNAME("timeout"));
+ }
+
+ SUBCASE("[Timer] Timer physics process timeout signal must not be emitted") {
+ SIGNAL_WATCH(test_timer, SNAME("timeout"));
+ test_timer->start(0.1);
+
+ SceneTree::get_singleton()->physics_process(0.05);
+
+ Array signal_args;
+ signal_args.push_back(Array());
+
+ SIGNAL_CHECK_FALSE(SNAME("timeout"));
+
+ SIGNAL_UNWATCH(test_timer, SNAME("timeout"));
+ }
+
+ memdelete(test_timer);
+}
+
+} // namespace TestTimer
+
+#endif // TEST_TIMER_H
diff --git a/tests/test_macros.h b/tests/test_macros.h
index 25e48c1e05..10f4c59a90 100644
--- a/tests/test_macros.h
+++ b/tests/test_macros.h
@@ -406,4 +406,71 @@ public:
#define SIGNAL_CHECK_FALSE(m_signal) CHECK(SignalWatcher::get_singleton()->check_false(m_signal));
#define SIGNAL_DISCARD(m_signal) SignalWatcher::get_singleton()->discard_signal(m_signal);
+#define MULTICHECK_STRING_EQ(m_obj, m_func, m_param1, m_eq) \
+ CHECK(m_obj.m_func(m_param1) == m_eq); \
+ CHECK(m_obj.m_func(U##m_param1) == m_eq); \
+ CHECK(m_obj.m_func(L##m_param1) == m_eq); \
+ CHECK(m_obj.m_func(String(m_param1)) == m_eq);
+
+#define MULTICHECK_STRING_INT_EQ(m_obj, m_func, m_param1, m_param2, m_eq) \
+ CHECK(m_obj.m_func(m_param1, m_param2) == m_eq); \
+ CHECK(m_obj.m_func(U##m_param1, m_param2) == m_eq); \
+ CHECK(m_obj.m_func(L##m_param1, m_param2) == m_eq); \
+ CHECK(m_obj.m_func(String(m_param1), m_param2) == m_eq);
+
+#define MULTICHECK_STRING_INT_INT_EQ(m_obj, m_func, m_param1, m_param2, m_param3, m_eq) \
+ CHECK(m_obj.m_func(m_param1, m_param2, m_param3) == m_eq); \
+ CHECK(m_obj.m_func(U##m_param1, m_param2, m_param3) == m_eq); \
+ CHECK(m_obj.m_func(L##m_param1, m_param2, m_param3) == m_eq); \
+ CHECK(m_obj.m_func(String(m_param1), m_param2, m_param3) == m_eq);
+
+#define MULTICHECK_STRING_STRING_EQ(m_obj, m_func, m_param1, m_param2, m_eq) \
+ CHECK(m_obj.m_func(m_param1, m_param2) == m_eq); \
+ CHECK(m_obj.m_func(U##m_param1, U##m_param2) == m_eq); \
+ CHECK(m_obj.m_func(L##m_param1, L##m_param2) == m_eq); \
+ CHECK(m_obj.m_func(String(m_param1), String(m_param2)) == m_eq);
+
+#define MULTICHECK_GET_SLICE(m_obj, m_param1, m_slices) \
+ for (int i = 0; i < m_obj.get_slice_count(m_param1); ++i) { \
+ CHECK(m_obj.get_slice(m_param1, i) == m_slices[i]); \
+ } \
+ for (int i = 0; i < m_obj.get_slice_count(U##m_param1); ++i) { \
+ CHECK(m_obj.get_slice(U##m_param1, i) == m_slices[i]); \
+ } \
+ for (int i = 0; i < m_obj.get_slice_count(L##m_param1); ++i) { \
+ CHECK(m_obj.get_slice(L##m_param1, i) == m_slices[i]); \
+ } \
+ for (int i = 0; i < m_obj.get_slice_count(String(m_param1)); ++i) { \
+ CHECK(m_obj.get_slice(String(m_param1), i) == m_slices[i]); \
+ }
+
+#define MULTICHECK_SPLIT(m_obj, m_func, m_param1, m_param2, m_param3, m_slices, m_expected_size) \
+ do { \
+ Vector<String> string_list; \
+ \
+ string_list = m_obj.m_func(m_param1, m_param2, m_param3); \
+ CHECK(m_expected_size == string_list.size()); \
+ for (int i = 0; i < string_list.size(); ++i) { \
+ CHECK(string_list[i] == m_slices[i]); \
+ } \
+ \
+ string_list = m_obj.m_func(U##m_param1, m_param2, m_param3); \
+ CHECK(m_expected_size == string_list.size()); \
+ for (int i = 0; i < string_list.size(); ++i) { \
+ CHECK(string_list[i] == m_slices[i]); \
+ } \
+ \
+ string_list = m_obj.m_func(L##m_param1, m_param2, m_param3); \
+ CHECK(m_expected_size == string_list.size()); \
+ for (int i = 0; i < string_list.size(); ++i) { \
+ CHECK(string_list[i] == m_slices[i]); \
+ } \
+ \
+ string_list = m_obj.m_func(String(m_param1), m_param2, m_param3); \
+ CHECK(m_expected_size == string_list.size()); \
+ for (int i = 0; i < string_list.size(); ++i) { \
+ CHECK(string_list[i] == m_slices[i]); \
+ } \
+ } while (0)
+
#endif // TEST_MACROS_H
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 56bd8739c6..69d8113e64 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -118,6 +118,7 @@
#include "tests/scene/test_sprite_frames.h"
#include "tests/scene/test_text_edit.h"
#include "tests/scene/test_theme.h"
+#include "tests/scene/test_timer.h"
#include "tests/scene/test_viewport.h"
#include "tests/scene/test_visual_shader.h"
#include "tests/scene/test_window.h"
@@ -187,7 +188,7 @@ int test_main(int argc, char *argv[]) {
}
// Doctest runner.
doctest::Context test_context;
- List<String> test_args;
+ LocalVector<String> test_args;
// Clean arguments of "--test" from the args.
for (int x = 0; x < argc; x++) {
@@ -200,7 +201,7 @@ int test_main(int argc, char *argv[]) {
if (test_args.size() > 0) {
// Convert Godot command line arguments back to standard arguments.
char **doctest_args = new char *[test_args.size()];
- for (int x = 0; x < test_args.size(); x++) {
+ for (uint32_t x = 0; x < test_args.size(); x++) {
// Operation to convert Godot string to non wchar string.
CharString cs = test_args[x].utf8();
const char *str = cs.get_data();
@@ -212,7 +213,7 @@ int test_main(int argc, char *argv[]) {
test_context.applyCommandLine(test_args.size(), doctest_args);
- for (int x = 0; x < test_args.size(); x++) {
+ for (uint32_t x = 0; x < test_args.size(); x++) {
delete[] doctest_args[x];
}
delete[] doctest_args;