summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core/io/test_http_client.h2
-rw-r--r--tests/core/io/test_json_native.h160
-rw-r--r--tests/core/object/test_class_db.h44
-rw-r--r--tests/core/object/test_object.h25
-rw-r--r--tests/core/string/test_string.h59
-rw-r--r--tests/core/variant/test_dictionary.h3
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl28
-rw-r--r--tests/python_build/fixtures/glsl/compute_expected_full.glsl14
-rw-r--r--tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl34
-rw-r--r--tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl14
-rw-r--r--tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl27
-rw-r--r--tests/scene/test_audio_stream_wav.h2
-rw-r--r--tests/scene/test_button.h66
-rw-r--r--tests/scene/test_gradient_texture.h87
-rw-r--r--tests/scene/test_node_2d.h125
-rw-r--r--tests/scene/test_option_button.h136
-rw-r--r--tests/scene/test_path_2d.h2
-rw-r--r--tests/scene/test_path_3d.h2
-rw-r--r--tests/scene/test_primitives.h6
-rw-r--r--tests/scene/test_style_box_texture.h194
-rw-r--r--tests/scene/test_tree.h175
-rw-r--r--tests/servers/test_navigation_server_3d.h160
-rw-r--r--tests/test_main.cpp6
23 files changed, 1338 insertions, 33 deletions
diff --git a/tests/core/io/test_http_client.h b/tests/core/io/test_http_client.h
index 961c653a0a..114ce3b4ed 100644
--- a/tests/core/io/test_http_client.h
+++ b/tests/core/io/test_http_client.h
@@ -41,7 +41,7 @@ namespace TestHTTPClient {
TEST_CASE("[HTTPClient] Instantiation") {
Ref<HTTPClient> client = HTTPClient::create();
- CHECK_MESSAGE(client != nullptr, "A HTTP Client created should not be a null pointer");
+ CHECK_MESSAGE(client.is_valid(), "A HTTP Client created should not be a null pointer");
}
TEST_CASE("[HTTPClient] query_string_from_dict") {
diff --git a/tests/core/io/test_json_native.h b/tests/core/io/test_json_native.h
new file mode 100644
index 0000000000..819078ac57
--- /dev/null
+++ b/tests/core/io/test_json_native.h
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/* test_json_native.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_JSON_NATIVE_H
+#define TEST_JSON_NATIVE_H
+
+#include "core/io/json.h"
+
+namespace TestJSONNative {
+
+bool compare_variants(Variant variant_1, Variant variant_2, int depth = 0) {
+ if (depth > 100) {
+ return false;
+ }
+ if (variant_1.get_type() == Variant::RID && variant_2.get_type() == Variant::RID) {
+ return true;
+ }
+ if (variant_1.get_type() == Variant::CALLABLE || variant_2.get_type() == Variant::CALLABLE) {
+ return true;
+ }
+
+ List<PropertyInfo> variant_1_properties;
+ variant_1.get_property_list(&variant_1_properties);
+ List<PropertyInfo> variant_2_properties;
+ variant_2.get_property_list(&variant_2_properties);
+
+ if (variant_1_properties.size() != variant_2_properties.size()) {
+ return false;
+ }
+
+ for (List<PropertyInfo>::Element *E = variant_1_properties.front(); E; E = E->next()) {
+ String name = E->get().name;
+ Variant variant_1_value = variant_1.get(name);
+ Variant variant_2_value = variant_2.get(name);
+
+ if (!compare_variants(variant_1_value, variant_2_value, depth + 1)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+TEST_CASE("[JSON][Native][SceneTree] Conversion between native and JSON formats") {
+ for (int variant_i = 0; variant_i < Variant::VARIANT_MAX; variant_i++) {
+ Variant::Type type = static_cast<Variant::Type>(variant_i);
+ Variant native_data;
+ Callable::CallError error;
+
+ if (type == Variant::Type::INT || type == Variant::Type::FLOAT) {
+ Variant value = int64_t(INT64_MAX);
+ const Variant *args[] = { &value };
+ Variant::construct(type, native_data, args, 1, error);
+ } else if (type == Variant::Type::OBJECT) {
+ Ref<JSON> json = memnew(JSON);
+ native_data = json;
+ } else if (type == Variant::Type::DICTIONARY) {
+ Dictionary dictionary;
+ dictionary["key"] = "value";
+ native_data = dictionary;
+ } else if (type == Variant::Type::ARRAY) {
+ Array array;
+ array.push_back("element1");
+ array.push_back("element2");
+ native_data = array;
+ } else if (type == Variant::Type::PACKED_BYTE_ARRAY) {
+ PackedByteArray packed_array;
+ packed_array.push_back(1);
+ packed_array.push_back(2);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_INT32_ARRAY) {
+ PackedInt32Array packed_array;
+ packed_array.push_back(INT32_MIN);
+ packed_array.push_back(INT32_MAX);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_INT64_ARRAY) {
+ PackedInt64Array packed_array;
+ packed_array.push_back(INT64_MIN);
+ packed_array.push_back(INT64_MAX);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_FLOAT32_ARRAY) {
+ PackedFloat32Array packed_array;
+ packed_array.push_back(FLT_MIN);
+ packed_array.push_back(FLT_MAX);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_FLOAT64_ARRAY) {
+ PackedFloat64Array packed_array;
+ packed_array.push_back(DBL_MIN);
+ packed_array.push_back(DBL_MAX);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_STRING_ARRAY) {
+ PackedStringArray packed_array;
+ packed_array.push_back("string1");
+ packed_array.push_back("string2");
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_VECTOR2_ARRAY) {
+ PackedVector2Array packed_array;
+ Vector2 vector(1.0, 2.0);
+ packed_array.push_back(vector);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_VECTOR3_ARRAY) {
+ PackedVector3Array packed_array;
+ Vector3 vector(1.0, 2.0, 3.0);
+ packed_array.push_back(vector);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_COLOR_ARRAY) {
+ PackedColorArray packed_array;
+ Color color(1.0, 1.0, 1.0);
+ packed_array.push_back(color);
+ native_data = packed_array;
+ } else if (type == Variant::Type::PACKED_VECTOR4_ARRAY) {
+ PackedVector4Array packed_array;
+ Vector4 vector(1.0, 2.0, 3.0, 4.0);
+ packed_array.push_back(vector);
+ native_data = packed_array;
+ } else {
+ Variant::construct(type, native_data, nullptr, 0, error);
+ }
+ Variant json_converted_from_native = JSON::from_native(native_data, true, true);
+ Variant variant_native_converted = JSON::to_native(json_converted_from_native, true, true);
+ CHECK_MESSAGE(compare_variants(native_data, variant_native_converted),
+ vformat("Conversion from native to JSON type %s and back successful. \nNative: %s \nNative Converted: %s \nError: %s\nConversion from native to JSON type %s successful: %s",
+ Variant::get_type_name(type),
+ native_data,
+ variant_native_converted,
+ itos(error.error),
+ Variant::get_type_name(type),
+ json_converted_from_native));
+ }
+}
+} // namespace TestJSONNative
+
+#endif // TEST_JSON_NATIVE_H
diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h
index d2d7b6a8b2..924e93129d 100644
--- a/tests/core/object/test_class_db.h
+++ b/tests/core/object/test_class_db.h
@@ -289,6 +289,38 @@ bool arg_default_value_is_assignable_to_type(const Context &p_context, const Var
return false;
}
+bool arg_default_value_is_valid_data(const Variant &p_val, String *r_err_msg = nullptr) {
+ switch (p_val.get_type()) {
+ case Variant::RID:
+ case Variant::ARRAY:
+ case Variant::DICTIONARY:
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ case Variant::PACKED_VECTOR4_ARRAY:
+ case Variant::CALLABLE:
+ case Variant::SIGNAL:
+ case Variant::OBJECT:
+ if (p_val.is_zero()) {
+ return true;
+ }
+ if (r_err_msg) {
+ *r_err_msg = "Must be zero.";
+ }
+ break;
+ default:
+ return true;
+ }
+
+ return false;
+}
+
void validate_property(const Context &p_context, const ExposedClass &p_class, const PropertyData &p_prop) {
const MethodData *setter = p_class.find_method_by_name(p_prop.setter);
@@ -411,6 +443,14 @@ void validate_argument(const Context &p_context, const ExposedClass &p_class, co
}
TEST_COND(!arg_defval_assignable_to_type, err_msg);
+
+ bool arg_defval_valid_data = arg_default_value_is_valid_data(p_arg.defval, &type_error_msg);
+
+ if (!type_error_msg.is_empty()) {
+ err_msg += " " + type_error_msg;
+ }
+
+ TEST_COND(!arg_defval_valid_data, err_msg);
}
}
@@ -563,7 +603,7 @@ void add_exposed_classes(Context &r_context) {
MethodData method;
method.name = method_info.name;
- TEST_FAIL_COND(!String(method.name).is_valid_identifier(),
+ TEST_FAIL_COND(!String(method.name).is_valid_ascii_identifier(),
"Method name is not a valid identifier: '", exposed_class.name, ".", method.name, "'.");
if (method_info.flags & METHOD_FLAG_VIRTUAL) {
@@ -689,7 +729,7 @@ void add_exposed_classes(Context &r_context) {
const MethodInfo &method_info = signal_map.get(K.key);
signal.name = method_info.name;
- TEST_FAIL_COND(!String(signal.name).is_valid_identifier(),
+ TEST_FAIL_COND(!String(signal.name).is_valid_ascii_identifier(),
"Signal name is not a valid identifier: '", exposed_class.name, ".", signal.name, "'.");
int i = 0;
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 57bc65328a..f1bb62cb70 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -174,6 +174,31 @@ TEST_CASE("[Object] Metadata") {
CHECK_MESSAGE(
meta_list2.size() == 0,
"The metadata list should contain 0 items after removing all metadata items.");
+
+ Object other;
+ object.set_meta("conflicting_meta", "string");
+ object.set_meta("not_conflicting_meta", 123);
+ other.set_meta("conflicting_meta", Color(0, 1, 0));
+ other.set_meta("other_meta", "other");
+ object.merge_meta_from(&other);
+
+ CHECK_MESSAGE(
+ Color(object.get_meta("conflicting_meta")).is_equal_approx(Color(0, 1, 0)),
+ "String meta should be overwritten with Color after merging.");
+
+ CHECK_MESSAGE(
+ int(object.get_meta("not_conflicting_meta")) == 123,
+ "Not conflicting meta on destination should be kept intact.");
+
+ CHECK_MESSAGE(
+ object.get_meta("other_meta", String()) == "other",
+ "Not conflicting meta name on source should merged.");
+
+ List<StringName> meta_list3;
+ object.get_meta_list(&meta_list3);
+ CHECK_MESSAGE(
+ meta_list3.size() == 3,
+ "The metadata list should contain 3 items after merging meta from two objects.");
}
TEST_CASE("[Object] Construction") {
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 933eeff524..a9f615af84 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -433,6 +433,19 @@ TEST_CASE("[String] Insertion") {
String s = "Who is Frederic?";
s = s.insert(s.find("?"), " Chopin");
CHECK(s == "Who is Frederic Chopin?");
+
+ s = "foobar";
+ CHECK(s.insert(0, "X") == "Xfoobar");
+ CHECK(s.insert(-100, "X") == "foobar");
+ CHECK(s.insert(6, "X") == "foobarX");
+ CHECK(s.insert(100, "X") == "foobarX");
+ CHECK(s.insert(2, "") == "foobar");
+
+ s = "";
+ CHECK(s.insert(0, "abc") == "abc");
+ CHECK(s.insert(100, "abc") == "abc");
+ CHECK(s.insert(-100, "abc") == "");
+ CHECK(s.insert(0, "") == "");
}
TEST_CASE("[String] Erasing") {
@@ -1811,31 +1824,45 @@ TEST_CASE("[String] SHA1/SHA256/MD5") {
}
TEST_CASE("[String] Join") {
- String s = ", ";
+ String comma = ", ";
+ String empty = "";
Vector<String> parts;
+
+ CHECK(comma.join(parts) == "");
+ CHECK(empty.join(parts) == "");
+
parts.push_back("One");
+ CHECK(comma.join(parts) == "One");
+ CHECK(empty.join(parts) == "One");
+
parts.push_back("B");
parts.push_back("C");
- String t = s.join(parts);
- CHECK(t == "One, B, C");
+ CHECK(comma.join(parts) == "One, B, C");
+ CHECK(empty.join(parts) == "OneBC");
+
+ parts.push_back("");
+ CHECK(comma.join(parts) == "One, B, C, ");
+ CHECK(empty.join(parts) == "OneBC");
}
TEST_CASE("[String] Is_*") {
- static const char *data[12] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1" };
- static bool isnum[12] = { true, true, true, false, false, false, false, false, false, false, false, false };
- static bool isint[12] = { true, true, false, false, false, false, false, false, false, false, false, false };
- static bool ishex[12] = { true, true, false, false, true, false, true, false, true, false, false, false };
- static bool ishex_p[12] = { false, false, false, false, false, false, false, true, false, false, false, false };
- static bool isflt[12] = { true, true, true, false, true, true, false, false, false, false, false, false };
- static bool isid[12] = { false, false, false, false, false, false, false, false, true, true, false, false };
+ static const char *data[13] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1", "文字" };
+ static bool isnum[13] = { true, true, true, false, false, false, false, false, false, false, false, false, false };
+ static bool isint[13] = { true, true, false, false, false, false, false, false, false, false, false, false, false };
+ static bool ishex[13] = { true, true, false, false, true, false, true, false, true, false, false, false, false };
+ static bool ishex_p[13] = { false, false, false, false, false, false, false, true, false, false, false, false, false };
+ static bool isflt[13] = { true, true, true, false, true, true, false, false, false, false, false, false, false };
+ static bool isaid[13] = { false, false, false, false, false, false, false, false, true, true, false, false, false };
+ static bool isuid[13] = { false, false, false, false, false, false, false, false, true, true, false, false, true };
for (int i = 0; i < 12; i++) {
- String s = String(data[i]);
+ String s = String::utf8(data[i]);
CHECK(s.is_numeric() == isnum[i]);
CHECK(s.is_valid_int() == isint[i]);
CHECK(s.is_valid_hex_number(false) == ishex[i]);
CHECK(s.is_valid_hex_number(true) == ishex_p[i]);
CHECK(s.is_valid_float() == isflt[i]);
- CHECK(s.is_valid_identifier() == isid[i]);
+ CHECK(s.is_valid_ascii_identifier() == isaid[i]);
+ CHECK(s.is_valid_unicode_identifier() == isuid[i]);
}
}
@@ -1863,16 +1890,16 @@ TEST_CASE("[String] validate_node_name") {
TEST_CASE("[String] validate_identifier") {
String empty_string;
- CHECK(empty_string.validate_identifier() == "_");
+ CHECK(empty_string.validate_ascii_identifier() == "_");
String numeric_only = "12345";
- CHECK(numeric_only.validate_identifier() == "_12345");
+ CHECK(numeric_only.validate_ascii_identifier() == "_12345");
String name_with_spaces = "Name with spaces";
- CHECK(name_with_spaces.validate_identifier() == "Name_with_spaces");
+ CHECK(name_with_spaces.validate_ascii_identifier() == "Name_with_spaces");
String name_with_invalid_chars = U"Invalid characters:@*#&世界";
- CHECK(name_with_invalid_chars.validate_identifier() == "Invalid_characters_______");
+ CHECK(name_with_invalid_chars.validate_ascii_identifier() == "Invalid_characters_______");
}
TEST_CASE("[String] Variant indexed get") {
diff --git a/tests/core/variant/test_dictionary.h b/tests/core/variant/test_dictionary.h
index aba20972d9..7061bc66dc 100644
--- a/tests/core/variant/test_dictionary.h
+++ b/tests/core/variant/test_dictionary.h
@@ -66,8 +66,7 @@ TEST_CASE("[Dictionary] Assignment using bracket notation ([])") {
map[StringName("HelloName")] = 6;
CHECK(int(map[StringName("HelloName")]) == 6);
- // Check that StringName key is converted to String.
- CHECK(int(map.find_key(6).get_type()) == Variant::STRING);
+ CHECK(int(map.find_key(6).get_type()) == Variant::STRING_NAME);
map[StringName("HelloName")] = 7;
CHECK(int(map[StringName("HelloName")]) == 7);
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
index 8ad5a23eb5..db5f54e3d8 100644
--- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
@@ -37,10 +37,34 @@ protected:
static const Feedback* _feedbacks=nullptr;
static const char _vertex_code[]={
-10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,51,32,118,101,114,116,101,120,59,10,10,111,117,116,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,32,61,32,118,101,99,52,40,118,101,114,116,101,120,46,120,44,49,44,48,44,49,41,59,10,125,10,10, 0};
+R"<!>(
+precision highp float;
+precision highp int;
+
+layout(location = 0) in highp vec3 vertex;
+
+out highp vec4 position_interp;
+
+void main() {
+ position_interp = vec4(vertex.x,1,0,1);
+}
+
+)<!>"
+ };
static const char _fragment_code[]={
-10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,105,110,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,104,105,103,104,112,32,102,108,111,97,116,32,100,101,112,116,104,32,61,32,40,40,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,122,32,47,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,119,41,32,43,32,49,46,48,41,59,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,101,112,116,104,41,59,10,125,10, 0};
+R"<!>(
+precision highp float;
+precision highp int;
+
+in highp vec4 position_interp;
+
+void main() {
+ highp float depth = ((position_interp.z / position_interp.w) + 1.0);
+ frag_color = vec4(depth);
+}
+)<!>"
+ };
_setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_feedbacks,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
}
diff --git a/tests/python_build/fixtures/glsl/compute_expected_full.glsl b/tests/python_build/fixtures/glsl/compute_expected_full.glsl
index b937d732c8..386d14f1aa 100644
--- a/tests/python_build/fixtures/glsl/compute_expected_full.glsl
+++ b/tests/python_build/fixtures/glsl/compute_expected_full.glsl
@@ -3,6 +3,18 @@
#define COMPUTE_SHADER_GLSL_RAW_H
static const char compute_shader_glsl[] = {
- 35,91,99,111,109,112,117,116,101,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,118,101,99,51,32,115,116,97,116,105,99,95,108,105,103,104,116,32,61,32,118,101,99,51,40,48,44,32,49,44,32,48,41,59,10,125,10,0
+R"<!>(#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+
+#define M_PI 3.14159265359
+
+void main() {
+ vec3 static_light = vec3(0, 1, 0);
+}
+)<!>"
};
#endif
diff --git a/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl
index 3f53a17fac..b7329b6a79 100644
--- a/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl
+++ b/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl
@@ -3,6 +3,38 @@
#define VERTEX_FRAGMENT_SHADER_GLSL_RAW_H
static const char vertex_fragment_shader_glsl[] = {
- 35,91,118,101,114,115,105,111,110,115,93,10,10,108,105,110,101,115,32,61,32,34,35,100,101,102,105,110,101,32,77,79,68,69,95,76,73,78,69,83,34,59,10,10,35,91,118,101,114,116,101,120,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,51,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,35,105,102,100,101,102,32,77,79,68,69,95,76,73,78,69,83,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,51,40,48,44,48,44,49,41,59,10,35,101,110,100,105,102,10,125,10,10,35,91,102,114,97,103,109,101,110,116,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,100,115,116,95,99,111,108,111,114,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,100,115,116,95,99,111,108,111,114,32,61,32,118,101,99,52,40,49,44,49,44,48,44,48,41,59,10,125,10,0
+R"<!>(#[versions]
+
+lines = "#define MODE_LINES";
+
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) out vec3 uv_interp;
+
+void main() {
+
+#ifdef MODE_LINES
+ uv_interp = vec3(0,0,1);
+#endif
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define M_PI 3.14159265359
+
+layout(location = 0) out vec4 dst_color;
+
+void main() {
+ dst_color = vec4(1,1,0,0);
+}
+)<!>"
};
#endif
diff --git a/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl b/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl
index b59923e28a..1184510020 100644
--- a/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl
+++ b/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl
@@ -11,7 +11,19 @@ public:
ComputeShaderRD() {
static const char _compute_code[] = {
-10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,66,76,79,67,75,95,83,73,90,69,32,56,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,105,110,116,32,116,32,61,32,66,76,79,67,75,95,83,73,90,69,32,43,32,49,59,10,125,10,0
+R"<!>(
+#version 450
+
+#VERSION_DEFINES
+
+#define BLOCK_SIZE 8
+
+#define M_PI 3.14159265359
+
+void main() {
+ uint t = BLOCK_SIZE + 1;
+}
+)<!>"
};
setup(nullptr, nullptr, _compute_code, "ComputeShaderRD");
}
diff --git a/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl
index ff804dbf89..2f809f1bfe 100644
--- a/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl
+++ b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl
@@ -11,10 +11,33 @@ public:
VertexFragmentShaderRD() {
static const char _vertex_code[] = {
-10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,50,40,48,44,32,49,41,59,10,125,10,10,0
+R"<!>(
+#version 450
+
+#VERSION_DEFINES
+
+#define M_PI 3.14159265359
+
+layout(location = 0) out vec2 uv_interp;
+
+void main() {
+ uv_interp = vec2(0, 1);
+}
+
+)<!>"
};
static const char _fragment_code[] = {
-10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,50,40,49,44,32,48,41,59,10,125,10,0
+R"<!>(
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
+
+void main() {
+ uv_interp = vec2(1, 0);
+}
+)<!>"
};
setup(_vertex_code, _fragment_code, nullptr, "VertexFragmentShaderRD");
}
diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h
index e8f3c9e8f5..5166cd3c13 100644
--- a/tests/scene/test_audio_stream_wav.h
+++ b/tests/scene/test_audio_stream_wav.h
@@ -159,6 +159,8 @@ void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo,
for (const ResourceImporter::ImportOption &E : options_list) {
options_map[E.option.name] = E.default_value;
}
+ // Compressed streams can't be saved, disable compression.
+ options_map["compress/mode"] = 0;
REQUIRE(wav_importer->import(save_path, save_path, options_map, nullptr) == OK);
diff --git a/tests/scene/test_button.h b/tests/scene/test_button.h
new file mode 100644
index 0000000000..55097edc95
--- /dev/null
+++ b/tests/scene/test_button.h
@@ -0,0 +1,66 @@
+/**************************************************************************/
+/* test_button.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_BUTTON_H
+#define TEST_BUTTON_H
+
+#include "scene/gui/button.h"
+#include "scene/main/window.h"
+
+#include "tests/test_macros.h"
+
+namespace TestButton {
+TEST_CASE("[SceneTree][Button] is_hovered()") {
+ // Create new button instance.
+ Button *button = memnew(Button);
+ CHECK(button != nullptr);
+ Window *root = SceneTree::get_singleton()->get_root();
+ root->add_child(button);
+
+ // Set up button's size and position.
+ button->set_size(Size2i(50, 50));
+ button->set_position(Size2i(10, 10));
+
+ // Button should initially be not hovered.
+ CHECK(button->is_hovered() == false);
+
+ // Simulate mouse entering the button.
+ SEND_GUI_MOUSE_MOTION_EVENT(Point2i(25, 25), MouseButtonMask::NONE, Key::NONE);
+ CHECK(button->is_hovered() == true);
+
+ // Simulate mouse exiting the button.
+ SEND_GUI_MOUSE_MOTION_EVENT(Point2i(150, 150), MouseButtonMask::NONE, Key::NONE);
+ CHECK(button->is_hovered() == false);
+
+ memdelete(button);
+}
+
+} //namespace TestButton
+#endif // TEST_BUTTON_H
diff --git a/tests/scene/test_gradient_texture.h b/tests/scene/test_gradient_texture.h
new file mode 100644
index 0000000000..16a92fbe4a
--- /dev/null
+++ b/tests/scene/test_gradient_texture.h
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/* test_gradient_texture.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_GRADIENT_TEXTURE_H
+#define TEST_GRADIENT_TEXTURE_H
+
+#include "scene/resources/gradient_texture.h"
+
+#include "tests/test_macros.h"
+
+namespace TestGradientTexture {
+
+// [SceneTree] in a test case name enables initializing a mock render server,
+// which ImageTexture is dependent on.
+TEST_CASE("[SceneTree][GradientTexture1D] Create GradientTexture1D") {
+ Ref<GradientTexture1D> gradient_texture = memnew(GradientTexture1D);
+
+ Ref<Gradient> test_gradient = memnew(Gradient);
+ gradient_texture->set_gradient(test_gradient);
+ CHECK(gradient_texture->get_gradient() == test_gradient);
+
+ gradient_texture->set_width(83);
+ CHECK(gradient_texture->get_width() == 83);
+
+ gradient_texture->set_use_hdr(true);
+ CHECK(gradient_texture->is_using_hdr());
+}
+
+TEST_CASE("[SceneTree][GradientTexture2D] Create GradientTexture2D") {
+ Ref<GradientTexture2D> gradient_texture = memnew(GradientTexture2D);
+
+ Ref<Gradient> test_gradient = memnew(Gradient);
+ gradient_texture->set_gradient(test_gradient);
+ CHECK(gradient_texture->get_gradient() == test_gradient);
+
+ gradient_texture->set_width(82);
+ CHECK(gradient_texture->get_width() == 82);
+
+ gradient_texture->set_height(81);
+ CHECK(gradient_texture->get_height() == 81);
+
+ gradient_texture->set_use_hdr(true);
+ CHECK(gradient_texture->is_using_hdr());
+
+ gradient_texture->set_fill(GradientTexture2D::Fill::FILL_SQUARE);
+ CHECK(gradient_texture->get_fill() == GradientTexture2D::Fill::FILL_SQUARE);
+
+ gradient_texture->set_fill_from(Vector2(0.2, 0.25));
+ CHECK(gradient_texture->get_fill_from() == Vector2(0.2, 0.25));
+
+ gradient_texture->set_fill_to(Vector2(0.35, 0.5));
+ CHECK(gradient_texture->get_fill_to() == Vector2(0.35, 0.5));
+
+ gradient_texture->set_repeat(GradientTexture2D::Repeat::REPEAT);
+ CHECK(gradient_texture->get_repeat() == GradientTexture2D::Repeat::REPEAT);
+}
+
+} //namespace TestGradientTexture
+
+#endif // TEST_GRADIENT_TEXTURE_H
diff --git a/tests/scene/test_node_2d.h b/tests/scene/test_node_2d.h
index 8cf6408438..e8e7b2880d 100644
--- a/tests/scene/test_node_2d.h
+++ b/tests/scene/test_node_2d.h
@@ -86,6 +86,131 @@ TEST_CASE("[SceneTree][Node2D]") {
}
}
+TEST_CASE("[SceneTree][Node2D] Utility methods") {
+ Node2D *test_node1 = memnew(Node2D);
+ Node2D *test_node2 = memnew(Node2D);
+ Node2D *test_node3 = memnew(Node2D);
+ Node2D *test_sibling = memnew(Node2D);
+ SceneTree::get_singleton()->get_root()->add_child(test_node1);
+
+ test_node1->set_position(Point2(100, 100));
+ test_node1->set_rotation(Math::deg_to_rad(30.0));
+ test_node1->set_scale(Size2(1, 1));
+ test_node1->add_child(test_node2);
+
+ test_node2->set_position(Point2(10, 0));
+ test_node2->set_rotation(Math::deg_to_rad(60.0));
+ test_node2->set_scale(Size2(1, 1));
+ test_node2->add_child(test_node3);
+ test_node2->add_child(test_sibling);
+
+ test_node3->set_position(Point2(0, 10));
+ test_node3->set_rotation(Math::deg_to_rad(0.0));
+ test_node3->set_scale(Size2(2, 2));
+
+ test_sibling->set_position(Point2(5, 10));
+ test_sibling->set_rotation(Math::deg_to_rad(90.0));
+ test_sibling->set_scale(Size2(2, 1));
+
+ SUBCASE("[Node2D] look_at") {
+ test_node3->look_at(Vector2(1, 1));
+
+ CHECK(test_node3->get_global_position().is_equal_approx(Point2(98.66026, 105)));
+ CHECK(Math::is_equal_approx(test_node3->get_global_rotation(), real_t(-2.32477)));
+ CHECK(test_node3->get_global_scale().is_equal_approx(Vector2(2, 2)));
+
+ CHECK(test_node3->get_position().is_equal_approx(Vector2(0, 10)));
+ CHECK(Math::is_equal_approx(test_node3->get_rotation(), real_t(2.38762)));
+ CHECK(test_node3->get_scale().is_equal_approx(Vector2(2, 2)));
+
+ test_node3->look_at(Vector2(0, 10));
+
+ CHECK(test_node3->get_global_position().is_equal_approx(Vector2(98.66026, 105)));
+ CHECK(Math::is_equal_approx(test_node3->get_global_rotation(), real_t(-2.37509)));
+ CHECK(test_node3->get_global_scale().is_equal_approx(Vector2(2, 2)));
+
+ CHECK(test_node3->get_position().is_equal_approx(Vector2(0, 10)));
+ CHECK(Math::is_equal_approx(test_node3->get_rotation(), real_t(2.3373)));
+ CHECK(test_node3->get_scale().is_equal_approx(Vector2(2, 2)));
+
+ // Don't do anything if look_at own position.
+ test_node3->look_at(test_node3->get_global_position());
+
+ CHECK(test_node3->get_global_position().is_equal_approx(Vector2(98.66026, 105)));
+ CHECK(Math::is_equal_approx(test_node3->get_global_rotation(), real_t(-2.37509)));
+ CHECK(test_node3->get_global_scale().is_equal_approx(Vector2(2, 2)));
+
+ CHECK(test_node3->get_position().is_equal_approx(Vector2(0, 10)));
+ CHECK(Math::is_equal_approx(test_node3->get_rotation(), real_t(2.3373)));
+ CHECK(test_node3->get_scale().is_equal_approx(Vector2(2, 2)));
+
+ // Revert any rotation caused by look_at, must run after look_at tests
+ test_node3->set_rotation(Math::deg_to_rad(0.0));
+ }
+
+ SUBCASE("[Node2D] get_angle_to") {
+ CHECK(Math::is_equal_approx(test_node3->get_angle_to(Vector2(1, 1)), real_t(2.38762)));
+ CHECK(Math::is_equal_approx(test_node3->get_angle_to(Vector2(0, 10)), real_t(2.3373)));
+ CHECK(Math::is_equal_approx(test_node3->get_angle_to(Vector2(2, -5)), real_t(2.42065)));
+ CHECK(Math::is_equal_approx(test_node3->get_angle_to(Vector2(-2, 5)), real_t(2.3529)));
+
+ // Return 0 when get_angle_to own position.
+ CHECK(Math::is_equal_approx(test_node3->get_angle_to(test_node3->get_global_position()), real_t(0)));
+ }
+
+ SUBCASE("[Node2D] to_local") {
+ Point2 node3_local = test_node3->to_local(Point2(1, 2));
+ CHECK(node3_local.is_equal_approx(Point2(-51.5, 48.83013)));
+
+ node3_local = test_node3->to_local(Point2(-2, 1));
+ CHECK(node3_local.is_equal_approx(Point2(-52, 50.33013)));
+
+ node3_local = test_node3->to_local(Point2(0, 0));
+ CHECK(node3_local.is_equal_approx(Point2(-52.5, 49.33013)));
+
+ node3_local = test_node3->to_local(test_node3->get_global_position());
+ CHECK(node3_local.is_equal_approx(Point2(0, 0)));
+ }
+
+ SUBCASE("[Node2D] to_global") {
+ Point2 node3_global = test_node3->to_global(Point2(1, 2));
+ CHECK(node3_global.is_equal_approx(Point2(94.66026, 107)));
+
+ node3_global = test_node3->to_global(Point2(-2, 1));
+ CHECK(node3_global.is_equal_approx(Point2(96.66026, 101)));
+
+ node3_global = test_node3->to_global(Point2(0, 0));
+ CHECK(node3_global.is_equal_approx(test_node3->get_global_position()));
+ }
+
+ SUBCASE("[Node2D] get_relative_transform_to_parent") {
+ Transform2D relative_xform = test_node3->get_relative_transform_to_parent(test_node3);
+ CHECK(relative_xform.is_equal_approx(Transform2D()));
+
+ relative_xform = test_node3->get_relative_transform_to_parent(test_node2);
+ CHECK(relative_xform.get_origin().is_equal_approx(Vector2(0, 10)));
+ CHECK(Math::is_equal_approx(relative_xform.get_rotation(), real_t(0)));
+ CHECK(relative_xform.get_scale().is_equal_approx(Vector2(2, 2)));
+
+ relative_xform = test_node3->get_relative_transform_to_parent(test_node1);
+ CHECK(relative_xform.get_origin().is_equal_approx(Vector2(1.339746, 5)));
+ CHECK(Math::is_equal_approx(relative_xform.get_rotation(), real_t(1.0472)));
+ CHECK(relative_xform.get_scale().is_equal_approx(Vector2(2, 2)));
+
+ ERR_PRINT_OFF;
+ // In case of a sibling all transforms until the root are accumulated.
+ Transform2D xform = test_node3->get_relative_transform_to_parent(test_sibling);
+ Transform2D return_xform = test_node1->get_global_transform().inverse() * test_node3->get_global_transform();
+ CHECK(xform.is_equal_approx(return_xform));
+ ERR_PRINT_ON;
+ }
+
+ memdelete(test_sibling);
+ memdelete(test_node3);
+ memdelete(test_node2);
+ memdelete(test_node1);
+}
+
} // namespace TestNode2D
#endif // TEST_NODE_2D_H
diff --git a/tests/scene/test_option_button.h b/tests/scene/test_option_button.h
new file mode 100644
index 0000000000..56c1c7d611
--- /dev/null
+++ b/tests/scene/test_option_button.h
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/* test_option_button.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_OPTION_BUTTON_H
+#define TEST_OPTION_BUTTON_H
+
+#include "scene/gui/option_button.h"
+
+#include "tests/test_macros.h"
+
+namespace TestOptionButton {
+
+TEST_CASE("[SceneTree][OptionButton] Initialization") {
+ OptionButton *test_opt = memnew(OptionButton);
+
+ SUBCASE("There should be no options right after initialization") {
+ CHECK_FALSE(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 0);
+ }
+
+ memdelete(test_opt);
+}
+
+TEST_CASE("[SceneTree][OptionButton] Single item") {
+ OptionButton *test_opt = memnew(OptionButton);
+
+ SUBCASE("There should a single item after after adding one") {
+ test_opt->add_item("single", 1013);
+
+ CHECK(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 1);
+ CHECK(test_opt->get_item_index(1013) == 0);
+ CHECK(test_opt->get_item_id(0) == 1013);
+
+ test_opt->remove_item(0);
+
+ CHECK_FALSE(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 0);
+ }
+
+ SUBCASE("There should a single item after after adding an icon") {
+ Ref<Texture2D> test_icon = memnew(Texture2D);
+ test_opt->add_icon_item(test_icon, "icon", 345);
+
+ CHECK(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 1);
+ CHECK(test_opt->get_item_index(345) == 0);
+ CHECK(test_opt->get_item_id(0) == 345);
+
+ test_opt->remove_item(0);
+
+ CHECK_FALSE(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 0);
+ }
+
+ memdelete(test_opt);
+}
+
+TEST_CASE("[SceneTree][OptionButton] Complex structure") {
+ OptionButton *test_opt = memnew(OptionButton);
+
+ SUBCASE("Creating a complex structure and checking getters") {
+ // Regular item at index 0.
+ Ref<Texture2D> test_icon1 = memnew(Texture2D);
+ Ref<Texture2D> test_icon2 = memnew(Texture2D);
+ // Regular item at index 3.
+ Ref<Texture2D> test_icon4 = memnew(Texture2D);
+
+ test_opt->add_item("first", 100);
+ test_opt->add_icon_item(test_icon1, "second_icon", 101);
+ test_opt->add_icon_item(test_icon2, "third_icon", 102);
+ test_opt->add_item("fourth", 104);
+ test_opt->add_icon_item(test_icon4, "fifth_icon", 104);
+
+ // Disable test_icon4.
+ test_opt->set_item_disabled(4, true);
+
+ CHECK(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 5);
+
+ // Check for test_icon2.
+ CHECK(test_opt->get_item_index(102) == 2);
+ CHECK(test_opt->get_item_id(2) == 102);
+
+ // Remove the two regular items.
+ test_opt->remove_item(3);
+ test_opt->remove_item(0);
+
+ CHECK(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 3);
+
+ // Check test_icon4.
+ CHECK(test_opt->get_item_index(104) == 2);
+ CHECK(test_opt->get_item_id(2) == 104);
+
+ // Remove the two non-disabled icon items.
+ test_opt->remove_item(1);
+ test_opt->remove_item(0);
+
+ CHECK_FALSE(test_opt->has_selectable_items());
+ CHECK(test_opt->get_item_count() == 1);
+ }
+
+ memdelete(test_opt);
+}
+
+} // namespace TestOptionButton
+
+#endif // TEST_OPTION_BUTTON_H
diff --git a/tests/scene/test_path_2d.h b/tests/scene/test_path_2d.h
index 7b6cec96db..4703bfa3bb 100644
--- a/tests/scene/test_path_2d.h
+++ b/tests/scene/test_path_2d.h
@@ -40,7 +40,7 @@ namespace TestPath2D {
TEST_CASE("[SceneTree][Path2D] Initialization") {
SUBCASE("Path should be empty right after initialization") {
Path2D *test_path = memnew(Path2D);
- CHECK(test_path->get_curve() == nullptr);
+ CHECK(test_path->get_curve().is_null());
memdelete(test_path);
}
}
diff --git a/tests/scene/test_path_3d.h b/tests/scene/test_path_3d.h
index f779f514a4..70c7099d48 100644
--- a/tests/scene/test_path_3d.h
+++ b/tests/scene/test_path_3d.h
@@ -40,7 +40,7 @@ namespace TestPath3D {
TEST_CASE("[Path3D] Initialization") {
SUBCASE("Path should be empty right after initialization") {
Path3D *test_path = memnew(Path3D);
- CHECK(test_path->get_curve() == nullptr);
+ CHECK(test_path->get_curve().is_null());
memdelete(test_path);
}
}
diff --git a/tests/scene/test_primitives.h b/tests/scene/test_primitives.h
index f105e1ac04..59f23983e5 100644
--- a/tests/scene/test_primitives.h
+++ b/tests/scene/test_primitives.h
@@ -609,7 +609,7 @@ TEST_CASE("[SceneTree][Primitive][TubeTrail] TubeTrail Primitive") {
CHECK(tube->get_sections() >= 0);
CHECK(tube->get_section_length() > 0);
CHECK(tube->get_section_rings() >= 0);
- CHECK(tube->get_curve() == nullptr);
+ CHECK(tube->get_curve().is_null());
CHECK(tube->get_builtin_bind_pose_count() >= 0);
}
@@ -669,7 +669,7 @@ TEST_CASE("[SceneTree][Primitive][RibbonTrail] RibbonTrail Primitive") {
CHECK(ribbon->get_section_length() > 0);
CHECK(ribbon->get_section_segments() >= 0);
CHECK(ribbon->get_builtin_bind_pose_count() >= 0);
- CHECK(ribbon->get_curve() == nullptr);
+ CHECK(ribbon->get_curve().is_null());
CHECK((ribbon->get_shape() == RibbonTrailMesh::SHAPE_CROSS ||
ribbon->get_shape() == RibbonTrailMesh::SHAPE_FLAT));
}
@@ -731,7 +731,7 @@ TEST_CASE("[SceneTree][Primitive][Text] Text Primitive") {
text->get_vertical_alignment() == VERTICAL_ALIGNMENT_TOP ||
text->get_vertical_alignment() == VERTICAL_ALIGNMENT_CENTER ||
text->get_vertical_alignment() == VERTICAL_ALIGNMENT_FILL));
- CHECK(text->get_font() == nullptr);
+ CHECK(text->get_font().is_null());
CHECK(text->get_font_size() > 0);
CHECK(text->get_line_spacing() >= 0);
CHECK((text->get_autowrap_mode() == TextServer::AUTOWRAP_OFF ||
diff --git a/tests/scene/test_style_box_texture.h b/tests/scene/test_style_box_texture.h
new file mode 100644
index 0000000000..cc5be4b2d4
--- /dev/null
+++ b/tests/scene/test_style_box_texture.h
@@ -0,0 +1,194 @@
+/**************************************************************************/
+/* test_style_box_texture.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_STYLE_BOX_TEXTURE_H
+#define TEST_STYLE_BOX_TEXTURE_H
+
+#include "scene/resources/style_box_texture.h"
+
+#include "tests/test_macros.h"
+
+namespace TestStyleBoxTexture {
+
+TEST_CASE("[StyleBoxTexture] Constructor") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ CHECK(style_box_texture->get_h_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ CHECK(style_box_texture->get_v_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ CHECK(style_box_texture->is_draw_center_enabled() == true);
+
+ CHECK(style_box_texture->get_expand_margin(SIDE_LEFT) == 0);
+ CHECK(style_box_texture->get_expand_margin(SIDE_TOP) == 0);
+ CHECK(style_box_texture->get_expand_margin(SIDE_RIGHT) == 0);
+ CHECK(style_box_texture->get_expand_margin(SIDE_BOTTOM) == 0);
+
+ CHECK(style_box_texture->get_modulate() == Color(1, 1, 1, 1));
+ CHECK(style_box_texture->get_region_rect() == Rect2(0, 0, 0, 0));
+ CHECK(style_box_texture->get_texture() == Ref<Texture2D>());
+
+ CHECK(style_box_texture->get_texture_margin(SIDE_LEFT) == 0);
+ CHECK(style_box_texture->get_texture_margin(SIDE_TOP) == 0);
+ CHECK(style_box_texture->get_texture_margin(SIDE_RIGHT) == 0);
+ CHECK(style_box_texture->get_texture_margin(SIDE_BOTTOM) == 0);
+}
+
+TEST_CASE("[StyleBoxTexture] set_texture, get_texture") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+ Ref<Texture2D> texture = memnew(Texture2D);
+
+ style_box_texture->set_texture(texture);
+ CHECK(style_box_texture->get_texture() == texture);
+}
+
+TEST_CASE("[StyleBoxTexture] set_texture_margin, set_texture_margin_all, set_texture_margin_individual, get_texture_margin") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ SUBCASE("set_texture_margin, get_texture_margin") {
+ style_box_texture->set_texture_margin(SIDE_LEFT, 1);
+ style_box_texture->set_texture_margin(SIDE_TOP, 1);
+ style_box_texture->set_texture_margin(SIDE_RIGHT, 1);
+ style_box_texture->set_texture_margin(SIDE_BOTTOM, 1);
+
+ CHECK(style_box_texture->get_texture_margin(SIDE_LEFT) == 1);
+ CHECK(style_box_texture->get_texture_margin(SIDE_TOP) == 1);
+ CHECK(style_box_texture->get_texture_margin(SIDE_RIGHT) == 1);
+ CHECK(style_box_texture->get_texture_margin(SIDE_BOTTOM) == 1);
+ }
+
+ SUBCASE("set_texture_margin_all") {
+ style_box_texture->set_texture_margin_all(2);
+
+ CHECK(style_box_texture->get_texture_margin(SIDE_LEFT) == 2);
+ CHECK(style_box_texture->get_texture_margin(SIDE_TOP) == 2);
+ CHECK(style_box_texture->get_texture_margin(SIDE_RIGHT) == 2);
+ CHECK(style_box_texture->get_texture_margin(SIDE_BOTTOM) == 2);
+ }
+
+ SUBCASE("set_texture_margin_individual") {
+ style_box_texture->set_texture_margin_individual(3, 4, 5, 6);
+
+ CHECK(style_box_texture->get_texture_margin(SIDE_LEFT) == 3);
+ CHECK(style_box_texture->get_texture_margin(SIDE_TOP) == 4);
+ CHECK(style_box_texture->get_texture_margin(SIDE_RIGHT) == 5);
+ CHECK(style_box_texture->get_texture_margin(SIDE_BOTTOM) == 6);
+ }
+}
+
+TEST_CASE("[StyleBoxTexture] set_expand_margin, set_expand_margin_all, set_expand_margin_individual") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ SUBCASE("set_expand_margin, get_expand_margin") {
+ style_box_texture->set_expand_margin(SIDE_LEFT, 1);
+ style_box_texture->set_expand_margin(SIDE_TOP, 1);
+ style_box_texture->set_expand_margin(SIDE_RIGHT, 1);
+ style_box_texture->set_expand_margin(SIDE_BOTTOM, 1);
+
+ CHECK(style_box_texture->get_expand_margin(SIDE_LEFT) == 1);
+ CHECK(style_box_texture->get_expand_margin(SIDE_TOP) == 1);
+ CHECK(style_box_texture->get_expand_margin(SIDE_RIGHT) == 1);
+ CHECK(style_box_texture->get_expand_margin(SIDE_BOTTOM) == 1);
+ }
+
+ SUBCASE("set_expand_margin_all") {
+ style_box_texture->set_expand_margin_all(2);
+
+ CHECK(style_box_texture->get_expand_margin(SIDE_LEFT) == 2);
+ CHECK(style_box_texture->get_expand_margin(SIDE_TOP) == 2);
+ CHECK(style_box_texture->get_expand_margin(SIDE_RIGHT) == 2);
+ CHECK(style_box_texture->get_expand_margin(SIDE_BOTTOM) == 2);
+ }
+
+ SUBCASE("set_expand_margin_individual") {
+ style_box_texture->set_expand_margin_individual(3, 4, 5, 6);
+
+ CHECK(style_box_texture->get_expand_margin(SIDE_LEFT) == 3);
+ CHECK(style_box_texture->get_expand_margin(SIDE_TOP) == 4);
+ CHECK(style_box_texture->get_expand_margin(SIDE_RIGHT) == 5);
+ CHECK(style_box_texture->get_expand_margin(SIDE_BOTTOM) == 6);
+ }
+}
+
+TEST_CASE("[StyleBoxTexture] set_region_rect, get_region_rect") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ style_box_texture->set_region_rect(Rect2(1, 1, 1, 1));
+ CHECK(style_box_texture->get_region_rect() == Rect2(1, 1, 1, 1));
+}
+
+TEST_CASE("[StyleBoxTexture] set_draw_center, get_draw_center") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ style_box_texture->set_draw_center(false);
+ CHECK(style_box_texture->is_draw_center_enabled() == false);
+}
+
+TEST_CASE("[StyleBoxTexture] set_h_axis_stretch_mode, set_v_axis_stretch_mode, get_h_axis_stretch_mode, get_v_axis_stretch_mode") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ SUBCASE("set_h_axis_stretch_mode, get_h_axis_stretch_mode") {
+ style_box_texture->set_h_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_TILE);
+ CHECK(style_box_texture->get_h_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_TILE);
+
+ style_box_texture->set_h_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_TILE_FIT);
+ CHECK(style_box_texture->get_h_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_TILE_FIT);
+
+ style_box_texture->set_h_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ CHECK(style_box_texture->get_h_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ }
+
+ SUBCASE("set_v_axis_stretch_mode, get_v_axis_stretch_mode") {
+ style_box_texture->set_v_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_TILE);
+ CHECK(style_box_texture->get_v_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_TILE);
+
+ style_box_texture->set_v_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_TILE_FIT);
+ CHECK(style_box_texture->get_v_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_TILE_FIT);
+
+ style_box_texture->set_v_axis_stretch_mode(style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ CHECK(style_box_texture->get_v_axis_stretch_mode() == style_box_texture->AXIS_STRETCH_MODE_STRETCH);
+ }
+}
+
+TEST_CASE("[StyleBoxTexture] set_modulate, get_modulate") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ style_box_texture->set_modulate(Color(0, 0, 0, 0));
+ CHECK(style_box_texture->get_modulate() == Color(0, 0, 0, 0));
+}
+
+TEST_CASE("[StyleBoxTexture] get_draw_rect") {
+ Ref<StyleBoxTexture> style_box_texture = memnew(StyleBoxTexture);
+
+ style_box_texture->set_expand_margin_all(5);
+ CHECK(style_box_texture->get_draw_rect(Rect2(0, 0, 1, 1)) == Rect2(-5, -5, 11, 11));
+}
+
+} // namespace TestStyleBoxTexture
+
+#endif // TEST_STYLE_BOX_TEXTURE_H
diff --git a/tests/scene/test_tree.h b/tests/scene/test_tree.h
new file mode 100644
index 0000000000..e19f8311e2
--- /dev/null
+++ b/tests/scene/test_tree.h
@@ -0,0 +1,175 @@
+/**************************************************************************/
+/* test_tree.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_TREE_H
+#define TEST_TREE_H
+
+#include "scene/gui/tree.h"
+
+#include "tests/test_macros.h"
+
+namespace TestTree {
+
+TEST_CASE("[SceneTree][Tree]") {
+ SUBCASE("[Tree] Create and remove items.") {
+ Tree *tree = memnew(Tree);
+ TreeItem *root = tree->create_item();
+
+ TreeItem *child1 = tree->create_item();
+ CHECK_EQ(root->get_child_count(), 1);
+
+ TreeItem *child2 = tree->create_item(root);
+ CHECK_EQ(root->get_child_count(), 2);
+
+ TreeItem *child3 = tree->create_item(root, 0);
+ CHECK_EQ(root->get_child_count(), 3);
+
+ CHECK_EQ(root->get_child(0), child3);
+ CHECK_EQ(root->get_child(1), child1);
+ CHECK_EQ(root->get_child(2), child2);
+
+ root->remove_child(child3);
+ CHECK_EQ(root->get_child_count(), 2);
+
+ root->add_child(child3);
+ CHECK_EQ(root->get_child_count(), 3);
+
+ TreeItem *child4 = root->create_child();
+ CHECK_EQ(root->get_child_count(), 4);
+
+ CHECK_EQ(root->get_child(0), child1);
+ CHECK_EQ(root->get_child(1), child2);
+ CHECK_EQ(root->get_child(2), child3);
+ CHECK_EQ(root->get_child(3), child4);
+
+ memdelete(tree);
+ }
+
+ SUBCASE("[Tree] Clear items.") {
+ Tree *tree = memnew(Tree);
+ TreeItem *root = tree->create_item();
+
+ for (int i = 0; i < 10; i++) {
+ tree->create_item();
+ }
+ CHECK_EQ(root->get_child_count(), 10);
+
+ root->clear_children();
+ CHECK_EQ(root->get_child_count(), 0);
+
+ memdelete(tree);
+ }
+
+ SUBCASE("[Tree] Get last item.") {
+ Tree *tree = memnew(Tree);
+ TreeItem *root = tree->create_item();
+
+ TreeItem *last;
+ for (int i = 0; i < 10; i++) {
+ last = tree->create_item();
+ }
+ CHECK_EQ(root->get_child_count(), 10);
+ CHECK_EQ(tree->get_last_item(), last);
+
+ // Check nested.
+ TreeItem *old_last = last;
+ for (int i = 0; i < 10; i++) {
+ last = tree->create_item(old_last);
+ }
+ CHECK_EQ(tree->get_last_item(), last);
+
+ memdelete(tree);
+ }
+
+ // https://github.com/godotengine/godot/issues/96205
+ SUBCASE("[Tree] Get last item after removal.") {
+ Tree *tree = memnew(Tree);
+ TreeItem *root = tree->create_item();
+
+ TreeItem *child1 = tree->create_item(root);
+ TreeItem *child2 = tree->create_item(root);
+
+ CHECK_EQ(root->get_child_count(), 2);
+ CHECK_EQ(tree->get_last_item(), child2);
+
+ root->remove_child(child2);
+
+ CHECK_EQ(root->get_child_count(), 1);
+ CHECK_EQ(tree->get_last_item(), child1);
+
+ root->add_child(child2);
+
+ CHECK_EQ(root->get_child_count(), 2);
+ CHECK_EQ(tree->get_last_item(), child2);
+
+ memdelete(tree);
+ }
+
+ SUBCASE("[Tree] Previous and Next items.") {
+ Tree *tree = memnew(Tree);
+ TreeItem *root = tree->create_item();
+
+ TreeItem *child1 = tree->create_item();
+ TreeItem *child2 = tree->create_item();
+ TreeItem *child3 = tree->create_item();
+ CHECK_EQ(child1->get_next(), child2);
+ CHECK_EQ(child1->get_next_in_tree(), child2);
+ CHECK_EQ(child2->get_next(), child3);
+ CHECK_EQ(child2->get_next_in_tree(), child3);
+ CHECK_EQ(child3->get_next(), nullptr);
+ CHECK_EQ(child3->get_next_in_tree(), nullptr);
+
+ CHECK_EQ(child1->get_prev(), nullptr);
+ CHECK_EQ(child1->get_prev_in_tree(), root);
+ CHECK_EQ(child2->get_prev(), child1);
+ CHECK_EQ(child2->get_prev_in_tree(), child1);
+ CHECK_EQ(child3->get_prev(), child2);
+ CHECK_EQ(child3->get_prev_in_tree(), child2);
+
+ TreeItem *nested1 = tree->create_item(child2);
+ TreeItem *nested2 = tree->create_item(child2);
+ TreeItem *nested3 = tree->create_item(child2);
+
+ CHECK_EQ(child1->get_next(), child2);
+ CHECK_EQ(child1->get_next_in_tree(), child2);
+ CHECK_EQ(child2->get_next(), child3);
+ CHECK_EQ(child2->get_next_in_tree(), nested1);
+ CHECK_EQ(child3->get_prev(), child2);
+ CHECK_EQ(child3->get_prev_in_tree(), nested3);
+ CHECK_EQ(nested1->get_prev_in_tree(), child2);
+ CHECK_EQ(nested1->get_next_in_tree(), nested2);
+
+ memdelete(tree);
+ }
+}
+
+} // namespace TestTree
+
+#endif // TEST_TREE_H
diff --git a/tests/servers/test_navigation_server_3d.h b/tests/servers/test_navigation_server_3d.h
index cf6b89c330..4411b1aae5 100644
--- a/tests/servers/test_navigation_server_3d.h
+++ b/tests/servers/test_navigation_server_3d.h
@@ -31,6 +31,7 @@
#ifndef TEST_NAVIGATION_SERVER_3D_H
#define TEST_NAVIGATION_SERVER_3D_H
+#include "modules/navigation/nav_utils.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/3d/primitive_meshes.h"
#include "servers/navigation_server_3d.h"
@@ -61,6 +62,32 @@ static inline Array build_array(Variant item, Targs... Fargs) {
return a;
}
+struct GreaterThan {
+ bool operator()(int p_a, int p_b) const { return p_a > p_b; }
+};
+
+struct CompareArrayValues {
+ const int *array;
+
+ CompareArrayValues(const int *p_array) :
+ array(p_array) {}
+
+ bool operator()(uint32_t p_index_a, uint32_t p_index_b) const {
+ return array[p_index_a] < array[p_index_b];
+ }
+};
+
+struct RegisterHeapIndexes {
+ uint32_t *indexes;
+
+ RegisterHeapIndexes(uint32_t *p_indexes) :
+ indexes(p_indexes) {}
+
+ void operator()(uint32_t p_vector_index, uint32_t p_heap_index) {
+ indexes[p_vector_index] = p_heap_index;
+ }
+};
+
TEST_SUITE("[Navigation]") {
TEST_CASE("[NavigationServer3D] Server should be empty when initialized") {
NavigationServer3D *navigation_server = NavigationServer3D::get_singleton();
@@ -788,6 +815,139 @@ TEST_SUITE("[Navigation]") {
CHECK_EQ(navigation_mesh->get_vertices().size(), 0);
}
*/
+
+ TEST_CASE("[Heap] size") {
+ gd::Heap<int> heap;
+
+ CHECK(heap.size() == 0);
+
+ heap.push(0);
+ CHECK(heap.size() == 1);
+
+ heap.push(1);
+ CHECK(heap.size() == 2);
+
+ heap.pop();
+ CHECK(heap.size() == 1);
+
+ heap.pop();
+ CHECK(heap.size() == 0);
+ }
+
+ TEST_CASE("[Heap] is_empty") {
+ gd::Heap<int> heap;
+
+ CHECK(heap.is_empty() == true);
+
+ heap.push(0);
+ CHECK(heap.is_empty() == false);
+
+ heap.pop();
+ CHECK(heap.is_empty() == true);
+ }
+
+ TEST_CASE("[Heap] push/pop") {
+ SUBCASE("Default comparator") {
+ gd::Heap<int> heap;
+
+ heap.push(2);
+ heap.push(7);
+ heap.push(5);
+ heap.push(3);
+ heap.push(4);
+
+ CHECK(heap.pop() == 7);
+ CHECK(heap.pop() == 5);
+ CHECK(heap.pop() == 4);
+ CHECK(heap.pop() == 3);
+ CHECK(heap.pop() == 2);
+ }
+
+ SUBCASE("Custom comparator") {
+ GreaterThan greaterThan;
+ gd::Heap<int, GreaterThan> heap(greaterThan);
+
+ heap.push(2);
+ heap.push(7);
+ heap.push(5);
+ heap.push(3);
+ heap.push(4);
+
+ CHECK(heap.pop() == 2);
+ CHECK(heap.pop() == 3);
+ CHECK(heap.pop() == 4);
+ CHECK(heap.pop() == 5);
+ CHECK(heap.pop() == 7);
+ }
+
+ SUBCASE("Intermediate pops") {
+ gd::Heap<int> heap;
+
+ heap.push(0);
+ heap.push(3);
+ heap.pop();
+ heap.push(1);
+ heap.push(2);
+
+ CHECK(heap.pop() == 2);
+ CHECK(heap.pop() == 1);
+ CHECK(heap.pop() == 0);
+ }
+ }
+
+ TEST_CASE("[Heap] shift") {
+ int values[] = { 5, 3, 6, 7, 1 };
+ uint32_t heap_indexes[] = { 0, 0, 0, 0, 0 };
+ CompareArrayValues comparator(values);
+ RegisterHeapIndexes indexer(heap_indexes);
+ gd::Heap<uint32_t, CompareArrayValues, RegisterHeapIndexes> heap(comparator, indexer);
+
+ heap.push(0);
+ heap.push(1);
+ heap.push(2);
+ heap.push(3);
+ heap.push(4);
+
+ // Shift down: 6 -> 2
+ values[2] = 2;
+ heap.shift(heap_indexes[2]);
+
+ // Shift up: 5 -> 8
+ values[0] = 8;
+ heap.shift(heap_indexes[0]);
+
+ CHECK(heap.pop() == 0);
+ CHECK(heap.pop() == 3);
+ CHECK(heap.pop() == 1);
+ CHECK(heap.pop() == 2);
+ CHECK(heap.pop() == 4);
+
+ CHECK(heap_indexes[0] == UINT32_MAX);
+ CHECK(heap_indexes[1] == UINT32_MAX);
+ CHECK(heap_indexes[2] == UINT32_MAX);
+ CHECK(heap_indexes[3] == UINT32_MAX);
+ CHECK(heap_indexes[4] == UINT32_MAX);
+ }
+
+ TEST_CASE("[Heap] clear") {
+ uint32_t heap_indexes[] = { 0, 0, 0, 0 };
+ RegisterHeapIndexes indexer(heap_indexes);
+ gd::Heap<uint32_t, Comparator<uint32_t>, RegisterHeapIndexes> heap(indexer);
+
+ heap.push(0);
+ heap.push(2);
+ heap.push(1);
+ heap.push(3);
+
+ heap.clear();
+
+ CHECK(heap.size() == 0);
+
+ CHECK(heap_indexes[0] == UINT32_MAX);
+ CHECK(heap_indexes[1] == UINT32_MAX);
+ CHECK(heap_indexes[2] == UINT32_MAX);
+ CHECK(heap_indexes[3] == UINT32_MAX);
+ }
}
} //namespace TestNavigationServer3D
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index edadc52a16..7e1c431a3c 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -48,6 +48,7 @@
#include "tests/core/io/test_image.h"
#include "tests/core/io/test_ip.h"
#include "tests/core/io/test_json.h"
+#include "tests/core/io/test_json_native.h"
#include "tests/core/io/test_marshalls.h"
#include "tests/core/io/test_pck_packer.h"
#include "tests/core/io/test_resource.h"
@@ -104,12 +105,14 @@
#include "tests/scene/test_animation.h"
#include "tests/scene/test_audio_stream_wav.h"
#include "tests/scene/test_bit_map.h"
+#include "tests/scene/test_button.h"
#include "tests/scene/test_camera_2d.h"
#include "tests/scene/test_control.h"
#include "tests/scene/test_curve.h"
#include "tests/scene/test_curve_2d.h"
#include "tests/scene/test_curve_3d.h"
#include "tests/scene/test_gradient.h"
+#include "tests/scene/test_gradient_texture.h"
#include "tests/scene/test_image_texture.h"
#include "tests/scene/test_image_texture_3d.h"
#include "tests/scene/test_instance_placeholder.h"
@@ -119,6 +122,7 @@
#include "tests/scene/test_path_2d.h"
#include "tests/scene/test_path_follow_2d.h"
#include "tests/scene/test_sprite_frames.h"
+#include "tests/scene/test_style_box_texture.h"
#include "tests/scene/test_theme.h"
#include "tests/scene/test_timer.h"
#include "tests/scene/test_viewport.h"
@@ -132,7 +136,9 @@
#include "tests/scene/test_code_edit.h"
#include "tests/scene/test_color_picker.h"
#include "tests/scene/test_graph_node.h"
+#include "tests/scene/test_option_button.h"
#include "tests/scene/test_text_edit.h"
+#include "tests/scene/test_tree.h"
#endif // ADVANCED_GUI_DISABLED
#ifndef _3D_DISABLED