diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/SCsub | 5 | ||||
-rw-r--r-- | tests/core/io/test_config_file.h (renamed from tests/test_config_file.h) | 5 | ||||
-rw-r--r-- | tests/core/io/test_file_access.h (renamed from tests/test_file_access.h) | 9 | ||||
-rw-r--r-- | tests/core/io/test_image.h (renamed from tests/test_image.h) | 58 | ||||
-rw-r--r-- | tests/core/io/test_json.h (renamed from tests/test_json.h) | 4 | ||||
-rw-r--r-- | tests/core/io/test_marshalls.h (renamed from tests/test_marshalls.h) | 4 | ||||
-rw-r--r-- | tests/core/io/test_pck_packer.h (renamed from tests/test_pck_packer.h) | 34 | ||||
-rw-r--r-- | tests/core/io/test_resource.h (renamed from tests/test_resource.h) | 4 | ||||
-rw-r--r-- | tests/core/io/test_xml_parser.h (renamed from tests/test_xml_parser.h) | 7 | ||||
-rw-r--r-- | tests/core/math/test_aabb.h (renamed from tests/test_aabb.h) | 29 | ||||
-rw-r--r-- | tests/core/math/test_astar.h (renamed from tests/test_astar.h) | 9 | ||||
-rw-r--r-- | tests/core/math/test_basis.h (renamed from tests/test_basis.h) | 7 | ||||
-rw-r--r-- | tests/core/math/test_color.h (renamed from tests/test_color.h) | 6 | ||||
-rw-r--r-- | tests/core/math/test_expression.h (renamed from tests/test_expression.h) | 6 | ||||
-rw-r--r-- | tests/core/math/test_geometry_2d.h (renamed from tests/test_geometry_2d.h) | 5 | ||||
-rw-r--r-- | tests/core/math/test_geometry_3d.h (renamed from tests/test_geometry_3d.h) | 8 | ||||
-rw-r--r-- | tests/core/math/test_math.cpp (renamed from tests/test_math.cpp) | 28 | ||||
-rw-r--r-- | tests/core/math/test_math.h (renamed from tests/test_math.h) | 6 | ||||
-rw-r--r-- | tests/core/math/test_random_number_generator.h (renamed from tests/test_random_number_generator.h) | 4 | ||||
-rw-r--r-- | tests/core/math/test_rect2.h (renamed from tests/test_rect2.h) | 294 | ||||
-rw-r--r-- | tests/core/math/test_rect2i.h | 311 | ||||
-rw-r--r-- | tests/core/math/test_vector2.h | 386 | ||||
-rw-r--r-- | tests/core/math/test_vector2i.h | 145 | ||||
-rw-r--r-- | tests/core/math/test_vector3.h | 414 | ||||
-rw-r--r-- | tests/core/math/test_vector3i.h | 145 | ||||
-rw-r--r-- | tests/core/object/test_class_db.h (renamed from tests/test_class_db.h) | 13 | ||||
-rw-r--r-- | tests/core/object/test_method_bind.h (renamed from tests/test_method_bind.h) | 24 | ||||
-rw-r--r-- | tests/core/object/test_object.h (renamed from tests/test_object.h) | 8 | ||||
-rw-r--r-- | tests/core/string/test_node_path.h (renamed from tests/test_node_path.h) | 6 | ||||
-rw-r--r-- | tests/core/string/test_string.h (renamed from tests/test_string.h) | 89 | ||||
-rw-r--r-- | tests/core/string/test_translation.h (renamed from tests/test_translation.h) | 7 | ||||
-rw-r--r-- | tests/core/templates/test_command_queue.h (renamed from tests/test_command_queue.h) | 8 | ||||
-rw-r--r-- | tests/core/templates/test_list.h (renamed from tests/test_list.h) | 4 | ||||
-rw-r--r-- | tests/core/templates/test_local_vector.h (renamed from tests/test_local_vector.h) | 39 | ||||
-rw-r--r-- | tests/core/templates/test_lru.h (renamed from tests/test_lru.h) | 5 | ||||
-rw-r--r-- | tests/core/templates/test_oa_hash_map.cpp (renamed from tests/test_oa_hash_map.cpp) | 9 | ||||
-rw-r--r-- | tests/core/templates/test_oa_hash_map.h (renamed from tests/test_oa_hash_map.h) | 6 | ||||
-rw-r--r-- | tests/core/templates/test_ordered_hash_map.h (renamed from tests/test_ordered_hash_map.h) | 7 | ||||
-rw-r--r-- | tests/core/templates/test_paged_array.h (renamed from tests/test_paged_array.h) | 4 | ||||
-rw-r--r-- | tests/core/templates/test_vector.h (renamed from tests/test_vector.h) | 108 | ||||
-rw-r--r-- | tests/core/test_crypto.h (renamed from tests/test_crypto.h) | 5 | ||||
-rw-r--r-- | tests/core/test_hashing_context.h (renamed from tests/test_hashing_context.h) | 4 | ||||
-rw-r--r-- | tests/core/test_time.h (renamed from tests/test_time.h) | 4 | ||||
-rw-r--r-- | tests/core/variant/test_array.h (renamed from tests/test_array.h) | 76 | ||||
-rw-r--r-- | tests/core/variant/test_dictionary.h (renamed from tests/test_dictionary.h) | 9 | ||||
-rw-r--r-- | tests/core/variant/test_variant.h (renamed from tests/test_variant.h) | 4 | ||||
-rw-r--r-- | tests/scene/test_animation.h | 314 | ||||
-rw-r--r-- | tests/scene/test_code_edit.h (renamed from tests/test_code_edit.h) | 252 | ||||
-rw-r--r-- | tests/scene/test_curve.h (renamed from tests/test_curve.h) | 32 | ||||
-rw-r--r-- | tests/scene/test_gradient.h (renamed from tests/test_gradient.h) | 6 | ||||
-rw-r--r-- | tests/scene/test_gui.cpp (renamed from tests/test_gui.cpp) | 19 | ||||
-rw-r--r-- | tests/scene/test_gui.h (renamed from tests/test_gui.h) | 6 | ||||
-rw-r--r-- | tests/scene/test_path_3d.h (renamed from tests/test_path_3d.h) | 5 | ||||
-rw-r--r-- | tests/scene/test_path_follow_2d.h (renamed from tests/test_path_follow_2d.h) | 5 | ||||
-rw-r--r-- | tests/scene/test_path_follow_3d.h (renamed from tests/test_path_follow_3d.h) | 5 | ||||
-rw-r--r-- | tests/servers/test_physics_2d.cpp (renamed from tests/test_physics_2d.cpp) | 17 | ||||
-rw-r--r-- | tests/servers/test_physics_2d.h (renamed from tests/test_physics_2d.h) | 6 | ||||
-rw-r--r-- | tests/servers/test_physics_3d.cpp (renamed from tests/test_physics_3d.cpp) | 14 | ||||
-rw-r--r-- | tests/servers/test_physics_3d.h (renamed from tests/test_physics_3d.h) | 6 | ||||
-rw-r--r-- | tests/servers/test_render.cpp (renamed from tests/test_render.cpp) | 9 | ||||
-rw-r--r-- | tests/servers/test_render.h (renamed from tests/test_render.h) | 8 | ||||
-rw-r--r-- | tests/servers/test_shader_lang.cpp (renamed from tests/test_shader_lang.cpp) | 25 | ||||
-rw-r--r-- | tests/servers/test_shader_lang.h (renamed from tests/test_shader_lang.h) | 6 | ||||
-rw-r--r-- | tests/servers/test_text_server.h (renamed from tests/test_text_server.h) | 210 | ||||
-rw-r--r-- | tests/test_macros.cpp | 4 | ||||
-rw-r--r-- | tests/test_macros.h | 18 | ||||
-rw-r--r-- | tests/test_main.cpp | 114 | ||||
-rw-r--r-- | tests/test_main.h | 4 | ||||
-rw-r--r-- | tests/test_tools.h | 6 | ||||
-rw-r--r-- | tests/test_utils.cpp | 6 | ||||
-rw-r--r-- | tests/test_utils.h | 6 | ||||
-rw-r--r-- | tests/test_validate_testing.h | 4 |
72 files changed, 2765 insertions, 714 deletions
diff --git a/tests/SCsub b/tests/SCsub index 0f3c14f0bd..31466fffc1 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -22,6 +22,11 @@ if env_tests["platform"] == "windows": if env_tests.msvc: env_tests.Append(CCFLAGS=["/bigobj"]) +env_tests.add_source_files(env.tests_sources, "core/*.cpp") +env_tests.add_source_files(env.tests_sources, "core/math/*.cpp") +env_tests.add_source_files(env.tests_sources, "core/templates/*.cpp") +env_tests.add_source_files(env.tests_sources, "scene/*.cpp") +env_tests.add_source_files(env.tests_sources, "servers/*.cpp") env_tests.add_source_files(env.tests_sources, "*.cpp") lib = env_tests.add_library("tests", env.tests_sources) diff --git a/tests/test_config_file.h b/tests/core/io/test_config_file.h index e3f40e16fd..6e393c7a2d 100644 --- a/tests/test_config_file.h +++ b/tests/core/io/test_config_file.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,7 @@ #define TEST_CONFIG_FILE_H #include "core/io/config_file.h" +#include "core/os/os.h" #include "tests/test_macros.h" diff --git a/tests/test_file_access.h b/tests/core/io/test_file_access.h index b3da16c1d1..eee57048cf 100644 --- a/tests/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,8 @@ #define TEST_FILE_ACCESS_H #include "core/io/file_access.h" -#include "test_utils.h" +#include "tests/test_macros.h" +#include "tests/test_utils.h" namespace TestFileAccess { @@ -52,7 +53,7 @@ TEST_CASE("[FileAccess] CSV read") { REQUIRE(row2.size() == 3); CHECK(row2[0] == "GOOD_EVENING"); CHECK(row2[1] == "Good Evening"); - CHECK(row2[2] == ""); // Use case: not yet translated! + CHECK(row2[2].is_empty()); // Use case: not yet translated! // https://github.com/godotengine/godot/issues/44269 CHECK_MESSAGE(row2[2] != "\"", "Should not parse empty string as a single double quote."); diff --git a/tests/test_image.h b/tests/core/io/test_image.h index 99c2a9380d..dcf21dd7b0 100644 --- a/tests/test_image.h +++ b/tests/core/io/test_image.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #ifndef TEST_IMAGE_H #define TEST_IMAGE_H -#include "core/io/file_access_pack.h" #include "core/io/image.h" -#include "test_utils.h" +#include "core/os/os.h" +#include "tests/test_utils.h" #include "thirdparty/doctest/doctest.h" namespace TestImage { @@ -52,6 +52,13 @@ TEST_CASE("[Image] Instantiation") { "A newly created image should not be compressed."); CHECK(!image->has_mipmaps()); + PackedByteArray image_data = image->get_data(); + for (int i = 0; i < image_data.size(); i++) { + CHECK_MESSAGE( + image_data[i] == 0, + "An image created without data specified should have its data zeroed out."); + } + Ref<Image> image_copy = memnew(Image()); CHECK_MESSAGE( image_copy->is_empty(), @@ -62,7 +69,7 @@ TEST_CASE("[Image] Instantiation") { image->get_data() == image_copy->get_data(), "Duplicated images should have the same data."); - PackedByteArray image_data = image->get_data(); + image_data = image->get_data(); Ref<Image> image_from_data = memnew(Image(8, 4, false, Image::FORMAT_RGBA8, image_data)); CHECK_MESSAGE( image->get_data() == image_from_data->get_data(), @@ -214,14 +221,51 @@ TEST_CASE("[Image] Modifying pixels of an image") { // Fill image with color image2->fill(Color(0.5, 0.5, 0.5, 0.5)); - for (int x = 0; x < image2->get_width(); x++) { - for (int y = 0; y < image2->get_height(); y++) { + for (int y = 0; y < image2->get_height(); y++) { + for (int x = 0; x < image2->get_width(); x++) { CHECK_MESSAGE( image2->get_pixel(x, y).r > 0.49, "fill() should colorize all pixels of the image."); } } + // Fill rect with color + { + const int img_width = 3; + const int img_height = 3; + Vector<Rect2> rects; + rects.push_back(Rect2()); + rects.push_back(Rect2(-5, -5, 3, 3)); + rects.push_back(Rect2(img_width, 0, 12, 12)); + rects.push_back(Rect2(0, img_height, 12, 12)); + rects.push_back(Rect2(img_width + 1, img_height + 2, 12, 12)); + rects.push_back(Rect2(1, 1, 1, 1)); + rects.push_back(Rect2(0, 1, 2, 3)); + rects.push_back(Rect2(-5, 0, img_width + 10, 2)); + rects.push_back(Rect2(0, -5, 2, img_height + 10)); + rects.push_back(Rect2(-1, -1, img_width + 1, img_height + 1)); + + for (const Rect2 &rect : rects) { + Ref<Image> img = memnew(Image(img_width, img_height, false, Image::FORMAT_RGBA8)); + CHECK_NOTHROW_MESSAGE( + img->fill_rect(rect, Color(1, 1, 1, 1)), + "fill_rect() shouldn't throw for any rect."); + for (int y = 0; y < img->get_height(); y++) { + for (int x = 0; x < img->get_width(); x++) { + if (rect.abs().has_point(Point2(x, y))) { + CHECK_MESSAGE( + img->get_pixel(x, y).is_equal_approx(Color(1, 1, 1, 1)), + "fill_rect() should colorize all image pixels within rect bounds."); + } else { + CHECK_MESSAGE( + !img->get_pixel(x, y).is_equal_approx(Color(1, 1, 1, 1)), + "fill_rect() shouldn't colorize any image pixel out of rect bounds."); + } + } + } + } + } + // Blend two images together image->blend_rect(image2, Rect2(Vector2(0, 0), image2->get_size()), Vector2(0, 0)); CHECK_MESSAGE( diff --git a/tests/test_json.h b/tests/core/io/test_json.h index 3af58dfa1c..478cf1766e 100644 --- a/tests/test_json.h +++ b/tests/core/io/test_json.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_marshalls.h b/tests/core/io/test_marshalls.h index 6bd916164e..546a2e9358 100644 --- a/tests/test_marshalls.h +++ b/tests/core/io/test_marshalls.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_pck_packer.h b/tests/core/io/test_pck_packer.h index 06e4e64963..95adca6d68 100644 --- a/tests/test_pck_packer.h +++ b/tests/core/io/test_pck_packer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,21 +35,16 @@ #include "core/io/pck_packer.h" #include "core/os/os.h" +#include "tests/test_utils.h" #include "thirdparty/doctest/doctest.h" namespace TestPCKPacker { -// Dummy 64-character encryption key (since it's required). -constexpr const char *ENCRYPTION_KEY = "0000000000000000000000000000000000000000000000000000000000000000"; - TEST_CASE("[PCKPacker] Pack an empty PCK file") { PCKPacker pck_packer; const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); CHECK_MESSAGE( - pck_packer.pck_start( - output_pck_path, - 32, - ENCRYPTION_KEY) == OK, + pck_packer.pck_start(output_pck_path) == OK, "Starting a PCK file should return an OK error code."); CHECK_MESSAGE( @@ -69,14 +64,27 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") { "The generated empty PCK file shouldn't be too large."); } +TEST_CASE("[PCKPacker] Pack empty with zero alignment invalid") { + PCKPacker pck_packer; + const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); + ERR_PRINT_OFF; + CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 0) != OK, "PCK with zero alignment should fail."); + ERR_PRINT_ON; +} + +TEST_CASE("[PCKPacker] Pack empty with invalid key") { + PCKPacker pck_packer; + const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); + ERR_PRINT_OFF; + CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 32, "") != OK, "PCK with invalid key should fail."); + ERR_PRINT_ON; +} + TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") { PCKPacker pck_packer; const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_with_files.pck"); CHECK_MESSAGE( - pck_packer.pck_start( - output_pck_path, - 32, - ENCRYPTION_KEY) == OK, + pck_packer.pck_start(output_pck_path) == OK, "Starting a PCK file should return an OK error code."); const String base_dir = OS::get_singleton()->get_executable_path().get_base_dir(); diff --git a/tests/test_resource.h b/tests/core/io/test_resource.h index cee3281995..b3983bb06d 100644 --- a/tests/test_resource.h +++ b/tests/core/io/test_resource.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_xml_parser.h b/tests/core/io/test_xml_parser.h index 55de048d6a..87592b56ce 100644 --- a/tests/test_xml_parser.h +++ b/tests/core/io/test_xml_parser.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,7 @@ #ifndef TEST_XML_PARSER_H #define TEST_XML_PARSER_H -#include <inttypes.h> - #include "core/io/xml_parser.h" -#include "core/string/ustring.h" #include "tests/test_macros.h" diff --git a/tests/test_aabb.h b/tests/core/math/test_aabb.h index 0312e185a1..526972a82f 100644 --- a/tests/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,10 +32,8 @@ #define TEST_AABB_H #include "core/math/aabb.h" -#include "core/string/print_string.h" -#include "tests/test_macros.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestAABB { @@ -351,14 +349,27 @@ TEST_CASE("[AABB] Has point") { aabb.has_point(Vector3(2, 3, 0)), "has_point() with contained point should return the expected value."); CHECK_MESSAGE( + !aabb.has_point(Vector3(-20, 0, 0)), + "has_point() with non-contained point should return the expected value."); + + CHECK_MESSAGE( aabb.has_point(Vector3(-1.5, 3, 0)), - "has_point() with contained point on negative edge should return the expected value."); + "has_point() with positive size should include point on near face (X axis)."); CHECK_MESSAGE( aabb.has_point(Vector3(2.5, 3, 0)), - "has_point() with contained point on positive edge should return the expected value."); + "has_point() with positive size should include point on far face (X axis)."); CHECK_MESSAGE( - !aabb.has_point(Vector3(-20, 0, 0)), - "has_point() with non-contained point should return the expected value."); + aabb.has_point(Vector3(0, 2, 0)), + "has_point() with positive size should include point on near face (Y axis)."); + CHECK_MESSAGE( + aabb.has_point(Vector3(0, 7, 0)), + "has_point() with positive size should include point on far face (Y axis)."); + CHECK_MESSAGE( + aabb.has_point(Vector3(0, 3, -2.5)), + "has_point() with positive size should include point on near face (Z axis)."); + CHECK_MESSAGE( + aabb.has_point(Vector3(0, 3, 3.5)), + "has_point() with positive size should include point on far face (Z axis)."); } TEST_CASE("[AABB] Expanding") { diff --git a/tests/test_astar.h b/tests/core/math/test_astar.h index 137c477946..859172dca3 100644 --- a/tests/test_astar.h +++ b/tests/core/math/test_astar.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,11 +32,6 @@ #define TEST_ASTAR_H #include "core/math/a_star.h" -#include "core/math/math_funcs.h" -#include "core/os/os.h" - -#include <math.h> -#include <stdio.h> #include "tests/test_macros.h" diff --git a/tests/test_basis.h b/tests/core/math/test_basis.h index b254d9fb7f..257e41e82c 100644 --- a/tests/test_basis.h +++ b/tests/core/math/test_basis.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,8 @@ #ifndef TEST_BASIS_H #define TEST_BASIS_H +#include "core/math/basis.h" #include "core/math/random_number_generator.h" -#include "core/os/os.h" -#include "core/string/ustring.h" #include "tests/test_macros.h" diff --git a/tests/test_color.h b/tests/core/math/test_color.h index bffa890ae2..e62ce6ec60 100644 --- a/tests/test_color.h +++ b/tests/core/math/test_color.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "core/math/color.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestColor { diff --git a/tests/test_expression.h b/tests/core/math/test_expression.h index cb1d29389f..6e3be541b0 100644 --- a/tests/test_expression.h +++ b/tests/core/math/test_expression.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -137,7 +137,7 @@ TEST_CASE("[Expression] Scientific notation") { expression.parse("2e5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 25), + Math::is_equal_approx(double(expression.execute()), 2e5), "The expression should return the expected result."); CHECK_MESSAGE( diff --git a/tests/test_geometry_2d.h b/tests/core/math/test_geometry_2d.h index 25af8c355e..3487e4d7e8 100644 --- a/tests/test_geometry_2d.h +++ b/tests/core/math/test_geometry_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #define TEST_GEOMETRY_2D_H #include "core/math/geometry_2d.h" -#include "core/templates/vector.h" #include "thirdparty/doctest/doctest.h" diff --git a/tests/test_geometry_3d.h b/tests/core/math/test_geometry_3d.h index ae30737fe2..1b8d2eee34 100644 --- a/tests/test_geometry_3d.h +++ b/tests/core/math/test_geometry_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,11 +32,7 @@ #define TEST_GEOMETRY_3D_H #include "core/math/geometry_3d.h" -#include "core/math/plane.h" -#include "core/math/random_number_generator.h" -#include "core/math/vector3.h" #include "tests/test_macros.h" -#include "vector" namespace TestGeometry3D { TEST_CASE("[Geometry3D] Closest Points Between Segments") { diff --git a/tests/test_math.cpp b/tests/core/math/test_math.cpp index 72272382ce..4182455b7a 100644 --- a/tests/test_math.cpp +++ b/tests/core/math/test_math.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,23 +30,11 @@ #include "test_math.h" -#include "core/io/file_access.h" -#include "core/math/basis.h" #include "core/math/camera_matrix.h" #include "core/math/delaunay_3d.h" #include "core/math/geometry_2d.h" -#include "core/math/math_funcs.h" -#include "core/math/transform_3d.h" -#include "core/os/keyboard.h" +#include "core/os/main_loop.h" #include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/string/ustring.h" -#include "core/templates/vmap.h" -#include "core/variant/method_ptrcall.h" -#include "core/variant/variant.h" -#include "scene/main/node.h" -#include "scene/resources/texture.h" -#include "servers/rendering/shader_language.h" namespace TestMath { @@ -239,7 +227,7 @@ class GetClassAndNamespace { return TK_SYMBOL; } - if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) { + if (code[idx] == '-' || is_digit(code[idx])) { //a number const char32_t *rptr; double number = String::to_float(&code[idx], &rptr); @@ -247,10 +235,10 @@ class GetClassAndNamespace { value = number; return TK_NUMBER; - } else if ((code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) { + } else if (is_ascii_char(code[idx]) || code[idx] > 127) { String id; - while ((code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) { + while (is_ascii_char(code[idx]) || code[idx] > 127) { id += code[idx]; idx++; } @@ -320,11 +308,11 @@ public: curly_stack++; break; } else { - break; //whathever else + break; //whatever else } } - if (name != String()) { + if (!name.is_empty()) { namespace_stack[at_level] = name; } diff --git a/tests/test_math.h b/tests/core/math/test_math.h index 4375925bd5..a8aa8f6847 100644 --- a/tests/test_math.h +++ b/tests/core/math/test_math.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_MATH_H #define TEST_MATH_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestMath { diff --git a/tests/test_random_number_generator.h b/tests/core/math/test_random_number_generator.h index 39c4771c19..e8cd47b9d7 100644 --- a/tests/test_random_number_generator.h +++ b/tests/core/math/test_random_number_generator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_rect2.h b/tests/core/math/test_rect2.h index 3d9fe5a32e..0b1106ac3c 100644 --- a/tests/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,15 +32,11 @@ #define TEST_RECT2_H #include "core/math/rect2.h" +#include "core/math/rect2i.h" #include "thirdparty/doctest/doctest.h" namespace TestRect2 { -// We also test Rect2i here, for consistency with the source code where Rect2 -// and Rect2i are defined in the same file. - -// Rect2 - TEST_CASE("[Rect2] Constructor methods") { const Rect2 rect = Rect2(0, 100, 1280, 720); const Rect2 rect_vector = Rect2(Vector2(0, 100), Vector2(1280, 720)); @@ -211,268 +207,98 @@ TEST_CASE("[Rect2] Growing") { } TEST_CASE("[Rect2] Has point") { + Rect2 rect = Rect2(0, 100, 1280, 720); CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).has_point(Vector2(500, 600)), + rect.has_point(Vector2(500, 600)), "has_point() with contained Vector2 should return the expected result."); CHECK_MESSAGE( - !Rect2(0, 100, 1280, 720).has_point(Vector2(0, 0)), + !rect.has_point(Vector2(0, 0)), "has_point() with non-contained Vector2 should return the expected result."); CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).has_point(Vector2(0, 110)), - "has_point() with positive Vector2 on left edge should return the expected result."); - CHECK_MESSAGE( - !Rect2(0, 100, 1280, 720).has_point(Vector2(1280, 110)), - "has_point() with positive Vector2 on right edge should return the expected result."); - - CHECK_MESSAGE( - Rect2(-4000, 100, 1280, 720).has_point(Vector2(-4000, 110)), - "has_point() with negative Vector2 on left edge should return the expected result."); + rect.has_point(rect.position), + "has_point() with positive size should include `position`."); CHECK_MESSAGE( - !Rect2(-4000, 100, 1280, 720).has_point(Vector2(-2720, 110)), - "has_point() with negative Vector2 on right edge should return the expected result."); -} - -TEST_CASE("[Rect2] Intersection") { - CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).intersects(Rect2(0, 300, 100, 100)), - "intersects() with fully enclosed Rect2 should return the expected result."); - CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).intersects(Rect2(1200, 700, 100, 100)), - "intersects() with partially enclosed Rect2 should return the expected result."); + rect.has_point(rect.position + Vector2(1, 1)), + "has_point() with positive size should include `position + (1, 1)`."); CHECK_MESSAGE( - !Rect2(0, 100, 1280, 720).intersects(Rect2(-4000, -4000, 100, 100)), - "intersects() with non-enclosed Rect2 should return the expected result."); -} - -TEST_CASE("[Rect2] Merging") { - CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).merge(Rect2(0, 300, 100, 100)).is_equal_approx(Rect2(0, 100, 1280, 720)), - "merge() with fully enclosed Rect2 should return the expected result."); - CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).merge(Rect2(1200, 700, 100, 100)).is_equal_approx(Rect2(0, 100, 1300, 720)), - "merge() with partially enclosed Rect2 should return the expected result."); - CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).merge(Rect2(-4000, -4000, 100, 100)).is_equal_approx(Rect2(-4000, -4000, 5280, 4820)), - "merge() with non-enclosed Rect2 should return the expected result."); -} - -// Rect2i - -TEST_CASE("[Rect2i] Constructor methods") { - Rect2i recti = Rect2i(0, 100, 1280, 720); - Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720)); - Rect2i recti_copy_recti = Rect2i(recti); - Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720)); - + !rect.has_point(rect.position + Vector2(1, -1)), + "has_point() with positive size should not include `position + (1, -1)`."); CHECK_MESSAGE( - recti == recti_vector, - "Rect2is created with the same dimensions but by different methods should be equal."); + !rect.has_point(rect.position + rect.size), + "has_point() with positive size should not include `position + size`."); CHECK_MESSAGE( - recti == recti_copy_recti, - "Rect2is created with the same dimensions but by different methods should be equal."); + !rect.has_point(rect.position + rect.size + Vector2(1, 1)), + "has_point() with positive size should not include `position + size + (1, 1)`."); CHECK_MESSAGE( - recti == recti_copy_rect, - "Rect2is created with the same dimensions but by different methods should be equal."); -} - -TEST_CASE("[Rect2i] String conversion") { - // Note: This also depends on the Vector2 string representation. + rect.has_point(rect.position + rect.size + Vector2(-1, -1)), + "has_point() with positive size should include `position + size + (-1, -1)`."); CHECK_MESSAGE( - String(Rect2i(0, 100, 1280, 720)) == "[P: (0, 100), S: (1280, 720)]", - "The string representation should match the expected value."); -} + !rect.has_point(rect.position + rect.size + Vector2(-1, 1)), + "has_point() with positive size should not include `position + size + (-1, 1)`."); -TEST_CASE("[Rect2i] Basic getters") { - const Rect2i rect = Rect2i(0, 100, 1280, 720); CHECK_MESSAGE( - rect.get_position() == Vector2i(0, 100), - "get_position() should return the expected value."); + rect.has_point(rect.position + Vector2(0, 10)), + "has_point() with point located on left edge should return true."); CHECK_MESSAGE( - rect.get_size() == Vector2i(1280, 720), - "get_size() should return the expected value."); + !rect.has_point(rect.position + Vector2(rect.size.x, 10)), + "has_point() with point located on right edge should return false."); CHECK_MESSAGE( - rect.get_end() == Vector2i(1280, 820), - "get_end() should return the expected value."); + rect.has_point(rect.position + Vector2(10, 0)), + "has_point() with point located on top edge should return true."); CHECK_MESSAGE( - rect.get_center() == Vector2i(640, 460), - "get_center() should return the expected value."); - CHECK_MESSAGE( - Rect2i(0, 100, 1281, 721).get_center() == Vector2i(640, 460), - "get_center() should return the expected value."); -} + !rect.has_point(rect.position + Vector2(10, rect.size.y)), + "has_point() with point located on bottom edge should return false."); -TEST_CASE("[Rect2i] Basic setters") { - Rect2i rect = Rect2i(0, 100, 1280, 720); - rect.set_end(Vector2i(4000, 4000)); + /* + // FIXME: Disabled for now until GH-37617 is fixed one way or another. + // More tests should then be written like for the positive size case. + rect = Rect2(0, 100, -1280, -720); CHECK_MESSAGE( - rect == Rect2i(0, 100, 4000, 3900), - "set_end() should result in the expected Rect2i."); - - rect = Rect2i(0, 100, 1280, 720); - rect.set_position(Vector2i(4000, 4000)); + rect.has_point(rect.position), + "has_point() with negative size should include `position`."); CHECK_MESSAGE( - rect == Rect2i(4000, 4000, 1280, 720), - "set_position() should result in the expected Rect2i."); + !rect.has_point(rect.position + rect.size), + "has_point() with negative size should not include `position + size`."); + */ - rect = Rect2i(0, 100, 1280, 720); - rect.set_size(Vector2i(4000, 4000)); - CHECK_MESSAGE( - rect == Rect2i(0, 100, 4000, 4000), - "set_size() should result in the expected Rect2i."); -} - -TEST_CASE("[Rect2i] Area getters") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).get_area() == 921'600, - "get_area() should return the expected value."); + rect = Rect2(-4000, -200, 1280, 720); CHECK_MESSAGE( - Rect2i(0, 100, -1280, -720).get_area() == 921'600, - "get_area() should return the expected value."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, -720).get_area() == -921'600, - "get_area() should return the expected value."); + rect.has_point(rect.position + Vector2(0, 10)), + "has_point() with negative position and point located on left edge should return true."); CHECK_MESSAGE( - Rect2i(0, 100, -1280, 720).get_area() == -921'600, - "get_area() should return the expected value."); - CHECK_MESSAGE( - Rect2i(0, 100, 0, 720).get_area() == 0, - "get_area() should return the expected value."); - + !rect.has_point(rect.position + Vector2(rect.size.x, 10)), + "has_point() with negative position and point located on right edge should return false."); CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).has_no_area(), - "has_no_area() should return the expected value on Rect2i with an area."); + rect.has_point(rect.position + Vector2(10, 0)), + "has_point() with negative position and point located on top edge should return true."); CHECK_MESSAGE( - Rect2i(0, 100, 0, 500).has_no_area(), - "has_no_area() should return the expected value on Rect2i with no area."); - CHECK_MESSAGE( - Rect2i(0, 100, 500, 0).has_no_area(), - "has_no_area() should return the expected value on Rect2i with no area."); - CHECK_MESSAGE( - Rect2i(0, 100, 0, 0).has_no_area(), - "has_no_area() should return the expected value on Rect2i with no area."); -} - -TEST_CASE("[Rect2i] Absolute coordinates") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).abs() == Rect2i(0, 100, 1280, 720), - "abs() should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, -100, 1280, 720).abs() == Rect2i(0, -100, 1280, 720), - "abs() should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, -100, -1280, -720).abs() == Rect2i(-1280, -820, 1280, 720), - "abs() should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, 100, -1280, 720).abs() == Rect2i(-1280, 100, 1280, 720), - "abs() should return the expected Rect2i."); + !rect.has_point(rect.position + Vector2(10, rect.size.y)), + "has_point() with negative position and point located on bottom edge should return false."); } -TEST_CASE("[Rect2i] Intersection") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).intersection(Rect2i(0, 300, 100, 100)) == Rect2i(0, 300, 100, 100), - "intersection() with fully enclosed Rect2i should return the expected result."); - // The resulting Rect2i is 100 pixels high because the first Rect2i is vertically offset by 100 pixels. - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).intersection(Rect2i(1200, 700, 100, 100)) == Rect2i(1200, 700, 80, 100), - "intersection() with partially enclosed Rect2i should return the expected result."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).intersection(Rect2i(-4000, -4000, 100, 100)) == Rect2i(), - "intersection() with non-enclosed Rect2i should return the expected result."); -} - -TEST_CASE("[Rect2i] Enclosing") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).encloses(Rect2i(0, 300, 100, 100)), - "encloses() with fully contained Rect2i should return the expected result."); - CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).encloses(Rect2i(1200, 700, 100, 100)), - "encloses() with partially contained Rect2i should return the expected result."); - CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).encloses(Rect2i(-4000, -4000, 100, 100)), - "encloses() with non-contained Rect2i should return the expected result."); -} - -TEST_CASE("[Rect2i] Expanding") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).expand(Vector2i(500, 600)) == Rect2i(0, 100, 1280, 720), - "expand() with contained Vector2i should return the expected result."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).expand(Vector2i(0, 0)) == Rect2i(0, 0, 1280, 820), - "expand() with non-contained Vector2i should return the expected result."); -} - -TEST_CASE("[Rect2i] Growing") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow(100) == Rect2i(-100, 0, 1480, 920), - "grow() with positive value should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow(-100) == Rect2i(100, 200, 1080, 520), - "grow() with negative value should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow(-4000) == Rect2i(4000, 4100, -6720, -7280), - "grow() with large negative value should return the expected Rect2i."); - - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow_individual(100, 200, 300, 400) == Rect2i(-100, -100, 1680, 1320), - "grow_individual() with positive values should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow_individual(-100, 200, 300, -400) == Rect2i(100, -100, 1480, 520), - "grow_individual() with positive and negative values should return the expected Rect2i."); - - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow_side(SIDE_TOP, 500) == Rect2i(0, -400, 1280, 1220), - "grow_side() with positive value should return the expected Rect2i."); - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).grow_side(SIDE_TOP, -500) == Rect2i(0, 600, 1280, 220), - "grow_side() with negative value should return the expected Rect2i."); -} - -TEST_CASE("[Rect2i] Has point") { - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).has_point(Vector2i(500, 600)), - "has_point() with contained Vector2i should return the expected result."); - CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).has_point(Vector2i(0, 0)), - "has_point() with non-contained Vector2i should return the expected result."); - - CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).has_point(Vector2(0, 110)), - "has_point() with positive Vector2 on left edge should return the expected result."); - CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).has_point(Vector2(1280, 110)), - "has_point() with positive Vector2 on right edge should return the expected result."); - - CHECK_MESSAGE( - Rect2i(-4000, 100, 1280, 720).has_point(Vector2(-4000, 110)), - "has_point() with negative Vector2 on left edge should return the expected result."); - CHECK_MESSAGE( - !Rect2i(-4000, 100, 1280, 720).has_point(Vector2(-2720, 110)), - "has_point() with negative Vector2 on right edge should return the expected result."); -} - -TEST_CASE("[Rect2i] Intersection") { +TEST_CASE("[Rect2] Intersection") { CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).intersects(Rect2i(0, 300, 100, 100)), - "intersects() with fully enclosed Rect2i should return the expected result."); + Rect2(0, 100, 1280, 720).intersects(Rect2(0, 300, 100, 100)), + "intersects() with fully enclosed Rect2 should return the expected result."); CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).intersects(Rect2i(1200, 700, 100, 100)), - "intersects() with partially enclosed Rect2i should return the expected result."); + Rect2(0, 100, 1280, 720).intersects(Rect2(1200, 700, 100, 100)), + "intersects() with partially enclosed Rect2 should return the expected result."); CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).intersects(Rect2i(-4000, -4000, 100, 100)), - "intersects() with non-enclosed Rect2i should return the expected result."); + !Rect2(0, 100, 1280, 720).intersects(Rect2(-4000, -4000, 100, 100)), + "intersects() with non-enclosed Rect2 should return the expected result."); } -TEST_CASE("[Rect2i] Merging") { +TEST_CASE("[Rect2] Merging") { CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).merge(Rect2i(0, 300, 100, 100)) == Rect2i(0, 100, 1280, 720), - "merge() with fully enclosed Rect2i should return the expected result."); + Rect2(0, 100, 1280, 720).merge(Rect2(0, 300, 100, 100)).is_equal_approx(Rect2(0, 100, 1280, 720)), + "merge() with fully enclosed Rect2 should return the expected result."); CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).merge(Rect2i(1200, 700, 100, 100)) == Rect2i(0, 100, 1300, 720), - "merge() with partially enclosed Rect2i should return the expected result."); + Rect2(0, 100, 1280, 720).merge(Rect2(1200, 700, 100, 100)).is_equal_approx(Rect2(0, 100, 1300, 720)), + "merge() with partially enclosed Rect2 should return the expected result."); CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).merge(Rect2i(-4000, -4000, 100, 100)) == Rect2i(-4000, -4000, 5280, 4820), - "merge() with non-enclosed Rect2i should return the expected result."); + Rect2(0, 100, 1280, 720).merge(Rect2(-4000, -4000, 100, 100)).is_equal_approx(Rect2(-4000, -4000, 5280, 4820)), + "merge() with non-enclosed Rect2 should return the expected result."); } } // namespace TestRect2 diff --git a/tests/core/math/test_rect2i.h b/tests/core/math/test_rect2i.h new file mode 100644 index 0000000000..0d1a088a66 --- /dev/null +++ b/tests/core/math/test_rect2i.h @@ -0,0 +1,311 @@ +/*************************************************************************/ +/* test_rect2i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_RECT2I_H +#define TEST_RECT2I_H + +#include "core/math/rect2.h" +#include "core/math/rect2i.h" + +#include "thirdparty/doctest/doctest.h" + +namespace TestRect2i { +TEST_CASE("[Rect2i] Constructor methods") { + Rect2i recti = Rect2i(0, 100, 1280, 720); + Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720)); + Rect2i recti_copy_recti = Rect2i(recti); + Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720)); + + CHECK_MESSAGE( + recti == recti_vector, + "Rect2is created with the same dimensions but by different methods should be equal."); + CHECK_MESSAGE( + recti == recti_copy_recti, + "Rect2is created with the same dimensions but by different methods should be equal."); + CHECK_MESSAGE( + recti == recti_copy_rect, + "Rect2is created with the same dimensions but by different methods should be equal."); +} + +TEST_CASE("[Rect2i] String conversion") { + // Note: This also depends on the Vector2 string representation. + CHECK_MESSAGE( + String(Rect2i(0, 100, 1280, 720)) == "[P: (0, 100), S: (1280, 720)]", + "The string representation should match the expected value."); +} + +TEST_CASE("[Rect2i] Basic getters") { + const Rect2i rect = Rect2i(0, 100, 1280, 720); + CHECK_MESSAGE( + rect.get_position() == Vector2i(0, 100), + "get_position() should return the expected value."); + CHECK_MESSAGE( + rect.get_size() == Vector2i(1280, 720), + "get_size() should return the expected value."); + CHECK_MESSAGE( + rect.get_end() == Vector2i(1280, 820), + "get_end() should return the expected value."); + CHECK_MESSAGE( + rect.get_center() == Vector2i(640, 460), + "get_center() should return the expected value."); + CHECK_MESSAGE( + Rect2i(0, 100, 1281, 721).get_center() == Vector2i(640, 460), + "get_center() should return the expected value."); +} + +TEST_CASE("[Rect2i] Basic setters") { + Rect2i rect = Rect2i(0, 100, 1280, 720); + rect.set_end(Vector2i(4000, 4000)); + CHECK_MESSAGE( + rect == Rect2i(0, 100, 4000, 3900), + "set_end() should result in the expected Rect2i."); + + rect = Rect2i(0, 100, 1280, 720); + rect.set_position(Vector2i(4000, 4000)); + CHECK_MESSAGE( + rect == Rect2i(4000, 4000, 1280, 720), + "set_position() should result in the expected Rect2i."); + + rect = Rect2i(0, 100, 1280, 720); + rect.set_size(Vector2i(4000, 4000)); + CHECK_MESSAGE( + rect == Rect2i(0, 100, 4000, 4000), + "set_size() should result in the expected Rect2i."); +} + +TEST_CASE("[Rect2i] Area getters") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).get_area() == 921'600, + "get_area() should return the expected value."); + CHECK_MESSAGE( + Rect2i(0, 100, -1280, -720).get_area() == 921'600, + "get_area() should return the expected value."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, -720).get_area() == -921'600, + "get_area() should return the expected value."); + CHECK_MESSAGE( + Rect2i(0, 100, -1280, 720).get_area() == -921'600, + "get_area() should return the expected value."); + CHECK_MESSAGE( + Rect2i(0, 100, 0, 720).get_area() == 0, + "get_area() should return the expected value."); + + CHECK_MESSAGE( + !Rect2i(0, 100, 1280, 720).has_no_area(), + "has_no_area() should return the expected value on Rect2i with an area."); + CHECK_MESSAGE( + Rect2i(0, 100, 0, 500).has_no_area(), + "has_no_area() should return the expected value on Rect2i with no area."); + CHECK_MESSAGE( + Rect2i(0, 100, 500, 0).has_no_area(), + "has_no_area() should return the expected value on Rect2i with no area."); + CHECK_MESSAGE( + Rect2i(0, 100, 0, 0).has_no_area(), + "has_no_area() should return the expected value on Rect2i with no area."); +} + +TEST_CASE("[Rect2i] Absolute coordinates") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).abs() == Rect2i(0, 100, 1280, 720), + "abs() should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, -100, 1280, 720).abs() == Rect2i(0, -100, 1280, 720), + "abs() should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, -100, -1280, -720).abs() == Rect2i(-1280, -820, 1280, 720), + "abs() should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, 100, -1280, 720).abs() == Rect2i(-1280, 100, 1280, 720), + "abs() should return the expected Rect2i."); +} + +TEST_CASE("[Rect2i] Intersection") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).intersection(Rect2i(0, 300, 100, 100)) == Rect2i(0, 300, 100, 100), + "intersection() with fully enclosed Rect2i should return the expected result."); + // The resulting Rect2i is 100 pixels high because the first Rect2i is vertically offset by 100 pixels. + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).intersection(Rect2i(1200, 700, 100, 100)) == Rect2i(1200, 700, 80, 100), + "intersection() with partially enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).intersection(Rect2i(-4000, -4000, 100, 100)) == Rect2i(), + "intersection() with non-enclosed Rect2i should return the expected result."); +} + +TEST_CASE("[Rect2i] Enclosing") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).encloses(Rect2i(0, 300, 100, 100)), + "encloses() with fully contained Rect2i should return the expected result."); + CHECK_MESSAGE( + !Rect2i(0, 100, 1280, 720).encloses(Rect2i(1200, 700, 100, 100)), + "encloses() with partially contained Rect2i should return the expected result."); + CHECK_MESSAGE( + !Rect2i(0, 100, 1280, 720).encloses(Rect2i(-4000, -4000, 100, 100)), + "encloses() with non-contained Rect2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).encloses(Rect2i(0, 100, 1280, 720)), + "encloses() with identical Rect2i should return the expected result."); +} + +TEST_CASE("[Rect2i] Expanding") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).expand(Vector2i(500, 600)) == Rect2i(0, 100, 1280, 720), + "expand() with contained Vector2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).expand(Vector2i(0, 0)) == Rect2i(0, 0, 1280, 820), + "expand() with non-contained Vector2i should return the expected result."); +} + +TEST_CASE("[Rect2i] Growing") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow(100) == Rect2i(-100, 0, 1480, 920), + "grow() with positive value should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow(-100) == Rect2i(100, 200, 1080, 520), + "grow() with negative value should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow(-4000) == Rect2i(4000, 4100, -6720, -7280), + "grow() with large negative value should return the expected Rect2i."); + + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow_individual(100, 200, 300, 400) == Rect2i(-100, -100, 1680, 1320), + "grow_individual() with positive values should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow_individual(-100, 200, 300, -400) == Rect2i(100, -100, 1480, 520), + "grow_individual() with positive and negative values should return the expected Rect2i."); + + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow_side(SIDE_TOP, 500) == Rect2i(0, -400, 1280, 1220), + "grow_side() with positive value should return the expected Rect2i."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).grow_side(SIDE_TOP, -500) == Rect2i(0, 600, 1280, 220), + "grow_side() with negative value should return the expected Rect2i."); +} + +TEST_CASE("[Rect2i] Has point") { + Rect2i rect = Rect2i(0, 100, 1280, 720); + CHECK_MESSAGE( + rect.has_point(Vector2i(500, 600)), + "has_point() with contained Vector2i should return the expected result."); + CHECK_MESSAGE( + !rect.has_point(Vector2i(0, 0)), + "has_point() with non-contained Vector2i should return the expected result."); + + CHECK_MESSAGE( + rect.has_point(rect.position), + "has_point() with positive size should include `position`."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(1, 1)), + "has_point() with positive size should include `position + (1, 1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(1, -1)), + "has_point() with positive size should not include `position + (1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size), + "has_point() with positive size should not include `position + size`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2i(1, 1)), + "has_point() with positive size should not include `position + size + (1, 1)`."); + CHECK_MESSAGE( + rect.has_point(rect.position + rect.size + Vector2i(-1, -1)), + "has_point() with positive size should include `position + size + (-1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2i(-1, 1)), + "has_point() with positive size should not include `position + size + (-1, 1)`."); + + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(0, 10)), + "has_point() with point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(rect.size.x, 10)), + "has_point() with point located on right edge should return false."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(10, 0)), + "has_point() with point located on top edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(10, rect.size.y)), + "has_point() with point located on bottom edge should return false."); + + /* + // FIXME: Disabled for now until GH-37617 is fixed one way or another. + // More tests should then be written like for the positive size case. + rect = Rect2i(0, 100, -1280, -720); + CHECK_MESSAGE( + rect.has_point(rect.position), + "has_point() with negative size should include `position`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size), + "has_point() with negative size should not include `position + size`."); + */ + + rect = Rect2i(-4000, -200, 1280, 720); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(0, 10)), + "has_point() with negative position and point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(rect.size.x, 10)), + "has_point() with negative position and point located on right edge should return false."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(10, 0)), + "has_point() with negative position and point located on top edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(10, rect.size.y)), + "has_point() with negative position and point located on bottom edge should return false."); +} + +TEST_CASE("[Rect2i] Intersection") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).intersects(Rect2i(0, 300, 100, 100)), + "intersects() with fully enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).intersects(Rect2i(1200, 700, 100, 100)), + "intersects() with partially enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + !Rect2i(0, 100, 1280, 720).intersects(Rect2i(-4000, -4000, 100, 100)), + "intersects() with non-enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + !Rect2i(0, 0, 2, 2).intersects(Rect2i(2, 2, 2, 2)), + "intersects() with adjacent Rect2i should return the expected result."); +} + +TEST_CASE("[Rect2i] Merging") { + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).merge(Rect2i(0, 300, 100, 100)) == Rect2i(0, 100, 1280, 720), + "merge() with fully enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).merge(Rect2i(1200, 700, 100, 100)) == Rect2i(0, 100, 1300, 720), + "merge() with partially enclosed Rect2i should return the expected result."); + CHECK_MESSAGE( + Rect2i(0, 100, 1280, 720).merge(Rect2i(-4000, -4000, 100, 100)) == Rect2i(-4000, -4000, 5280, 4820), + "merge() with non-enclosed Rect2i should return the expected result."); +} +} // namespace TestRect2i + +#endif // TEST_RECT2I_H diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h new file mode 100644 index 0000000000..ff60467bf4 --- /dev/null +++ b/tests/core/math/test_vector2.h @@ -0,0 +1,386 @@ +/*************************************************************************/ +/* test_vector2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_VECTOR2_H +#define TEST_VECTOR2_H + +#include "core/math/vector2.h" +#include "core/math/vector2i.h" +#include "tests/test_macros.h" + +namespace TestVector2 { + +TEST_CASE("[Vector2] Angle methods") { + const Vector2 vector_x = Vector2(1, 0); + const Vector2 vector_y = Vector2(0, 1); + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.angle_to(vector_y), (real_t)Math_TAU / 4), + "Vector2 angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_y.angle_to(vector_x), (real_t)-Math_TAU / 4), + "Vector2 angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.angle_to_point(vector_y), (real_t)Math_TAU * 3 / 8), + "Vector2 angle_to_point should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_y.angle_to_point(vector_x), (real_t)-Math_TAU / 8), + "Vector2 angle_to_point should work as expected."); +} + +TEST_CASE("[Vector2] Axis methods") { + Vector2 vector = Vector2(1.2, 3.4); + CHECK_MESSAGE( + vector.max_axis_index() == Vector2::Axis::AXIS_Y, + "Vector2 max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector2::Axis::AXIS_X, + "Vector2 min_axis_index should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == (real_t)1.2, + "Vector2 array operator should work as expected."); + vector[Vector2::Axis::AXIS_Y] = 3.7; + CHECK_MESSAGE( + vector[Vector2::Axis::AXIS_Y] == (real_t)3.7, + "Vector2 array operator setter should work as expected."); +} + +TEST_CASE("[Vector2] Interpolation methods") { + const Vector2 vector1 = Vector2(1, 2); + const Vector2 vector2 = Vector2(4, 5); + CHECK_MESSAGE( + vector1.lerp(vector2, 0.5) == Vector2(2.5, 3.5), + "Vector2 lerp should work as expected."); + CHECK_MESSAGE( + vector1.lerp(vector2, 1.0 / 3.0).is_equal_approx(Vector2(2, 3)), + "Vector2 lerp should work as expected."); + CHECK_MESSAGE( + vector1.normalized().slerp(vector2.normalized(), 0.5).is_equal_approx(Vector2(0.538953602313995361, 0.84233558177947998)), + "Vector2 slerp should work as expected."); + CHECK_MESSAGE( + vector1.normalized().slerp(vector2.normalized(), 1.0 / 3.0).is_equal_approx(Vector2(0.508990883827209473, 0.860771894454956055)), + "Vector2 slerp should work as expected."); + CHECK_MESSAGE( + Vector2(5, 0).slerp(Vector2(0, 5), 0.5).is_equal_approx(Vector2(5, 5) * Math_SQRT12), + "Vector2 slerp with non-normalized values should work as expected."); + CHECK_MESSAGE( + Vector2().slerp(Vector2(), 0.5) == Vector2(), + "Vector2 slerp with both inputs as zero vectors should return a zero vector."); + CHECK_MESSAGE( + Vector2().slerp(Vector2(1, 1), 0.5) == Vector2(0.5, 0.5), + "Vector2 slerp with one input as zero should behave like a regular lerp."); + CHECK_MESSAGE( + Vector2(1, 1).slerp(Vector2(), 0.5) == Vector2(0.5, 0.5), + "Vector2 slerp with one input as zero should behave like a regular lerp."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)4.31959610746631919), + "Vector2 slerp with different length input should return a vector with an interpolated length."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.angle_to(vector1.slerp(vector2, 0.5)) * 2, vector1.angle_to(vector2)), + "Vector2 slerp with different length input should return a vector with an interpolated angle."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector2(), Vector2(7, 7), 0.5) == Vector2(2.375, 3.5), + "Vector2 cubic_interpolate should work as expected."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector2(), Vector2(7, 7), 1.0 / 3.0).is_equal_approx(Vector2(1.851851940155029297, 2.962963104248046875)), + "Vector2 cubic_interpolate should work as expected."); + CHECK_MESSAGE( + Vector2(1, 0).move_toward(Vector2(10, 0), 3) == Vector2(4, 0), + "Vector2 move_toward should work as expected."); +} + +TEST_CASE("[Vector2] Length methods") { + const Vector2 vector1 = Vector2(10, 10); + const Vector2 vector2 = Vector2(20, 30); + CHECK_MESSAGE( + vector1.length_squared() == 200, + "Vector2 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 10 * (real_t)Math_SQRT2), + "Vector2 length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 1300, + "Vector2 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), (real_t)36.05551275463989293119), + "Vector2 length should work as expected."); + CHECK_MESSAGE( + vector1.distance_squared_to(vector2) == 500, + "Vector2 distance_squared_to should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.distance_to(vector2), (real_t)22.36067977499789696409), + "Vector2 distance_to should work as expected."); +} + +TEST_CASE("[Vector2] Limiting methods") { + const Vector2 vector = Vector2(10, 10); + CHECK_MESSAGE( + vector.limit_length().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)), + "Vector2 limit_length should work as expected."); + CHECK_MESSAGE( + vector.limit_length(5).is_equal_approx(5 * Vector2(Math_SQRT12, Math_SQRT12)), + "Vector2 limit_length should work as expected."); + + CHECK_MESSAGE( + Vector2(-5, 15).clamp(Vector2(), vector).is_equal_approx(Vector2(0, 10)), + "Vector2 clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector2(0, 15), Vector2(5, 20)).is_equal_approx(Vector2(5, 15)), + "Vector2 clamp should work as expected."); +} + +TEST_CASE("[Vector2] Normalization methods") { + CHECK_MESSAGE( + Vector2(1, 0).is_normalized() == true, + "Vector2 is_normalized should return true for a normalized vector."); + CHECK_MESSAGE( + Vector2(1, 1).is_normalized() == false, + "Vector2 is_normalized should return false for a non-normalized vector."); + CHECK_MESSAGE( + Vector2(1, 0).normalized() == Vector2(1, 0), + "Vector2 normalized should return the same vector for a normalized vector."); + CHECK_MESSAGE( + Vector2(1, 1).normalized().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)), + "Vector2 normalized should work as expected."); +} + +TEST_CASE("[Vector2] Operators") { + const Vector2 decimal1 = Vector2(2.3, 4.9); + const Vector2 decimal2 = Vector2(1.2, 3.4); + const Vector2 power1 = Vector2(0.75, 1.5); + const Vector2 power2 = Vector2(0.5, 0.125); + const Vector2 int1 = Vector2(4, 5); + const Vector2 int2 = Vector2(1, 2); + + CHECK_MESSAGE( + (decimal1 + decimal2).is_equal_approx(Vector2(3.5, 8.3)), + "Vector2 addition should behave as expected."); + CHECK_MESSAGE( + (power1 + power2) == Vector2(1.25, 1.625), + "Vector2 addition with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 + int2) == Vector2(5, 7), + "Vector2 addition with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 - decimal2).is_equal_approx(Vector2(1.1, 1.5)), + "Vector2 subtraction should behave as expected."); + CHECK_MESSAGE( + (power1 - power2) == Vector2(0.25, 1.375), + "Vector2 subtraction with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 - int2) == Vector2(3, 3), + "Vector2 subtraction with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * decimal2).is_equal_approx(Vector2(2.76, 16.66)), + "Vector2 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * power2) == Vector2(0.375, 0.1875), + "Vector2 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * int2) == Vector2(4, 10), + "Vector2 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / decimal2).is_equal_approx(Vector2(1.91666666666666666, 1.44117647058823529)), + "Vector2 division should behave as expected."); + CHECK_MESSAGE( + (power1 / power2) == Vector2(1.5, 12.0), + "Vector2 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / int2) == Vector2(4, 2.5), + "Vector2 division with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * 2).is_equal_approx(Vector2(4.6, 9.8)), + "Vector2 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * 2) == Vector2(1.5, 3), + "Vector2 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * 2) == Vector2(8, 10), + "Vector2 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / 2).is_equal_approx(Vector2(1.15, 2.45)), + "Vector2 division should behave as expected."); + CHECK_MESSAGE( + (power1 / 2) == Vector2(0.375, 0.75), + "Vector2 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / 2) == Vector2(2, 2.5), + "Vector2 division with integers should give exact results."); + + CHECK_MESSAGE( + ((Vector2i)decimal1) == Vector2i(2, 4), + "Vector2 cast to Vector2i should work as expected."); + CHECK_MESSAGE( + ((Vector2i)decimal2) == Vector2i(1, 3), + "Vector2 cast to Vector2i should work as expected."); + CHECK_MESSAGE( + Vector2(Vector2i(1, 2)) == Vector2(1, 2), + "Vector2 constructed from Vector2i should work as expected."); + + CHECK_MESSAGE( + ((String)decimal1) == "(2.3, 4.9)", + "Vector2 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)decimal2) == "(1.2, 3.4)", + "Vector2 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)Vector2(9.8, 9.9)) == "(9.8, 9.9)", + "Vector2 cast to String should work as expected."); +#ifdef REAL_T_IS_DOUBLE + CHECK_MESSAGE( + ((String)Vector2(Math_PI, Math_TAU)) == "(3.14159265358979, 6.28318530717959)", + "Vector2 cast to String should print the correct amount of digits for real_t = double."); +#else + CHECK_MESSAGE( + ((String)Vector2(Math_PI, Math_TAU)) == "(3.141593, 6.283185)", + "Vector2 cast to String should print the correct amount of digits for real_t = float."); +#endif // REAL_T_IS_DOUBLE +} + +TEST_CASE("[Vector2] Other methods") { + const Vector2 vector = Vector2(1.2, 3.4); + CHECK_MESSAGE( + Math::is_equal_approx(vector.aspect(), (real_t)1.2 / (real_t)3.4), + "Vector2 aspect should work as expected."); + CHECK_MESSAGE( + vector.direction_to(Vector2()).is_equal_approx(-vector.normalized()), + "Vector2 direction_to should work as expected."); + CHECK_MESSAGE( + Vector2(1, 1).direction_to(Vector2(2, 2)).is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)), + "Vector2 direction_to should work as expected."); + CHECK_MESSAGE( + vector.posmod(2).is_equal_approx(Vector2(1.2, 1.4)), + "Vector2 posmod should work as expected."); + CHECK_MESSAGE( + (-vector).posmod(2).is_equal_approx(Vector2(0.8, 0.6)), + "Vector2 posmod should work as expected."); + CHECK_MESSAGE( + vector.posmodv(Vector2(1, 2)).is_equal_approx(Vector2(0.2, 1.4)), + "Vector2 posmodv should work as expected."); + CHECK_MESSAGE( + (-vector).posmodv(Vector2(2, 3)).is_equal_approx(Vector2(0.8, 2.6)), + "Vector2 posmodv should work as expected."); + CHECK_MESSAGE( + vector.rotated(Math_TAU / 4).is_equal_approx(Vector2(-3.4, 1.2)), + "Vector2 rotated should work as expected."); + CHECK_MESSAGE( + vector.snapped(Vector2(1, 1)) == Vector2(1, 3), + "Vector2 snapped to integers should be the same as rounding."); + CHECK_MESSAGE( + Vector2(3.4, 5.6).snapped(Vector2(1, 1)) == Vector2(3, 6), + "Vector2 snapped to integers should be the same as rounding."); + CHECK_MESSAGE( + vector.snapped(Vector2(0.25, 0.25)) == Vector2(1.25, 3.5), + "Vector2 snapped to 0.25 should give exact results."); +} + +TEST_CASE("[Vector2] Plane methods") { + const Vector2 vector = Vector2(1.2, 3.4); + const Vector2 vector_y = Vector2(0, 1); + CHECK_MESSAGE( + vector.bounce(vector_y) == Vector2(1.2, -3.4), + "Vector2 bounce on a plane with normal of the Y axis should."); + CHECK_MESSAGE( + vector.reflect(vector_y) == Vector2(-1.2, 3.4), + "Vector2 reflect on a plane with normal of the Y axis should."); + CHECK_MESSAGE( + vector.project(vector_y) == Vector2(0, 3.4), + "Vector2 projected on the X axis should only give the Y component."); + CHECK_MESSAGE( + vector.slide(vector_y) == Vector2(1.2, 0), + "Vector2 slide on a plane with normal of the Y axis should set the Y to zero."); +} + +TEST_CASE("[Vector2] Rounding methods") { + const Vector2 vector1 = Vector2(1.2, 5.6); + const Vector2 vector2 = Vector2(1.2, -5.6); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector2 abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector2 abs should work as expected."); + + CHECK_MESSAGE( + vector1.ceil() == Vector2(2, 6), + "Vector2 ceil should work as expected."); + CHECK_MESSAGE( + vector2.ceil() == Vector2(2, -5), + "Vector2 ceil should work as expected."); + + CHECK_MESSAGE( + vector1.floor() == Vector2(1, 5), + "Vector2 floor should work as expected."); + CHECK_MESSAGE( + vector2.floor() == Vector2(1, -6), + "Vector2 floor should work as expected."); + + CHECK_MESSAGE( + vector1.round() == Vector2(1, 6), + "Vector2 round should work as expected."); + CHECK_MESSAGE( + vector2.round() == Vector2(1, -6), + "Vector2 round should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector2(1, 1), + "Vector2 sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector2(1, -1), + "Vector2 sign should work as expected."); +} + +TEST_CASE("[Vector2] Linear algebra methods") { + const Vector2 vector_x = Vector2(1, 0); + const Vector2 vector_y = Vector2(0, 1); + CHECK_MESSAGE( + vector_x.cross(vector_y) == 1, + "Vector2 cross product of X and Y should give 1."); + CHECK_MESSAGE( + vector_y.cross(vector_x) == -1, + "Vector2 cross product of Y and X should give negative 1."); + + CHECK_MESSAGE( + vector_x.dot(vector_y) == 0.0, + "Vector2 dot product of perpendicular vectors should be zero."); + CHECK_MESSAGE( + vector_x.dot(vector_x) == 1.0, + "Vector2 dot product of identical unit vectors should be one."); + CHECK_MESSAGE( + (vector_x * 10).dot(vector_x * 10) == 100.0, + "Vector2 dot product of same direction vectors should behave as expected."); +} +} // namespace TestVector2 + +#endif // TEST_VECTOR2_H diff --git a/tests/core/math/test_vector2i.h b/tests/core/math/test_vector2i.h new file mode 100644 index 0000000000..841bb793a4 --- /dev/null +++ b/tests/core/math/test_vector2i.h @@ -0,0 +1,145 @@ +/*************************************************************************/ +/* test_vector2i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_VECTOR2I_H +#define TEST_VECTOR2I_H + +#include "core/math/vector2.h" +#include "core/math/vector2i.h" +#include "tests/test_macros.h" + +namespace TestVector2i { + +TEST_CASE("[Vector2i] Axis methods") { + Vector2i vector = Vector2i(2, 3); + CHECK_MESSAGE( + vector.max_axis_index() == Vector2i::Axis::AXIS_Y, + "Vector2i max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector2i::Axis::AXIS_X, + "Vector2i min_axis_index should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == 2, + "Vector2i array operator should work as expected."); + vector[Vector2i::Axis::AXIS_Y] = 5; + CHECK_MESSAGE( + vector[Vector2i::Axis::AXIS_Y] == 5, + "Vector2i array operator setter should work as expected."); +} + +TEST_CASE("[Vector2i] Clamp method") { + const Vector2i vector = Vector2i(10, 10); + CHECK_MESSAGE( + Vector2i(-5, 15).clamp(Vector2i(), vector) == Vector2i(0, 10), + "Vector2i clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector2i(0, 15), Vector2i(5, 20)) == Vector2i(5, 15), + "Vector2i clamp should work as expected."); +} + +TEST_CASE("[Vector2i] Length methods") { + const Vector2i vector1 = Vector2i(10, 10); + const Vector2i vector2 = Vector2i(20, 30); + CHECK_MESSAGE( + vector1.length_squared() == 200, + "Vector2i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 10 * Math_SQRT2), + "Vector2i length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 1300, + "Vector2i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), 36.05551275463989293119), + "Vector2i length should work as expected."); +} + +TEST_CASE("[Vector2i] Operators") { + const Vector2i vector1 = Vector2i(5, 9); + const Vector2i vector2 = Vector2i(2, 3); + + CHECK_MESSAGE( + (vector1 + vector2) == Vector2i(7, 12), + "Vector2i addition with integers should give exact results."); + CHECK_MESSAGE( + (vector1 - vector2) == Vector2i(3, 6), + "Vector2i subtraction with integers should give exact results."); + CHECK_MESSAGE( + (vector1 * vector2) == Vector2i(10, 27), + "Vector2i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / vector2) == Vector2i(2, 3), + "Vector2i division with integers should give exact results."); + + CHECK_MESSAGE( + (vector1 * 2) == Vector2i(10, 18), + "Vector2i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / 2) == Vector2i(2, 4), + "Vector2i division with integers should give exact results."); + + CHECK_MESSAGE( + ((Vector2)vector1) == Vector2(5, 9), + "Vector2i cast to Vector2 should work as expected."); + CHECK_MESSAGE( + ((Vector2)vector2) == Vector2(2, 3), + "Vector2i cast to Vector2 should work as expected."); + CHECK_MESSAGE( + Vector2i(Vector2(1.1, 2.9)) == Vector2i(1, 2), + "Vector2i constructed from Vector2 should work as expected."); +} + +TEST_CASE("[Vector2i] Other methods") { + const Vector2i vector = Vector2i(1, 3); + CHECK_MESSAGE( + Math::is_equal_approx(vector.aspect(), (real_t)1.0 / (real_t)3.0), + "Vector2i aspect should work as expected."); +} + +TEST_CASE("[Vector2i] Abs and sign methods") { + const Vector2i vector1 = Vector2i(1, 3); + const Vector2i vector2 = Vector2i(1, -3); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector2i abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector2i abs should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector2i(1, 1), + "Vector2i sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector2i(1, -1), + "Vector2i sign should work as expected."); +} +} // namespace TestVector2i + +#endif // TEST_VECTOR2I_H diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h new file mode 100644 index 0000000000..847a7c0b3f --- /dev/null +++ b/tests/core/math/test_vector3.h @@ -0,0 +1,414 @@ +/*************************************************************************/ +/* test_vector3.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_VECTOR3_H +#define TEST_VECTOR3_H + +#include "core/math/vector3.h" +#include "tests/test_macros.h" + +#define Math_SQRT13 0.57735026918962576450914878050196 +#define Math_SQRT3 1.7320508075688772935274463415059 + +namespace TestVector3 { + +TEST_CASE("[Vector3] Angle methods") { + const Vector3 vector_x = Vector3(1, 0, 0); + const Vector3 vector_y = Vector3(0, 1, 0); + const Vector3 vector_yz = Vector3(0, 1, 1); + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.angle_to(vector_y), (real_t)Math_TAU / 4), + "Vector3 angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.angle_to(vector_yz), (real_t)Math_TAU / 4), + "Vector3 angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_yz.angle_to(vector_x), (real_t)Math_TAU / 4), + "Vector3 angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_y.angle_to(vector_yz), (real_t)Math_TAU / 8), + "Vector3 angle_to should work as expected."); + + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.signed_angle_to(vector_y, vector_y), (real_t)Math_TAU / 4), + "Vector3 signed_angle_to edge case should be positive."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_x.signed_angle_to(vector_yz, vector_y), (real_t)Math_TAU / -4), + "Vector3 signed_angle_to should work as expected."); + CHECK_MESSAGE( + Math::is_equal_approx(vector_yz.signed_angle_to(vector_x, vector_y), (real_t)Math_TAU / 4), + "Vector3 signed_angle_to should work as expected."); +} + +TEST_CASE("[Vector3] Axis methods") { + Vector3 vector = Vector3(1.2, 3.4, 5.6); + CHECK_MESSAGE( + vector.max_axis_index() == Vector3::Axis::AXIS_Z, + "Vector3 max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector3::Axis::AXIS_X, + "Vector3 min_axis_index should work as expected."); + CHECK_MESSAGE( + vector.get_axis(vector.max_axis_index()) == (real_t)5.6, + "Vector3 get_axis should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == (real_t)1.2, + "Vector3 array operator should work as expected."); + + vector.set_axis(Vector3::Axis::AXIS_Y, 4.7); + CHECK_MESSAGE( + vector.get_axis(Vector3::Axis::AXIS_Y) == (real_t)4.7, + "Vector3 set_axis should work as expected."); + vector[Vector3::Axis::AXIS_Y] = 3.7; + CHECK_MESSAGE( + vector[Vector3::Axis::AXIS_Y] == (real_t)3.7, + "Vector3 array operator setter should work as expected."); +} + +TEST_CASE("[Vector3] Interpolation methods") { + const Vector3 vector1 = Vector3(1, 2, 3); + const Vector3 vector2 = Vector3(4, 5, 6); + CHECK_MESSAGE( + vector1.lerp(vector2, 0.5) == Vector3(2.5, 3.5, 4.5), + "Vector3 lerp should work as expected."); + CHECK_MESSAGE( + vector1.lerp(vector2, 1.0 / 3.0).is_equal_approx(Vector3(2, 3, 4)), + "Vector3 lerp should work as expected."); + CHECK_MESSAGE( + vector1.normalized().slerp(vector2.normalized(), 0.5).is_equal_approx(Vector3(0.363866806030273438, 0.555698215961456299, 0.747529566287994385)), + "Vector3 slerp should work as expected."); + CHECK_MESSAGE( + vector1.normalized().slerp(vector2.normalized(), 1.0 / 3.0).is_equal_approx(Vector3(0.332119762897491455, 0.549413740634918213, 0.766707837581634521)), + "Vector3 slerp should work as expected."); + CHECK_MESSAGE( + Vector3(5, 0, 0).slerp(Vector3(0, 3, 4), 0.5).is_equal_approx(Vector3(3.535533905029296875, 2.121320486068725586, 2.828427314758300781)), + "Vector3 slerp with non-normalized values should work as expected."); + CHECK_MESSAGE( + Vector3().slerp(Vector3(), 0.5) == Vector3(), + "Vector3 slerp with both inputs as zero vectors should return a zero vector."); + CHECK_MESSAGE( + Vector3().slerp(Vector3(1, 1, 1), 0.5) == Vector3(0.5, 0.5, 0.5), + "Vector3 slerp with one input as zero should behave like a regular lerp."); + CHECK_MESSAGE( + Vector3(1, 1, 1).slerp(Vector3(), 0.5) == Vector3(0.5, 0.5, 0.5), + "Vector3 slerp with one input as zero should behave like a regular lerp."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)6.25831088708303172), + "Vector3 slerp with different length input should return a vector with an interpolated length."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.angle_to(vector1.slerp(vector2, 0.5)) * 2, vector1.angle_to(vector2)), + "Vector3 slerp with different length input should return a vector with an interpolated angle."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector3(), Vector3(7, 7, 7), 0.5) == Vector3(2.375, 3.5, 4.625), + "Vector3 cubic_interpolate should work as expected."); + CHECK_MESSAGE( + vector1.cubic_interpolate(vector2, Vector3(), Vector3(7, 7, 7), 1.0 / 3.0).is_equal_approx(Vector3(1.851851940155029297, 2.962963104248046875, 4.074074268341064453)), + "Vector3 cubic_interpolate should work as expected."); + CHECK_MESSAGE( + Vector3(1, 0, 0).move_toward(Vector3(10, 0, 0), 3) == Vector3(4, 0, 0), + "Vector3 move_toward should work as expected."); +} + +TEST_CASE("[Vector3] Length methods") { + const Vector3 vector1 = Vector3(10, 10, 10); + const Vector3 vector2 = Vector3(20, 30, 40); + CHECK_MESSAGE( + vector1.length_squared() == 300, + "Vector3 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 10 * (real_t)Math_SQRT3), + "Vector3 length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 2900, + "Vector3 length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), (real_t)53.8516480713450403125), + "Vector3 length should work as expected."); + CHECK_MESSAGE( + vector1.distance_squared_to(vector2) == 1400, + "Vector3 distance_squared_to should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.distance_to(vector2), (real_t)37.41657386773941385584), + "Vector3 distance_to should work as expected."); +} + +TEST_CASE("[Vector3] Limiting methods") { + const Vector3 vector = Vector3(10, 10, 10); + CHECK_MESSAGE( + vector.limit_length().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)), + "Vector3 limit_length should work as expected."); + CHECK_MESSAGE( + vector.limit_length(5).is_equal_approx(5 * Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)), + "Vector3 limit_length should work as expected."); + + CHECK_MESSAGE( + Vector3(-5, 5, 15).clamp(Vector3(), vector) == Vector3(0, 5, 10), + "Vector3 clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector3(0, 10, 15), Vector3(5, 10, 20)) == Vector3(5, 10, 15), + "Vector3 clamp should work as expected."); +} + +TEST_CASE("[Vector3] Normalization methods") { + CHECK_MESSAGE( + Vector3(1, 0, 0).is_normalized() == true, + "Vector3 is_normalized should return true for a normalized vector."); + CHECK_MESSAGE( + Vector3(1, 1, 1).is_normalized() == false, + "Vector3 is_normalized should return false for a non-normalized vector."); + CHECK_MESSAGE( + Vector3(1, 0, 0).normalized() == Vector3(1, 0, 0), + "Vector3 normalized should return the same vector for a normalized vector."); + CHECK_MESSAGE( + Vector3(1, 1, 0).normalized().is_equal_approx(Vector3(Math_SQRT12, Math_SQRT12, 0)), + "Vector3 normalized should work as expected."); + CHECK_MESSAGE( + Vector3(1, 1, 1).normalized().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)), + "Vector3 normalized should work as expected."); +} + +TEST_CASE("[Vector3] Operators") { + const Vector3 decimal1 = Vector3(2.3, 4.9, 7.8); + const Vector3 decimal2 = Vector3(1.2, 3.4, 5.6); + const Vector3 power1 = Vector3(0.75, 1.5, 0.625); + const Vector3 power2 = Vector3(0.5, 0.125, 0.25); + const Vector3 int1 = Vector3(4, 5, 9); + const Vector3 int2 = Vector3(1, 2, 3); + + CHECK_MESSAGE( + (decimal1 + decimal2).is_equal_approx(Vector3(3.5, 8.3, 13.4)), + "Vector3 addition should behave as expected."); + CHECK_MESSAGE( + (power1 + power2) == Vector3(1.25, 1.625, 0.875), + "Vector3 addition with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 + int2) == Vector3(5, 7, 12), + "Vector3 addition with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 - decimal2).is_equal_approx(Vector3(1.1, 1.5, 2.2)), + "Vector3 subtraction should behave as expected."); + CHECK_MESSAGE( + (power1 - power2) == Vector3(0.25, 1.375, 0.375), + "Vector3 subtraction with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 - int2) == Vector3(3, 3, 6), + "Vector3 subtraction with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * decimal2).is_equal_approx(Vector3(2.76, 16.66, 43.68)), + "Vector3 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * power2) == Vector3(0.375, 0.1875, 0.15625), + "Vector3 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * int2) == Vector3(4, 10, 27), + "Vector3 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / decimal2).is_equal_approx(Vector3(1.91666666666666666, 1.44117647058823529, 1.39285714285714286)), + "Vector3 division should behave as expected."); + CHECK_MESSAGE( + (power1 / power2) == Vector3(1.5, 12.0, 2.5), + "Vector3 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / int2) == Vector3(4, 2.5, 3), + "Vector3 division with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 * 2).is_equal_approx(Vector3(4.6, 9.8, 15.6)), + "Vector3 multiplication should behave as expected."); + CHECK_MESSAGE( + (power1 * 2) == Vector3(1.5, 3, 1.25), + "Vector3 multiplication with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 * 2) == Vector3(8, 10, 18), + "Vector3 multiplication with integers should give exact results."); + + CHECK_MESSAGE( + (decimal1 / 2).is_equal_approx(Vector3(1.15, 2.45, 3.9)), + "Vector3 division should behave as expected."); + CHECK_MESSAGE( + (power1 / 2) == Vector3(0.375, 0.75, 0.3125), + "Vector3 division with powers of two should give exact results."); + CHECK_MESSAGE( + (int1 / 2) == Vector3(2, 2.5, 4.5), + "Vector3 division with integers should give exact results."); + + CHECK_MESSAGE( + ((Vector3i)decimal1) == Vector3i(2, 4, 7), + "Vector3 cast to Vector3i should work as expected."); + CHECK_MESSAGE( + ((Vector3i)decimal2) == Vector3i(1, 3, 5), + "Vector3 cast to Vector3i should work as expected."); + CHECK_MESSAGE( + Vector3(Vector3i(1, 2, 3)) == Vector3(1, 2, 3), + "Vector3 constructed from Vector3i should work as expected."); + + CHECK_MESSAGE( + ((String)decimal1) == "(2.3, 4.9, 7.8)", + "Vector3 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)decimal2) == "(1.2, 3.4, 5.6)", + "Vector3 cast to String should work as expected."); + CHECK_MESSAGE( + ((String)Vector3(9.7, 9.8, 9.9)) == "(9.7, 9.8, 9.9)", + "Vector3 cast to String should work as expected."); +#ifdef REAL_T_IS_DOUBLE + CHECK_MESSAGE( + ((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888)", + "Vector3 cast to String should print the correct amount of digits for real_t = double."); +#else + CHECK_MESSAGE( + ((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051)", + "Vector3 cast to String should print the correct amount of digits for real_t = float."); +#endif // REAL_T_IS_DOUBLE +} + +TEST_CASE("[Vector3] Other methods") { + const Vector3 vector = Vector3(1.2, 3.4, 5.6); + CHECK_MESSAGE( + vector.direction_to(Vector3()).is_equal_approx(-vector.normalized()), + "Vector3 direction_to should work as expected."); + CHECK_MESSAGE( + Vector3(1, 1, 1).direction_to(Vector3(2, 2, 2)).is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)), + "Vector3 direction_to should work as expected."); + CHECK_MESSAGE( + vector.inverse().is_equal_approx(Vector3(1 / 1.2, 1 / 3.4, 1 / 5.6)), + "Vector3 inverse should work as expected."); + CHECK_MESSAGE( + vector.posmod(2).is_equal_approx(Vector3(1.2, 1.4, 1.6)), + "Vector3 posmod should work as expected."); + CHECK_MESSAGE( + (-vector).posmod(2).is_equal_approx(Vector3(0.8, 0.6, 0.4)), + "Vector3 posmod should work as expected."); + CHECK_MESSAGE( + vector.posmodv(Vector3(1, 2, 3)).is_equal_approx(Vector3(0.2, 1.4, 2.6)), + "Vector3 posmodv should work as expected."); + CHECK_MESSAGE( + (-vector).posmodv(Vector3(2, 3, 4)).is_equal_approx(Vector3(0.8, 2.6, 2.4)), + "Vector3 posmodv should work as expected."); + CHECK_MESSAGE( + vector.rotated(Vector3(0, 1, 0), Math_TAU / 4).is_equal_approx(Vector3(5.6, 3.4, -1.2)), + "Vector3 rotated should work as expected."); + CHECK_MESSAGE( + vector.snapped(Vector3(1, 1, 1)) == Vector3(1, 3, 6), + "Vector3 snapped to integers should be the same as rounding."); + CHECK_MESSAGE( + vector.snapped(Vector3(0.25, 0.25, 0.25)) == Vector3(1.25, 3.5, 5.5), + "Vector3 snapped to 0.25 should give exact results."); +} + +TEST_CASE("[Vector3] Plane methods") { + const Vector3 vector = Vector3(1.2, 3.4, 5.6); + const Vector3 vector_y = Vector3(0, 1, 0); + CHECK_MESSAGE( + vector.bounce(vector_y) == Vector3(1.2, -3.4, 5.6), + "Vector3 bounce on a plane with normal of the Y axis should."); + CHECK_MESSAGE( + vector.reflect(vector_y) == Vector3(-1.2, 3.4, -5.6), + "Vector3 reflect on a plane with normal of the Y axis should."); + CHECK_MESSAGE( + vector.project(vector_y) == Vector3(0, 3.4, 0), + "Vector3 projected on the X axis should only give the Y component."); + CHECK_MESSAGE( + vector.slide(vector_y) == Vector3(1.2, 0, 5.6), + "Vector3 slide on a plane with normal of the Y axis should set the Y to zero."); +} + +TEST_CASE("[Vector3] Rounding methods") { + const Vector3 vector1 = Vector3(1.2, 3.4, 5.6); + const Vector3 vector2 = Vector3(1.2, -3.4, -5.6); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector3 abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector3 abs should work as expected."); + + CHECK_MESSAGE( + vector1.ceil() == Vector3(2, 4, 6), + "Vector3 ceil should work as expected."); + CHECK_MESSAGE( + vector2.ceil() == Vector3(2, -3, -5), + "Vector3 ceil should work as expected."); + + CHECK_MESSAGE( + vector1.floor() == Vector3(1, 3, 5), + "Vector3 floor should work as expected."); + CHECK_MESSAGE( + vector2.floor() == Vector3(1, -4, -6), + "Vector3 floor should work as expected."); + + CHECK_MESSAGE( + vector1.round() == Vector3(1, 3, 6), + "Vector3 round should work as expected."); + CHECK_MESSAGE( + vector2.round() == Vector3(1, -3, -6), + "Vector3 round should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector3(1, 1, 1), + "Vector3 sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector3(1, -1, -1), + "Vector3 sign should work as expected."); +} + +TEST_CASE("[Vector3] Linear algebra methods") { + const Vector3 vector_x = Vector3(1, 0, 0); + const Vector3 vector_y = Vector3(0, 1, 0); + const Vector3 vector_z = Vector3(0, 0, 1); + CHECK_MESSAGE( + vector_x.cross(vector_y) == vector_z, + "Vector3 cross product of X and Y should give Z."); + CHECK_MESSAGE( + vector_y.cross(vector_x) == -vector_z, + "Vector3 cross product of Y and X should give negative Z."); + CHECK_MESSAGE( + vector_y.cross(vector_z) == vector_x, + "Vector3 cross product of Y and Z should give X."); + CHECK_MESSAGE( + vector_z.cross(vector_x) == vector_y, + "Vector3 cross product of Z and X should give Y."); + + CHECK_MESSAGE( + vector_x.dot(vector_y) == 0.0, + "Vector3 dot product of perpendicular vectors should be zero."); + CHECK_MESSAGE( + vector_x.dot(vector_x) == 1.0, + "Vector3 dot product of identical unit vectors should be one."); + CHECK_MESSAGE( + (vector_x * 10).dot(vector_x * 10) == 100.0, + "Vector3 dot product of same direction vectors should behave as expected."); +} +} // namespace TestVector3 + +#endif // TEST_VECTOR3_H diff --git a/tests/core/math/test_vector3i.h b/tests/core/math/test_vector3i.h new file mode 100644 index 0000000000..b1c6944eba --- /dev/null +++ b/tests/core/math/test_vector3i.h @@ -0,0 +1,145 @@ +/*************************************************************************/ +/* test_vector3i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_VECTOR3I_H +#define TEST_VECTOR3I_H + +#include "core/math/vector3i.h" +#include "tests/test_macros.h" + +namespace TestVector3i { + +TEST_CASE("[Vector3i] Axis methods") { + Vector3i vector = Vector3i(1, 2, 3); + CHECK_MESSAGE( + vector.max_axis_index() == Vector3i::Axis::AXIS_Z, + "Vector3i max_axis_index should work as expected."); + CHECK_MESSAGE( + vector.min_axis_index() == Vector3i::Axis::AXIS_X, + "Vector3i min_axis_index should work as expected."); + CHECK_MESSAGE( + vector.get_axis(vector.max_axis_index()) == 3, + "Vector3i get_axis should work as expected."); + CHECK_MESSAGE( + vector[vector.min_axis_index()] == 1, + "Vector3i array operator should work as expected."); + + vector.set_axis(Vector3i::Axis::AXIS_Y, 4); + CHECK_MESSAGE( + vector.get_axis(Vector3i::Axis::AXIS_Y) == 4, + "Vector3i set_axis should work as expected."); + vector[Vector3i::Axis::AXIS_Y] = 5; + CHECK_MESSAGE( + vector[Vector3i::Axis::AXIS_Y] == 5, + "Vector3i array operator setter should work as expected."); +} + +TEST_CASE("[Vector3i] Clamp method") { + const Vector3i vector = Vector3i(10, 10, 10); + CHECK_MESSAGE( + Vector3i(-5, 5, 15).clamp(Vector3i(), vector) == Vector3i(0, 5, 10), + "Vector3i clamp should work as expected."); + CHECK_MESSAGE( + vector.clamp(Vector3i(0, 10, 15), Vector3i(5, 10, 20)) == Vector3i(5, 10, 15), + "Vector3i clamp should work as expected."); +} + +TEST_CASE("[Vector3i] Length methods") { + const Vector3i vector1 = Vector3i(10, 10, 10); + const Vector3i vector2 = Vector3i(20, 30, 40); + CHECK_MESSAGE( + vector1.length_squared() == 300, + "Vector3i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector1.length(), 10 * Math_SQRT3), + "Vector3i length should work as expected."); + CHECK_MESSAGE( + vector2.length_squared() == 2900, + "Vector3i length_squared should work as expected and return exact result."); + CHECK_MESSAGE( + Math::is_equal_approx(vector2.length(), 53.8516480713450403125), + "Vector3i length should work as expected."); +} + +TEST_CASE("[Vector3i] Operators") { + const Vector3i vector1 = Vector3i(4, 5, 9); + const Vector3i vector2 = Vector3i(1, 2, 3); + + CHECK_MESSAGE( + (vector1 + vector2) == Vector3i(5, 7, 12), + "Vector3i addition with integers should give exact results."); + CHECK_MESSAGE( + (vector1 - vector2) == Vector3i(3, 3, 6), + "Vector3i subtraction with integers should give exact results."); + CHECK_MESSAGE( + (vector1 * vector2) == Vector3i(4, 10, 27), + "Vector3i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / vector2) == Vector3i(4, 2, 3), + "Vector3i division with integers should give exact results."); + + CHECK_MESSAGE( + (vector1 * 2) == Vector3i(8, 10, 18), + "Vector3i multiplication with integers should give exact results."); + CHECK_MESSAGE( + (vector1 / 2) == Vector3i(2, 2, 4), + "Vector3i division with integers should give exact results."); + + CHECK_MESSAGE( + ((Vector3)vector1) == Vector3(4, 5, 9), + "Vector3i cast to Vector3 should work as expected."); + CHECK_MESSAGE( + ((Vector3)vector2) == Vector3(1, 2, 3), + "Vector3i cast to Vector3 should work as expected."); + CHECK_MESSAGE( + Vector3i(Vector3(1.1, 2.9, 3.9)) == Vector3i(1, 2, 3), + "Vector3i constructed from Vector3 should work as expected."); +} + +TEST_CASE("[Vector3i] Abs and sign methods") { + const Vector3i vector1 = Vector3i(1, 3, 5); + const Vector3i vector2 = Vector3i(1, -3, -5); + CHECK_MESSAGE( + vector1.abs() == vector1, + "Vector3i abs should work as expected."); + CHECK_MESSAGE( + vector2.abs() == vector1, + "Vector3i abs should work as expected."); + + CHECK_MESSAGE( + vector1.sign() == Vector3i(1, 1, 1), + "Vector3i sign should work as expected."); + CHECK_MESSAGE( + vector2.sign() == Vector3i(1, -1, -1), + "Vector3i sign should work as expected."); +} +} // namespace TestVector3i + +#endif // TEST_VECTOR3I_H diff --git a/tests/test_class_db.h b/tests/core/object/test_class_db.h index 4b058a4c67..e4145c8408 100644 --- a/tests/test_class_db.h +++ b/tests/core/object/test_class_db.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,14 +31,9 @@ #ifndef TEST_CLASS_DB_H #define TEST_CLASS_DB_H -#include "core/register_core_types.h" - +#include "core/core_bind.h" #include "core/core_constants.h" -#include "core/os/os.h" -#include "core/string/string_name.h" -#include "core/string/ustring.h" -#include "core/templates/ordered_hash_map.h" -#include "core/variant/variant.h" +#include "core/object/class_db.h" #include "tests/test_macros.h" diff --git a/tests/test_method_bind.h b/tests/core/object/test_method_bind.h index 879e7949e2..350a08b6e2 100644 --- a/tests/test_method_bind.h +++ b/tests/core/object/test_method_bind.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,10 +35,6 @@ #include "tests/test_macros.h" -#include <inttypes.h> -#include <stdio.h> -#include <wchar.h> - namespace TestMethodBind { class MethodBindTester : public Object { @@ -55,9 +51,15 @@ public: TEST_METHODRC, TEST_METHODRC_ARGS, TEST_METHOD_DEFARGS, + TEST_METHOD_OBJECT_CAST, TEST_MAX }; + class ObjectSubclass : public Object { + public: + int value = 1; + }; + int test_num = 0; bool test_valid[TEST_MAX]; @@ -102,6 +104,10 @@ public: test_valid[TEST_METHOD_DEFARGS] = p_arg1 == 1 && p_arg2 == 2 && p_arg3 == 3 && p_arg4 == 4 && p_arg5 == 5; //temporary } + void test_method_object_cast(ObjectSubclass *p_object) { + test_valid[TEST_METHOD_OBJECT_CAST] = p_object->value == 1; + } + static void _bind_methods() { ClassDB::bind_method(D_METHOD("test_method"), &MethodBindTester::test_method); ClassDB::bind_method(D_METHOD("test_method_args"), &MethodBindTester::test_method_args); @@ -112,6 +118,7 @@ public: ClassDB::bind_method(D_METHOD("test_methodrc"), &MethodBindTester::test_methodrc); ClassDB::bind_method(D_METHOD("test_methodrc_args"), &MethodBindTester::test_methodrc_args); ClassDB::bind_method(D_METHOD("test_method_default_args"), &MethodBindTester::test_method_default_args, DEFVAL(9) /* wrong on purpose */, DEFVAL(4), DEFVAL(5)); + ClassDB::bind_method(D_METHOD("test_method_object_cast", "object"), &MethodBindTester::test_method_object_cast); } virtual void run_tests() { @@ -138,6 +145,10 @@ public: test_valid[TEST_METHODRC_ARGS] = int(call("test_methodrc_args", test_num)) == test_num && test_valid[TEST_METHODRC_ARGS]; call("test_method_default_args", 1, 2, 3, 4); + + ObjectSubclass *obj = memnew(ObjectSubclass); + call("test_method_object_cast", obj); + memdelete(obj); } }; @@ -156,6 +167,7 @@ TEST_CASE("[MethodBind] check all method binds") { CHECK(mbt->test_valid[MethodBindTester::TEST_METHODRC]); CHECK(mbt->test_valid[MethodBindTester::TEST_METHODRC_ARGS]); CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD_DEFARGS]); + CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD_OBJECT_CAST]); memdelete(mbt); } diff --git a/tests/test_object.h b/tests/core/object/test_object.h index 8cb7116a20..f9158eccec 100644 --- a/tests/test_object.h +++ b/tests/core/object/test_object.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,9 +32,11 @@ #define TEST_OBJECT_H #include "core/core_string_names.h" +#include "core/object/class_db.h" #include "core/object/object.h" +#include "core/object/script_language.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" // Declared in global namespace because of GDCLASS macro warning (Windows): // "Unqualified friend declaration referring to type outside of the nearest enclosing namespace diff --git a/tests/test_node_path.h b/tests/core/string/test_node_path.h index f30fe53c5a..d2de766889 100644 --- a/tests/test_node_path.h +++ b/tests/core/string/test_node_path.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "core/string/node_path.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestNodePath { diff --git a/tests/test_string.h b/tests/core/string/test_string.h index 28d1089d2f..bf78298450 100644 --- a/tests/test_string.h +++ b/tests/core/string/test_string.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,23 +31,16 @@ #ifndef TEST_STRING_H #define TEST_STRING_H -#include <inttypes.h> -#include <stdio.h> -#include <wchar.h> - -#include "core/io/ip_address.h" -#include "core/os/main_loop.h" -#include "core/os/os.h" #include "core/string/ustring.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" namespace TestString { int u32scmp(const char32_t *l, const char32_t *r) { - for (; *l == *r && *l && *r; l++, r++) + for (; *l == *r && *l && *r; l++, r++) { ; + } return *l - *r; } @@ -165,10 +158,10 @@ TEST_CASE("[String] Invalid UTF8") { String s; bool err = s.parse_utf8((const char *)u8str); CHECK(err); - CHECK(s == String()); + CHECK(s.is_empty()); CharString cs = (const char *)u8str; - CHECK(String::utf8(cs) == String()); + CHECK(String::utf8(cs).is_empty()); ERR_PRINT_ON } @@ -178,10 +171,10 @@ TEST_CASE("[String] Invalid UTF16") { String s; bool err = s.parse_utf16(u16str); CHECK(err); - CHECK(s == String()); + CHECK(s.is_empty()); Char16String cs = u16str; - CHECK(String::utf16(cs) == String()); + CHECK(String::utf16(cs).is_empty()); ERR_PRINT_ON } @@ -252,6 +245,19 @@ TEST_CASE("[String] Testing for empty string") { CHECK(String("").is_empty()); } +TEST_CASE("[String] Contains") { + String s = "C:\\Godot\\project\\string_test.tscn"; + CHECK(s.contains(":\\")); + CHECK(s.contains("Godot")); + CHECK(s.contains(String("project\\string_test"))); + CHECK(s.contains(String("\\string_test.tscn"))); + + CHECK(!s.contains("://")); + CHECK(!s.contains("Godoh")); + CHECK(!s.contains(String("project\\string test"))); + CHECK(!s.contains(String("\\char_test.tscn"))); +} + TEST_CASE("[String] Test chr") { CHECK(String::chr('H') == "H"); CHECK(String::chr(0x3012)[0] == 0x3012); @@ -363,11 +369,17 @@ TEST_CASE("[String] Number to string") { CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros. // String::num_real tests. + CHECK(String::num_real(1.0) == "1.0"); + CHECK(String::num_real(1.0, false) == "1"); + CHECK(String::num_real(9.9) == "9.9"); + CHECK(String::num_real(9.99) == "9.99"); + CHECK(String::num_real(9.999) == "9.999"); + CHECK(String::num_real(9.9999) == "9.9999"); CHECK(String::num_real(3.141593) == "3.141593"); CHECK(String::num_real(3.141) == "3.141"); // No trailing zeros. #ifdef REAL_T_IS_DOUBLE CHECK_MESSAGE(String::num_real(Math_PI) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double."); - CHECK_MESSAGE(String::num_real(3.1415f) == "3.14149999618530", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double)."); + CHECK_MESSAGE(String::num_real(3.1415f) == "3.1414999961853", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double) and no trailing zero."); #else CHECK_MESSAGE(String::num_real(Math_PI) == "3.141593", "Prints the appropriate amount of digits for real_t = float."); CHECK_MESSAGE(String::num_real(3.1415f) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float."); @@ -498,12 +510,6 @@ TEST_CASE("[String] Splitting") { } } -TEST_CASE("[String] Erasing") { - String s = "Josephine is such a cute girl!"; - s.erase(s.find("cute "), String("cute ").length()); - CHECK(s == "Josephine is such a girl!"); -} - struct test_27_data { char const *data; char const *part; @@ -885,7 +891,7 @@ TEST_CASE("[String] is_subsequence_of") { String a = "is subsequence of"; CHECK(String("sub").is_subsequence_of(a)); CHECK(!String("Sub").is_subsequence_of(a)); - CHECK(String("Sub").is_subsequence_ofi(a)); + CHECK(String("Sub").is_subsequence_ofn(a)); } TEST_CASE("[String] match") { @@ -1146,6 +1152,25 @@ TEST_CASE("[String] c-escape/unescape") { CHECK(s.c_escape().c_unescape() == s); } +TEST_CASE("[String] indent") { + static const char *input[] = { + "", + "aaa\nbbb", + "\tcontains\n\tindent", + "empty\n\nline", + }; + static const char *expected[] = { + "", + "\taaa\n\tbbb", + "\t\tcontains\n\t\tindent", + "\tempty\n\n\tline", + }; + + for (int i = 0; i < 3; i++) { + CHECK(String(input[i]).indent("\t") == expected[i]); + } +} + TEST_CASE("[String] dedent") { String s = " aaa\n bbb"; String t = "aaa\nbbb"; @@ -1453,6 +1478,24 @@ TEST_CASE("[String] Variant ptr indexed set") { CHECK_EQ(s, String("azcd")); } + +TEST_CASE("[Stress][String] Empty via ' == String()'") { + for (int i = 0; i < 100000; ++i) { + String str = "Hello World!"; + if (str.is_empty()) { + continue; + } + } +} + +TEST_CASE("[Stress][String] Empty via `is_empty()`") { + for (int i = 0; i < 100000; ++i) { + String str = "Hello World!"; + if (str.is_empty()) { + continue; + } + } +} } // namespace TestString #endif // TEST_STRING_H diff --git a/tests/test_translation.h b/tests/core/string/test_translation.h index 93c53bbbc9..85ac639bec 100644 --- a/tests/test_translation.h +++ b/tests/core/string/test_translation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,7 +39,8 @@ #include "editor/import/resource_importer_csv_translation.h" #endif -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" +#include "tests/test_utils.h" namespace TestTranslation { diff --git a/tests/test_command_queue.h b/tests/core/templates/test_command_queue.h index f0d4569942..0d016f5d06 100644 --- a/tests/test_command_queue.h +++ b/tests/core/templates/test_command_queue.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,12 +33,10 @@ #include "core/config/project_settings.h" #include "core/math/random_number_generator.h" -#include "core/os/mutex.h" #include "core/os/os.h" -#include "core/os/semaphore.h" #include "core/os/thread.h" #include "core/templates/command_queue_mt.h" -#include "test_macros.h" +#include "tests/test_macros.h" #if !defined(NO_THREADS) diff --git a/tests/test_list.h b/tests/core/templates/test_list.h index 52d5edff70..49da0b8aad 100644 --- a/tests/test_list.h +++ b/tests/core/templates/test_list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_local_vector.h b/tests/core/templates/test_local_vector.h index eff2a16abc..b2464c3914 100644 --- a/tests/test_local_vector.h +++ b/tests/core/templates/test_local_vector.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +37,17 @@ namespace TestLocalVector { +TEST_CASE("[LocalVector] List Initialization.") { + LocalVector<int> vector{ 0, 1, 2, 3, 4 }; + + CHECK(vector.size() == 5); + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + TEST_CASE("[LocalVector] Push Back.") { LocalVector<int> vector; vector.push_back(0); @@ -84,25 +95,25 @@ TEST_CASE("[LocalVector] Remove.") { vector.push_back(3); vector.push_back(4); - vector.remove(0); + vector.remove_at(0); CHECK(vector[0] == 1); CHECK(vector[1] == 2); CHECK(vector[2] == 3); CHECK(vector[3] == 4); - vector.remove(2); + vector.remove_at(2); CHECK(vector[0] == 1); CHECK(vector[1] == 2); CHECK(vector[2] == 4); - vector.remove(1); + vector.remove_at(1); CHECK(vector[0] == 1); CHECK(vector[1] == 4); - vector.remove(0); + vector.remove_at(0); CHECK(vector[0] == 4); } @@ -117,7 +128,7 @@ TEST_CASE("[LocalVector] Remove Unordered.") { CHECK(vector.size() == 5); - vector.remove_unordered(0); + vector.remove_at_unordered(0); CHECK(vector.size() == 4); @@ -128,7 +139,7 @@ TEST_CASE("[LocalVector] Remove Unordered.") { CHECK(vector.find(4) != -1); // Now the vector is no more ordered. - vector.remove_unordered(vector.find(3)); + vector.remove_at_unordered(vector.find(3)); CHECK(vector.size() == 3); @@ -137,7 +148,7 @@ TEST_CASE("[LocalVector] Remove Unordered.") { CHECK(vector.find(2) != -1); CHECK(vector.find(4) != -1); - vector.remove_unordered(vector.find(2)); + vector.remove_at_unordered(vector.find(2)); CHECK(vector.size() == 2); @@ -145,7 +156,7 @@ TEST_CASE("[LocalVector] Remove Unordered.") { CHECK(vector.find(1) != -1); CHECK(vector.find(4) != -1); - vector.remove_unordered(vector.find(4)); + vector.remove_at_unordered(vector.find(4)); CHECK(vector.size() == 1); @@ -153,7 +164,7 @@ TEST_CASE("[LocalVector] Remove Unordered.") { CHECK(vector.find(1) != -1); // Remove the last one. - vector.remove_unordered(0); + vector.remove_at_unordered(0); CHECK(vector.is_empty()); CHECK(vector.size() == 0); @@ -193,9 +204,9 @@ TEST_CASE("[LocalVector] Size / Resize / Reserve.") { // Capacity is supposed to change only when the size increase. CHECK(vector.get_capacity() >= 10); - vector.remove(0); - vector.remove(0); - vector.remove(0); + vector.remove_at(0); + vector.remove_at(0); + vector.remove_at(0); CHECK(vector.size() == 2); // Capacity is supposed to change only when the size increase. diff --git a/tests/test_lru.h b/tests/core/templates/test_lru.h index 2802754729..354f53e164 100644 --- a/tests/test_lru.h +++ b/tests/core/templates/test_lru.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #define TEST_LRU_H #include "core/templates/lru.h" -#include "core/templates/vector.h" #include "tests/test_macros.h" diff --git a/tests/test_oa_hash_map.cpp b/tests/core/templates/test_oa_hash_map.cpp index 904c01642d..87bf9feb83 100644 --- a/tests/test_oa_hash_map.cpp +++ b/tests/core/templates/test_oa_hash_map.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,7 +55,10 @@ struct CountedItem { count++; } - CountedItem &operator=(const CountedItem &p_other) = default; + void operator=(const CountedItem &p_other) { + id = p_other.id; + count++; + } ~CountedItem() { CRASH_COND(destroyed); diff --git a/tests/test_oa_hash_map.h b/tests/core/templates/test_oa_hash_map.h index 9745802cc0..d4b72af2ac 100644 --- a/tests/test_oa_hash_map.h +++ b/tests/core/templates/test_oa_hash_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_OA_HASH_MAP_H #define TEST_OA_HASH_MAP_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestOAHashMap { diff --git a/tests/test_ordered_hash_map.h b/tests/core/templates/test_ordered_hash_map.h index fbaaa224cf..08c5c9b72a 100644 --- a/tests/test_ordered_hash_map.h +++ b/tests/core/templates/test_ordered_hash_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,7 @@ #ifndef TEST_ORDERED_HASH_MAP_H #define TEST_ORDERED_HASH_MAP_H -#include "core/os/os.h" #include "core/templates/ordered_hash_map.h" -#include "core/templates/pair.h" -#include "core/templates/vector.h" #include "tests/test_macros.h" diff --git a/tests/test_paged_array.h b/tests/core/templates/test_paged_array.h index 7efd3799f3..86cf3a2dfc 100644 --- a/tests/test_paged_array.h +++ b/tests/core/templates/test_paged_array.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_vector.h b/tests/core/templates/test_vector.h index bfdf389aa7..f27d6a332e 100644 --- a/tests/test_vector.h +++ b/tests/core/templates/test_vector.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +37,17 @@ namespace TestVector { +TEST_CASE("[Vector] List initialization") { + Vector<int> vector{ 0, 1, 2, 3, 4 }; + + CHECK(vector.size() == 5); + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + TEST_CASE("[Vector] Push back and append") { Vector<int> vector; vector.push_back(0); @@ -129,7 +140,7 @@ TEST_CASE("[Vector] Fill large array and modify it") { CHECK(vector[200] == 0); CHECK(vector[499'999] == 0x60d07); CHECK(vector[999'999] == 0x60d07); - vector.remove(200); + vector.remove_at(200); CHECK(vector[200] == 0x60d07); vector.clear(); @@ -145,7 +156,7 @@ TEST_CASE("[Vector] Copy creation") { vector.push_back(4); Vector<int> vector_other = Vector<int>(vector); - vector_other.remove(0); + vector_other.remove_at(0); CHECK(vector_other[0] == 1); CHECK(vector_other[1] == 2); CHECK(vector_other[2] == 3); @@ -168,7 +179,7 @@ TEST_CASE("[Vector] Duplicate") { vector.push_back(4); Vector<int> vector_other = vector.duplicate(); - vector_other.remove(0); + vector_other.remove_at(0); CHECK(vector_other[0] == 1); CHECK(vector_other[1] == 2); CHECK(vector_other[2] == 3); @@ -238,7 +249,7 @@ TEST_CASE("[Vector] To byte array") { CHECK(byte_array[15] == 59); } -TEST_CASE("[Vector] Subarray") { +TEST_CASE("[Vector] Slice") { Vector<int> vector; vector.push_back(0); vector.push_back(1); @@ -246,27 +257,42 @@ TEST_CASE("[Vector] Subarray") { vector.push_back(3); vector.push_back(4); - Vector<int> subarray1 = vector.subarray(1, 2); - CHECK(subarray1.size() == 2); - CHECK(subarray1[0] == 1); - CHECK(subarray1[1] == 2); - - Vector<int> subarray2 = vector.subarray(1, -1); - CHECK(subarray2.size() == 4); - CHECK(subarray2[0] == 1); - CHECK(subarray2[1] == 2); - CHECK(subarray2[2] == 3); - CHECK(subarray2[3] == 4); - - Vector<int> subarray3 = vector.subarray(-2, -1); - CHECK(subarray3.size() == 2); - CHECK(subarray3[0] == 3); - CHECK(subarray3[1] == 4); - - Vector<int> subarray4 = vector.subarray(-3, 3); - CHECK(subarray4.size() == 2); - CHECK(subarray4[0] == 2); - CHECK(subarray4[1] == 3); + Vector<int> slice0 = vector.slice(0, 0); + CHECK(slice0.size() == 0); + + Vector<int> slice1 = vector.slice(1, 3); + CHECK(slice1.size() == 2); + CHECK(slice1[0] == 1); + CHECK(slice1[1] == 2); + + Vector<int> slice2 = vector.slice(1, -1); + CHECK(slice2.size() == 3); + CHECK(slice2[0] == 1); + CHECK(slice2[1] == 2); + CHECK(slice2[2] == 3); + + Vector<int> slice3 = vector.slice(3); + CHECK(slice3.size() == 2); + CHECK(slice3[0] == 3); + CHECK(slice3[1] == 4); + + Vector<int> slice4 = vector.slice(2, -2); + CHECK(slice4.size() == 1); + CHECK(slice4[0] == 2); + + Vector<int> slice5 = vector.slice(-2); + CHECK(slice5.size() == 2); + CHECK(slice5[0] == 3); + CHECK(slice5[1] == 4); + + Vector<int> slice6 = vector.slice(2, 42); + CHECK(slice6.size() == 3); + CHECK(slice6[0] == 2); + CHECK(slice6[1] == 3); + CHECK(slice6[2] == 4); + + Vector<int> slice7 = vector.slice(5, 1); + CHECK(slice7.size() == 0); } TEST_CASE("[Vector] Find, has") { @@ -302,7 +328,7 @@ TEST_CASE("[Vector] Find, has") { CHECK(!vector.has(5)); } -TEST_CASE("[Vector] Remove") { +TEST_CASE("[Vector] Remove at") { Vector<int> vector; vector.push_back(0); vector.push_back(1); @@ -310,30 +336,30 @@ TEST_CASE("[Vector] Remove") { vector.push_back(3); vector.push_back(4); - vector.remove(0); + vector.remove_at(0); CHECK(vector[0] == 1); CHECK(vector[1] == 2); CHECK(vector[2] == 3); CHECK(vector[3] == 4); - vector.remove(2); + vector.remove_at(2); CHECK(vector[0] == 1); CHECK(vector[1] == 2); CHECK(vector[2] == 4); - vector.remove(1); + vector.remove_at(1); CHECK(vector[0] == 1); CHECK(vector[1] == 4); - vector.remove(0); + vector.remove_at(0); CHECK(vector[0] == 4); } -TEST_CASE("[Vector] Remove and find") { +TEST_CASE("[Vector] Remove at and find") { Vector<int> vector; vector.push_back(0); vector.push_back(1); @@ -343,7 +369,7 @@ TEST_CASE("[Vector] Remove and find") { CHECK(vector.size() == 5); - vector.remove(0); + vector.remove_at(0); CHECK(vector.size() == 4); @@ -353,7 +379,7 @@ TEST_CASE("[Vector] Remove and find") { CHECK(vector.find(3) != -1); CHECK(vector.find(4) != -1); - vector.remove(vector.find(3)); + vector.remove_at(vector.find(3)); CHECK(vector.size() == 3); @@ -362,7 +388,7 @@ TEST_CASE("[Vector] Remove and find") { CHECK(vector.find(2) != -1); CHECK(vector.find(4) != -1); - vector.remove(vector.find(2)); + vector.remove_at(vector.find(2)); CHECK(vector.size() == 2); @@ -370,14 +396,14 @@ TEST_CASE("[Vector] Remove and find") { CHECK(vector.find(1) != -1); CHECK(vector.find(4) != -1); - vector.remove(vector.find(4)); + vector.remove_at(vector.find(4)); CHECK(vector.size() == 1); CHECK(vector.find(4) == -1); CHECK(vector.find(1) != -1); - vector.remove(0); + vector.remove_at(0); CHECK(vector.is_empty()); CHECK(vector.size() == 0); @@ -412,9 +438,9 @@ TEST_CASE("[Vector] Size, resize, reserve") { CHECK(vector.size() == 5); - vector.remove(0); - vector.remove(0); - vector.remove(0); + vector.remove_at(0); + vector.remove_at(0); + vector.remove_at(0); CHECK(vector.size() == 2); diff --git a/tests/test_crypto.h b/tests/core/test_crypto.h index 8da8c75544..ce4edc71ae 100644 --- a/tests/test_crypto.h +++ b/tests/core/test_crypto.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,6 @@ #include "core/crypto/crypto.h" #include "tests/test_macros.h" -#include <stdio.h> namespace TestCrypto { diff --git a/tests/test_hashing_context.h b/tests/core/test_hashing_context.h index 728a5f2cfa..4795d24103 100644 --- a/tests/test_hashing_context.h +++ b/tests/core/test_hashing_context.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_time.h b/tests/core/test_time.h index 28f1cb2f20..903ca9c001 100644 --- a/tests/test_time.h +++ b/tests/core/test_time.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_array.h b/tests/core/variant/test_array.h index 05b4eaea2a..6093048307 100644 --- a/tests/test_array.h +++ b/tests/core/variant/test_array.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,7 @@ #ifndef TEST_ARRAY_H #define TEST_ARRAY_H -#include "core/object/class_db.h" -#include "core/object/script_language.h" -#include "core/templates/hashfuncs.h" -#include "core/templates/vector.h" #include "core/variant/array.h" -#include "core/variant/container_type_validate.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" #include "tests/test_tools.h" @@ -135,20 +129,20 @@ TEST_CASE("[Array] has() and count()") { CHECK(arr.count(2) == 0); } -TEST_CASE("[Array] remove()") { +TEST_CASE("[Array] remove_at()") { Array arr; arr.push_back(1); arr.push_back(2); - arr.remove(0); + arr.remove_at(0); CHECK(arr.size() == 1); CHECK(int(arr[0]) == 2); - arr.remove(0); + arr.remove_at(0); CHECK(arr.size() == 0); - // The array is now empty; try to use `remove()` again. + // The array is now empty; try to use `remove_at()` again. // Normally, this prints an error message so we silence it. ERR_PRINT_OFF; - arr.remove(0); + arr.remove_at(0); ERR_PRINT_ON; CHECK(arr.size() == 0); @@ -252,6 +246,62 @@ TEST_CASE("[Array] max() and min()") { CHECK(min == 2); } +TEST_CASE("[Array] slice()") { + Array array; + array.push_back(0); + array.push_back(1); + array.push_back(2); + array.push_back(3); + array.push_back(4); + + Array slice0 = array.slice(0, 0); + CHECK(slice0.size() == 0); + + Array slice1 = array.slice(1, 3); + CHECK(slice1.size() == 2); + CHECK(slice1[0] == Variant(1)); + CHECK(slice1[1] == Variant(2)); + + Array slice2 = array.slice(1, -1); + CHECK(slice2.size() == 3); + CHECK(slice2[0] == Variant(1)); + CHECK(slice2[1] == Variant(2)); + CHECK(slice2[2] == Variant(3)); + + Array slice3 = array.slice(3); + CHECK(slice3.size() == 2); + CHECK(slice3[0] == Variant(3)); + CHECK(slice3[1] == Variant(4)); + + Array slice4 = array.slice(2, -2); + CHECK(slice4.size() == 1); + CHECK(slice4[0] == Variant(2)); + + Array slice5 = array.slice(-2); + CHECK(slice5.size() == 2); + CHECK(slice5[0] == Variant(3)); + CHECK(slice5[1] == Variant(4)); + + Array slice6 = array.slice(2, 42); + CHECK(slice6.size() == 3); + CHECK(slice6[0] == Variant(2)); + CHECK(slice6[1] == Variant(3)); + CHECK(slice6[2] == Variant(4)); + + Array slice7 = array.slice(4, 0, -2); + CHECK(slice7.size() == 2); + CHECK(slice7[0] == Variant(4)); + CHECK(slice7[1] == Variant(2)); + + ERR_PRINT_OFF; + Array slice8 = array.slice(4, 1); + CHECK(slice8.size() == 0); + + Array slice9 = array.slice(3, -4); + CHECK(slice9.size() == 0); + ERR_PRINT_ON; +} + TEST_CASE("[Array] Duplicate array") { // a = [1, [2, 2], {3: 3}] Array a = build_array(1, build_array(2, 2), build_dictionary(3, 3)); diff --git a/tests/test_dictionary.h b/tests/core/variant/test_dictionary.h index 64d1d68e21..729035919d 100644 --- a/tests/test_dictionary.h +++ b/tests/core/variant/test_dictionary.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,7 @@ #ifndef TEST_DICTIONARY_H #define TEST_DICTIONARY_H -#include "core/templates/ordered_hash_map.h" -#include "core/templates/safe_refcount.h" #include "core/variant/dictionary.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" namespace TestDictionary { @@ -199,7 +196,7 @@ TEST_CASE("[Dictionary] Duplicate dictionary") { Dictionary shallow_d = d.duplicate(false); CHECK_MESSAGE(shallow_d.id() != d.id(), "Should create a new array"); CHECK_MESSAGE(Dictionary(shallow_d[1]).id() == Dictionary(d[1]).id(), "Should keep nested dictionary"); - CHECK_MESSAGE(Array(shallow_d[2]).id() == Array(d[2]).id(), "Should keep nested array"); + CHECK_MESSAGE(Array(shallow_d[k2]).id() == Array(d[k2]).id(), "Should keep nested array"); CHECK_EQ(shallow_d, d); shallow_d[0] = 0; CHECK_NE(shallow_d, d); diff --git a/tests/test_variant.h b/tests/core/variant/test_variant.h index 0d16fa092c..916686d7c1 100644 --- a/tests/test_variant.h +++ b/tests/core/variant/test_variant.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/scene/test_animation.h b/tests/scene/test_animation.h new file mode 100644 index 0000000000..9199713fd9 --- /dev/null +++ b/tests/scene/test_animation.h @@ -0,0 +1,314 @@ +/*************************************************************************/ +/* test_animation.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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_ANIMATION_H +#define TEST_ANIMATION_H + +#include "scene/resources/animation.h" + +#include "tests/test_macros.h" + +namespace TestAnimation { + +TEST_CASE("[Animation] Empty animation getters") { + const Ref<Animation> animation = memnew(Animation); + + CHECK(Math::is_equal_approx(animation->get_length(), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->get_step(), real_t(0.1))); +} + +TEST_CASE("[Animation] Create value track") { + // This creates an animation that makes the node "Enemy" move to the right by + // 100 pixels in 0.5 seconds. + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_VALUE); + CHECK(track_index == 0); + animation->track_set_path(track_index, NodePath("Enemy:position:x")); + animation->track_insert_key(track_index, 0.0, 0); + animation->track_insert_key(track_index, 0.5, 100); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + CHECK(int(animation->track_get_key_value(0, 0)) == 0); + CHECK(int(animation->track_get_key_value(0, 1)) == 100); + + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, -0.2), 0.0)); + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, 0.0), 0.0)); + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, 0.2), 40.0)); + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, 0.4), 80.0)); + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, 0.5), 100.0)); + CHECK(Math::is_equal_approx(animation->value_track_interpolate(0, 0.6), 100.0)); + + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 0), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 1), real_t(1.0))); + + ERR_PRINT_OFF; + // Nonexistent keys. + CHECK(animation->track_get_key_value(0, 2).is_null()); + CHECK(animation->track_get_key_value(0, -1).is_null()); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 2), real_t(-1.0))); + // Nonexistent track (and keys). + CHECK(animation->track_get_key_value(1, 0).is_null()); + CHECK(animation->track_get_key_value(1, 1).is_null()); + CHECK(animation->track_get_key_value(1, 2).is_null()); + CHECK(animation->track_get_key_value(1, -1).is_null()); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(1, 0), real_t(-1.0))); + + // This is a value track, so the methods below should return errors. + CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(Math::is_zero_approx(animation->bezier_track_interpolate(0, 0.0))); + CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + ERR_PRINT_ON; +} + +TEST_CASE("[Animation] Create 3D position track") { + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_POSITION_3D); + animation->track_set_path(track_index, NodePath("Enemy:position")); + animation->position_track_insert_key(track_index, 0.0, Vector3(0, 1, 2)); + animation->position_track_insert_key(track_index, 0.5, Vector3(3.5, 4, 5)); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + CHECK(Vector3(animation->track_get_key_value(0, 0)).is_equal_approx(Vector3(0, 1, 2))); + CHECK(Vector3(animation->track_get_key_value(0, 1)).is_equal_approx(Vector3(3.5, 4, 5))); + + Vector3 r_interpolation; + + CHECK(animation->position_track_interpolate(0, -0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2))); + + CHECK(animation->position_track_interpolate(0, 0.0, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2))); + + CHECK(animation->position_track_interpolate(0, 0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(1.4, 2.2, 3.2))); + + CHECK(animation->position_track_interpolate(0, 0.4, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(2.8, 3.4, 4.4))); + + CHECK(animation->position_track_interpolate(0, 0.5, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5))); + + CHECK(animation->position_track_interpolate(0, 0.6, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5))); + + // 3D position tracks always use linear interpolation for performance reasons. + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 0), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 1), real_t(1.0))); + + // This is a 3D position track, so the methods below should return errors. + ERR_PRINT_OFF; + CHECK(animation->value_track_interpolate(0, 0.0).is_null()); + CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(Math::is_zero_approx(animation->bezier_track_interpolate(0, 0.0))); + CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + ERR_PRINT_ON; +} + +TEST_CASE("[Animation] Create 3D rotation track") { + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_ROTATION_3D); + animation->track_set_path(track_index, NodePath("Enemy:rotation")); + animation->rotation_track_insert_key(track_index, 0.0, Quaternion(Vector3(0, 1, 2))); + animation->rotation_track_insert_key(track_index, 0.5, Quaternion(Vector3(3.5, 4, 5))); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + CHECK(Quaternion(animation->track_get_key_value(0, 0)).is_equal_approx(Quaternion(Vector3(0, 1, 2)))); + CHECK(Quaternion(animation->track_get_key_value(0, 1)).is_equal_approx(Quaternion(Vector3(3.5, 4, 5)))); + + Quaternion r_interpolation; + + CHECK(animation->rotation_track_interpolate(0, -0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.403423, 0.259035, 0.73846, 0.47416))); + + CHECK(animation->rotation_track_interpolate(0, 0.0, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.403423, 0.259035, 0.73846, 0.47416))); + + CHECK(animation->rotation_track_interpolate(0, 0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.336182, 0.30704, 0.751515, 0.477425))); + + CHECK(animation->rotation_track_interpolate(0, 0.4, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.266585, 0.352893, 0.759303, 0.477344))); + + CHECK(animation->rotation_track_interpolate(0, 0.5, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.231055, 0.374912, 0.761204, 0.476048))); + + CHECK(animation->rotation_track_interpolate(0, 0.6, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Quaternion(0.231055, 0.374912, 0.761204, 0.476048))); + + // 3D rotation tracks always use linear interpolation for performance reasons. + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 0), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 1), real_t(1.0))); + + // This is a 3D rotation track, so the methods below should return errors. + ERR_PRINT_OFF; + CHECK(animation->value_track_interpolate(0, 0.0).is_null()); + CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(Math::is_zero_approx(animation->bezier_track_interpolate(0, 0.0))); + CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + ERR_PRINT_ON; +} + +TEST_CASE("[Animation] Create 3D scale track") { + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_SCALE_3D); + animation->track_set_path(track_index, NodePath("Enemy:scale")); + animation->scale_track_insert_key(track_index, 0.0, Vector3(0, 1, 2)); + animation->scale_track_insert_key(track_index, 0.5, Vector3(3.5, 4, 5)); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + CHECK(Vector3(animation->track_get_key_value(0, 0)).is_equal_approx(Vector3(0, 1, 2))); + CHECK(Vector3(animation->track_get_key_value(0, 1)).is_equal_approx(Vector3(3.5, 4, 5))); + + Vector3 r_interpolation; + + CHECK(animation->scale_track_interpolate(0, -0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2))); + + CHECK(animation->scale_track_interpolate(0, 0.0, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2))); + + CHECK(animation->scale_track_interpolate(0, 0.2, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(1.4, 2.2, 3.2))); + + CHECK(animation->scale_track_interpolate(0, 0.4, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(2.8, 3.4, 4.4))); + + CHECK(animation->scale_track_interpolate(0, 0.5, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5))); + + CHECK(animation->scale_track_interpolate(0, 0.6, &r_interpolation) == OK); + CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5))); + + // 3D scale tracks always use linear interpolation for performance reasons. + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 0), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 1), real_t(1.0))); + + // This is a 3D scale track, so the methods below should return errors. + ERR_PRINT_OFF; + CHECK(animation->value_track_interpolate(0, 0.0).is_null()); + CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(Math::is_zero_approx(animation->bezier_track_interpolate(0, 0.0))); + CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + ERR_PRINT_ON; +} + +TEST_CASE("[Animation] Create blend shape track") { + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_BLEND_SHAPE); + animation->track_set_path(track_index, NodePath("Enemy:scale")); + // Negative values for blend shapes should work as expected. + animation->blend_shape_track_insert_key(track_index, 0.0, -1.0); + animation->blend_shape_track_insert_key(track_index, 0.5, 1.0); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + + float r_blend = 0.0f; + + CHECK(animation->blend_shape_track_get_key(0, 0, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, -1.0f)); + + CHECK(animation->blend_shape_track_get_key(0, 1, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, 1.0f)); + + CHECK(animation->blend_shape_track_interpolate(0, -0.2, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, -1.0f)); + + CHECK(animation->blend_shape_track_interpolate(0, 0.0, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, -1.0f)); + + CHECK(animation->blend_shape_track_interpolate(0, 0.2, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, -0.2f)); + + CHECK(animation->blend_shape_track_interpolate(0, 0.4, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, 0.6f)); + + CHECK(animation->blend_shape_track_interpolate(0, 0.5, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, 1.0f)); + + CHECK(animation->blend_shape_track_interpolate(0, 0.6, &r_blend) == OK); + CHECK(Math::is_equal_approx(r_blend, 1.0f)); + + // Blend shape tracks always use linear interpolation for performance reasons. + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 0), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->track_get_key_transition(0, 1), real_t(1.0))); + + // This is a blend shape track, so the methods below should return errors. + ERR_PRINT_OFF; + CHECK(animation->value_track_interpolate(0, 0.0).is_null()); + CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(Math::is_zero_approx(animation->bezier_track_interpolate(0, 0.0))); + ERR_PRINT_ON; +} + +TEST_CASE("[Animation] Create Bezier track") { + Ref<Animation> animation = memnew(Animation); + const int track_index = animation->add_track(Animation::TYPE_BEZIER); + animation->track_set_path(track_index, NodePath("Enemy:scale")); + animation->bezier_track_insert_key(track_index, 0.0, -1.0, Vector2(-1, -1), Vector2(1, 1)); + animation->bezier_track_insert_key(track_index, 0.5, 1.0, Vector2(0, 1), Vector2(1, 0.5)); + + CHECK(animation->get_track_count() == 1); + CHECK(!animation->track_is_compressed(0)); + + CHECK(Math::is_equal_approx(animation->bezier_track_get_key_value(0, 0), real_t(-1.0))); + CHECK(Math::is_equal_approx(animation->bezier_track_get_key_value(0, 1), real_t(1.0))); + + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, -0.2), real_t(-1.0))); + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, 0.0), real_t(-1.0))); + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, 0.2), real_t(-0.76057207584381))); + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, 0.4), real_t(-0.39975279569626))); + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, 0.5), real_t(1.0))); + CHECK(Math::is_equal_approx(animation->bezier_track_interpolate(0, 0.6), real_t(1.0))); + + // This is a bezier track, so the methods below should return errors. + ERR_PRINT_OFF; + CHECK(animation->value_track_interpolate(0, 0.0).is_null()); + CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); + ERR_PRINT_ON; +} + +} // namespace TestAnimation + +#endif // TEST_ANIMATION_H diff --git a/tests/test_code_edit.h b/tests/scene/test_code_edit.h index 62235ed0ae..8bd35df107 100644 --- a/tests/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,12 +31,7 @@ #ifndef TEST_CODE_EDIT_H #define TEST_CODE_EDIT_H -#include "core/input/input_map.h" -#include "core/object/message_queue.h" -#include "core/os/keyboard.h" -#include "core/string/string_builder.h" #include "scene/gui/code_edit.h" -#include "scene/resources/default_theme/default_theme.h" #include "tests/test_macros.h" @@ -1109,7 +1104,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_key(idx) == "#"); CHECK(code_edit->get_delimiter_end_key(idx) == ""); - /* Check nested strings are handeled correctly. */ + /* Check nested strings are handled correctly. */ code_edit->set_text(" \n# # \n "); /* Check line above is not in string. */ @@ -1137,7 +1132,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER); CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER); - /* Check is in string with no column retruns true if entire line is comment excluding whitespace. */ + /* Check is in string with no column returns true if entire line is comment excluding whitespace. */ code_edit->set_text(" \n # # \n "); CHECK(code_edit->is_in_string(1) != -1); @@ -1200,7 +1195,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_key(idx) == "#"); CHECK(code_edit->get_delimiter_end_key(idx) == ""); - /* Check nested comments are handeled correctly. */ + /* Check nested comments are handled correctly. */ code_edit->set_text(" \n# # \n "); /* Check line above is not in comment. */ @@ -1228,7 +1223,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_position(2, 1) == OUTSIDE_DELIMETER); CHECK(code_edit->get_delimiter_end_position(2, 1) == OUTSIDE_DELIMETER); - /* Check is in comment with no column retruns true if entire line is comment excluding whitespace. */ + /* Check is in comment with no column returns true if entire line is comment excluding whitespace. */ code_edit->set_text(" \n # # \n "); CHECK(code_edit->is_in_comment(1) != -1); @@ -1496,7 +1491,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_key(idx) == "#"); CHECK(code_edit->get_delimiter_end_key(idx) == "#"); - /* Check is in string with no column retruns true if entire line is string excluding whitespace. */ + /* Check is in string with no column returns true if entire line is string excluding whitespace. */ code_edit->set_text(" \n # \n\n #\n "); CHECK(code_edit->is_in_string(1) != -1); CHECK(code_edit->is_in_string(2) != -1); @@ -1685,7 +1680,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_key(idx) == "#"); CHECK(code_edit->get_delimiter_end_key(idx) == "#"); - /* Check is in comment with no column retruns true if entire line is comment excluding whitespace. */ + /* Check is in comment with no column returns true if entire line is comment excluding whitespace. */ code_edit->set_text(" \n # \n\n #\n "); CHECK(code_edit->is_in_comment(1) != -1); CHECK(code_edit->is_in_comment(2) != -1); @@ -1751,7 +1746,7 @@ TEST_CASE("[SceneTree][CodeEdit] delimiters") { CHECK(code_edit->get_delimiter_start_key(idx) == "#"); CHECK(code_edit->get_delimiter_end_key(idx) == "#"); - /* Check is in comment with no column retruns true as inner delimiter should not be counted. */ + /* Check is in comment with no column returns true as inner delimiter should not be counted. */ CHECK(code_edit->is_in_comment(1) != -1); CHECK(code_edit->is_in_comment(2) != -1); CHECK(code_edit->is_in_comment(3) != -1); @@ -2337,6 +2332,20 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(2)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + // Indent with blank lines. + code_edit->set_text("line1\n\tline2\n\n\nline3"); + CHECK(code_edit->can_fold_line(0)); + for (int i = 1; i < 2; i++) { + CHECK_FALSE(code_edit->can_fold_line(i)); + code_edit->fold_line(i); + CHECK_FALSE(code_edit->is_line_folded(i)); + } + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + // Nested indents. code_edit->set_text("line1\n\tline2\n\t\tline3\nline4"); CHECK(code_edit->can_fold_line(0)); @@ -2413,7 +2422,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { for (int i = 1; i < code_edit->get_line_count(); i++) { CHECK_FALSE(code_edit->is_line_folded(i)); } - CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 6); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 5); // End of file. code_edit->set_text("line1\n\tline2"); @@ -2495,7 +2504,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { // Multiline blocks. code_edit->add_comment_delimiter("&", "&", false); - code_edit->set_text("&line1\n\tline2&"); + code_edit->set_text("&line1\n\tline2&\nline3"); CHECK(code_edit->can_fold_line(0)); CHECK_FALSE(code_edit->can_fold_line(1)); code_edit->fold_line(1); @@ -2503,7 +2512,17 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { code_edit->fold_line(0); CHECK(code_edit->is_line_folded(0)); CHECK_FALSE(code_edit->is_line_folded(1)); - CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Multiline comment before last line. + code_edit->set_text("&line1\nline2&\ntest"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); // Has to be full line. code_edit->set_text("test &line1\n\tline2&"); @@ -2559,7 +2578,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(1)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1); - // Non-indented comments/ strings. + // Non-indented comments/strings. // Single line code_edit->set_text("test\n\tline1\n#line1\n#line2\n\ttest"); CHECK(code_edit->can_fold_line(0)); @@ -2581,6 +2600,50 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(1)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4); + // Indent level 0->1, comment after lines + code_edit->set_text("line1\n\tline2\n#test"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(1)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Indent level 0->1, comment between lines + code_edit->set_text("line1\n#test\n\tline2\nline3"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(2); + CHECK_FALSE(code_edit->is_line_folded(2)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3); + + // Indent level 1->2, comment after lines + code_edit->set_text("\tline1\n\t\tline2\n#test"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(1)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Indent level 1->2, comment between lines + code_edit->set_text("\tline1\n#test\n\t\tline2\nline3"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(2); + CHECK_FALSE(code_edit->is_line_folded(2)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3); + // Multiline code_edit->set_text("test\n\tline1\n&line1\nline2&\n\ttest"); CHECK(code_edit->can_fold_line(0)); @@ -2678,18 +2741,18 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { /* Check typing inserts closing pair. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); CHECK(code_edit->get_line(0) == "[]"); /* Should first match and insert smaller key. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "''"); CHECK(code_edit->get_caret_column() == 1); /* Move out from centre, Should match and insert larger key. */ SEND_GUI_ACTION(code_edit, "ui_text_caret_right"); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "''''''"); CHECK(code_edit->get_caret_column() == 3); @@ -2698,31 +2761,77 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { CHECK(code_edit->get_line(0).is_empty()); /* If in between and typing close key should "skip". */ - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); CHECK(code_edit->get_line(0) == "[]"); CHECK(code_edit->get_caret_column() == 1); - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETRIGHT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETRIGHT); CHECK(code_edit->get_line(0) == "[]"); CHECK(code_edit->get_caret_column() == 2); /* If current is char and inserting a string, do not autocomplete. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_A); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::A); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "A'"); /* If in comment, do not complete. */ code_edit->add_comment_delimiter("#", ""); code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_NUMBERSIGN); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::NUMBERSIGN); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "#'"); /* If in string, and inserting string do not complete. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); - SEND_GUI_KEY_EVENT(code_edit, KEY_QUOTEDBL); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::QUOTEDBL); CHECK(code_edit->get_line(0) == "'\"'"); + + /* Wrap single line selection with brackets */ + code_edit->clear(); + code_edit->insert_text_at_caret("abc"); + code_edit->select_all(); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); + CHECK(code_edit->get_line(0) == "[abc]"); + + /* Caret should be after the last character of the single line selection */ + CHECK(code_edit->get_caret_column() == 4); + + /* Wrap multi line selection with brackets */ + code_edit->clear(); + code_edit->insert_text_at_caret("abc\nabc"); + code_edit->select_all(); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); + CHECK(code_edit->get_text() == "[abc\nabc]"); + + /* Caret should be after the last character of the multi line selection */ + CHECK(code_edit->get_caret_line() == 1); + CHECK(code_edit->get_caret_column() == 3); + + /* If inserted character is not a auto brace completion open key, replace selected text with the inserted character */ + code_edit->clear(); + code_edit->insert_text_at_caret("abc"); + code_edit->select_all(); + SEND_GUI_KEY_EVENT(code_edit, Key::KEY_1); + CHECK(code_edit->get_text() == "1"); + + /* If potential multichar and single brace completion is matched, it should wrap the single. */ + code_edit->clear(); + code_edit->insert_text_at_caret("\'\'abc"); + code_edit->select(0, 2, 0, 5); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); + CHECK(code_edit->get_text() == "\'\'\'abc\'"); + + /* If only the potential multichar brace completion is matched, it does not wrap or complete. */ + auto_brace_completion_pairs.erase("\'"); + code_edit->set_auto_brace_completion_pairs(auto_brace_completion_pairs); + CHECK_FALSE(code_edit->has_auto_brace_completion_open_key("\'")); + + code_edit->clear(); + code_edit->insert_text_at_caret("\'\'abc"); + code_edit->select(0, 2, 0, 5); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); + CHECK(code_edit->get_text() == "\'\'\'"); } SUBCASE("[CodeEdit] autocomplete") { @@ -2749,7 +2858,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { } SUBCASE("[CodeEdit] autocomplete request") { - SIGNAL_WATCH(code_edit, "request_code_completion"); + SIGNAL_WATCH(code_edit, "code_completion_requested"); code_edit->set_code_completion_enabled(true); Array signal_args; @@ -2757,13 +2866,13 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { /* Force request. */ code_edit->request_code_completion(); - SIGNAL_CHECK_FALSE("request_code_completion"); + SIGNAL_CHECK_FALSE("code_completion_requested"); code_edit->request_code_completion(true); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Manual request should force. */ SEND_GUI_ACTION(code_edit, "ui_text_completion_query"); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Insert prefix. */ TypedArray<String> completion_prefixes; @@ -2772,12 +2881,12 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { code_edit->insert_text_at_caret("."); code_edit->request_code_completion(); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Should work with space too. */ code_edit->insert_text_at_caret(" "); code_edit->request_code_completion(); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); /* Should work when complete ends with prefix. */ code_edit->clear(); @@ -2786,9 +2895,9 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { code_edit->update_code_completion_options(); code_edit->confirm_code_completion(); CHECK(code_edit->get_line(0) == "test."); - SIGNAL_CHECK("request_code_completion", signal_args); + SIGNAL_CHECK("code_completion_requested", signal_args); - SIGNAL_UNWATCH(code_edit, "request_code_completion"); + SIGNAL_UNWATCH(code_edit, "code_completion_requested"); } SUBCASE("[CodeEdit] autocomplete completion") { @@ -2867,7 +2976,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { SEND_GUI_ACTION(code_edit, "ui_down"); CHECK(code_edit->get_code_completion_selected_index() == 0); - SEND_GUI_KEY_EVENT(code_edit, KEY_T); + SEND_GUI_KEY_EVENT(code_edit, Key::T); CHECK(code_edit->get_code_completion_selected_index() == 0); SEND_GUI_ACTION(code_edit, "ui_left"); @@ -2881,14 +2990,14 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { Point2 caret_pos = code_edit->get_caret_draw_pos(); caret_pos.y -= code_edit->get_line_height(); - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_NONE); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::WHEEL_DOWN, MouseButton::NONE); CHECK(code_edit->get_code_completion_selected_index() == 1); - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_NONE); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::WHEEL_UP, MouseButton::NONE); CHECK(code_edit->get_code_completion_selected_index() == 0); /* Single click selects. */ - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::LEFT, MouseButton::MASK_LEFT); CHECK(code_edit->get_code_completion_selected_index() == 2); /* Double click inserts. */ @@ -3095,16 +3204,16 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") { code_edit->set_text("this is some text"); Point2 caret_pos = code_edit->get_caret_draw_pos(); - caret_pos.x += 55; - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE); + caret_pos.x += 58; + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::NONE, MouseButton::NONE); CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text"); SIGNAL_WATCH(code_edit, "symbol_validate"); #ifdef OSX_ENABLED - SEND_GUI_KEY_EVENT(code_edit, KEY_META); + SEND_GUI_KEY_EVENT(code_edit, Key::META); #else - SEND_GUI_KEY_EVENT(code_edit, KEY_CTRL); + SEND_GUI_KEY_EVENT(code_edit, Key::CTRL); #endif Array signal_args; @@ -3157,7 +3266,7 @@ TEST_CASE("[SceneTree][CodeEdit] Backspace delete") { code_edit->backspace(); CHECK(code_edit->get_line(0) == "backspace"); - /* Move caret up to the previous line on backspace if carret is at the first column. */ + /* Move caret up to the previous line on backspace if caret is at the first column. */ code_edit->set_text(""); code_edit->insert_text_at_caret("line 1\nline 2"); code_edit->set_caret_line(1); @@ -3172,7 +3281,7 @@ TEST_CASE("[SceneTree][CodeEdit] Backspace delete") { code_edit->insert_text_at_caret("line 1\nline 2\nline 3"); code_edit->select_all(); code_edit->backspace(); - CHECK(code_edit->get_text() == ""); + CHECK(code_edit->get_text().is_empty()); /* Backspace at the beginning without selection has no effect. */ code_edit->set_text(""); @@ -3185,6 +3294,55 @@ TEST_CASE("[SceneTree][CodeEdit] Backspace delete") { memdelete(code_edit); } +TEST_CASE("[SceneTree][CodeEdit] New Line") { + CodeEdit *code_edit = memnew(CodeEdit); + SceneTree::get_singleton()->get_root()->add_child(code_edit); + + /* Add a new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(13); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Split line with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == "test "); + CHECK(code_edit->get_line(1) == "new line"); + + /* Delete selection and split with new line. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "new line"); + + /* Blank new line below with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_blank"); + CHECK(code_edit->get_line(0) == "test new line"); + CHECK(code_edit->get_line(1) == ""); + + /* Blank new line above with selection should not split. */ + code_edit->set_text(""); + code_edit->insert_text_at_caret("test new line"); + code_edit->select(0, 0, 0, 5); + SEND_GUI_ACTION(code_edit, "ui_text_newline_above"); + CHECK(code_edit->get_line(0) == ""); + CHECK(code_edit->get_line(1) == "test new line"); + + memdelete(code_edit); +} + } // namespace TestCodeEdit #endif // TEST_CODE_EDIT_H diff --git a/tests/test_curve.h b/tests/scene/test_curve.h index e079905e35..0370ab15fd 100644 --- a/tests/test_curve.h +++ b/tests/scene/test_curve.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "scene/resources/curve.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestCurve { @@ -219,35 +219,33 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { TEST_CASE("[Curve2D] Linear sampling should return exact value") { Ref<Curve2D> curve = memnew(Curve2D); - int len = 2048; + real_t len = 2048.0; curve->add_point(Vector2(0, 0)); - curve->add_point(Vector2((float)len, 0)); + curve->add_point(Vector2(len, 0)); - float baked_length = curve->get_baked_length(); - CHECK((float)len == baked_length); + real_t baked_length = curve->get_baked_length(); + CHECK(len == baked_length); for (int i = 0; i < len; i++) { - float expected = (float)i; - Vector2 pos = curve->interpolate_baked(expected); - CHECK_MESSAGE(pos.x == expected, "interpolate_baked should return exact value"); + Vector2 pos = curve->interpolate_baked(i); + CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value"); } } TEST_CASE("[Curve3D] Linear sampling should return exact value") { Ref<Curve3D> curve = memnew(Curve3D); - int len = 2048; + real_t len = 2048.0; curve->add_point(Vector3(0, 0, 0)); - curve->add_point(Vector3((float)len, 0, 0)); + curve->add_point(Vector3(len, 0, 0)); - float baked_length = curve->get_baked_length(); - CHECK((float)len == baked_length); + real_t baked_length = curve->get_baked_length(); + CHECK(len == baked_length); for (int i = 0; i < len; i++) { - float expected = (float)i; - Vector3 pos = curve->interpolate_baked(expected); - CHECK_MESSAGE(pos.x == expected, "interpolate_baked should return exact value"); + Vector3 pos = curve->interpolate_baked(i); + CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value"); } } diff --git a/tests/test_gradient.h b/tests/scene/test_gradient.h index 8eaa6b2b64..b0e6128932 100644 --- a/tests/test_gradient.h +++ b/tests/scene/test_gradient.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,6 @@ #ifndef TEST_GRADIENT_H #define TEST_GRADIENT_H -#include "core/math/color.h" -#include "core/object/class_db.h" #include "scene/resources/gradient.h" #include "thirdparty/doctest/doctest.h" diff --git a/tests/test_gui.cpp b/tests/scene/test_gui.cpp index 0ec8aa78c4..cd5624b70c 100644 --- a/tests/test_gui.cpp +++ b/tests/scene/test_gui.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,29 +32,18 @@ #include "test_gui.h" -#include "core/io/image_loader.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "scene/2d/sprite_2d.h" #include "scene/gui/button.h" -#include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/panel.h" -#include "scene/gui/popup_menu.h" #include "scene/gui/progress_bar.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/spin_box.h" #include "scene/gui/tab_container.h" -#include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" -#include "scene/main/scene_tree.h" - -#include "scene/3d/camera_3d.h" -#include "scene/main/window.h" namespace TestGUI { @@ -80,7 +69,7 @@ public: label->set_position(Point2(80, 90)); label->set_size(Point2(170, 80)); - label->set_align(Label::ALIGN_FILL); + label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_FILL); label->set_text("There was once upon a time a beautiful unicorn that loved to play with little girls..."); frame->add_child(label); @@ -267,4 +256,4 @@ MainLoop *test() { } } // namespace TestGUI -#endif +#endif // _3D_DISABLED diff --git a/tests/test_gui.h b/tests/scene/test_gui.h index e5c40de7e8..a1807ed15c 100644 --- a/tests/test_gui.h +++ b/tests/scene/test_gui.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_GUI_H #define TEST_GUI_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestGUI { diff --git a/tests/test_path_3d.h b/tests/scene/test_path_3d.h index 9961ae6e97..78f4e97f03 100644 --- a/tests/test_path_3d.h +++ b/tests/scene/test_path_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #define TEST_PATH_3D_H #include "scene/3d/path_3d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_path_follow_2d.h b/tests/scene/test_path_follow_2d.h index 388b690060..abd12fe862 100644 --- a/tests/test_path_follow_2d.h +++ b/tests/scene/test_path_follow_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #define TEST_PATH_FOLLOW_2D_H #include "scene/2d/path_2d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_path_follow_3d.h b/tests/scene/test_path_follow_3d.h index b6b4c88222..9ffe49e3d6 100644 --- a/tests/test_path_follow_3d.h +++ b/tests/scene/test_path_follow_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,6 @@ #define TEST_PATH_FOLLOW_3D_H #include "scene/3d/path_3d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_physics_2d.cpp b/tests/servers/test_physics_2d.cpp index f6619db8fd..8b77458a33 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/servers/test_physics_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,6 @@ #include "test_physics_2d.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" -#include "scene/resources/texture.h" -#include "servers/display_server.h" #include "servers/physics_server_2d.h" #include "servers/rendering_server.h" @@ -201,10 +196,10 @@ protected: if (mb->is_pressed()) { Point2 p = mb->get_position(); - if (mb->get_button_index() == 1) { + if (mb->get_button_index() == MouseButton::LEFT) { ray_to = p; _do_ray_query(); - } else if (mb->get_button_index() == 2) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { ray_from = p; _do_ray_query(); } @@ -216,10 +211,10 @@ protected: if (mm.is_valid()) { Point2 p = mm->get_position(); - if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { ray_to = p; _do_ray_query(); - } else if (mm->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) { + } else if ((mm->get_button_mask() & MouseButton::MASK_RIGHT) != MouseButton::NONE) { ray_from = p; _do_ray_query(); } diff --git a/tests/test_physics_2d.h b/tests/servers/test_physics_2d.h index 966d49200a..b6c47574cd 100644 --- a/tests/test_physics_2d.h +++ b/tests/servers/test_physics_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_PHYSICS_2D_H #define TEST_PHYSICS_2D_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestPhysics2D { diff --git a/tests/test_physics_3d.cpp b/tests/servers/test_physics_3d.cpp index d839ae26b7..3d38b9d901 100644 --- a/tests/test_physics_3d.cpp +++ b/tests/servers/test_physics_3d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,12 +31,8 @@ #include "test_physics_3d.h" #include "core/math/convex_hull.h" -#include "core/math/math_funcs.h" +#include "core/math/geometry_3d.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" -#include "servers/display_server.h" #include "servers/physics_server_3d.h" #include "servers/rendering_server.h" @@ -249,12 +245,12 @@ protected: public: virtual void input_event(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & 4) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { ofs_y -= mm->get_relative().y / 200.0; ofs_x += mm->get_relative().x / 200.0; } - if (mm.is_valid() && mm->get_button_mask() & 1) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { real_t y = -mm->get_relative().y / 20.0; real_t x = mm->get_relative().x / 20.0; diff --git a/tests/test_physics_3d.h b/tests/servers/test_physics_3d.h index b6b66f350e..f618d0fb4f 100644 --- a/tests/test_physics_3d.h +++ b/tests/servers/test_physics_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_PHYSICS_H #define TEST_PHYSICS_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestPhysics3D { diff --git a/tests/test_render.cpp b/tests/servers/test_render.cpp index 21b4da9b3b..44403e3724 100644 --- a/tests/test_render.cpp +++ b/tests/servers/test_render.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,12 +31,7 @@ #include "test_render.h" #include "core/math/convex_hull.h" -#include "core/math/math_funcs.h" -#include "core/os/keyboard.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "servers/display_server.h" #include "servers/rendering_server.h" #define OBJECT_COUNT 50 diff --git a/tests/test_render.h b/tests/servers/test_render.h index 35bb383773..d5a3e01ee5 100644 --- a/tests/test_render.h +++ b/tests/servers/test_render.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef TEST_RENDER_H #define TEST_RENDER_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestRender { MainLoop *test(); } -#endif +#endif // TEST_RENDER_H diff --git a/tests/test_shader_lang.cpp b/tests/servers/test_shader_lang.cpp index 5598852f29..06e28212d2 100644 --- a/tests/test_shader_lang.cpp +++ b/tests/servers/test_shader_lang.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,8 @@ #include "test_shader_lang.h" -#include "core/io/file_access.h" #include "core/os/main_loop.h" #include "core/os/os.h" - -#include "core/string/print_string.h" -#include "scene/gui/control.h" -#include "scene/gui/text_edit.h" #include "servers/rendering/shader_language.h" typedef ShaderLanguage SL; @@ -216,9 +211,6 @@ static String dump_node_code(SL::Node *p_node, int p_level) { SL::ArrayNode *vnode = (SL::ArrayNode *)p_node; code = vnode->name; } break; - case SL::Node::TYPE_ARRAY_DECLARATION: { - // FIXME: Implement - } break; case SL::Node::TYPE_ARRAY_CONSTRUCT: { // FIXME: Implement } break; @@ -266,6 +258,8 @@ static String dump_node_code(SL::Node *p_node, int p_level) { } code += ")"; break; + case SL::OP_EMPTY: + break; default: { code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")"; break; @@ -344,12 +338,17 @@ MainLoop *test() { dt["fragment"].built_ins["ALBEDO"] = SL::TYPE_VEC3; dt["fragment"].can_discard = true; - Vector<StringName> rm; - rm.push_back("popo"); + Vector<SL::ModeInfo> rm; + rm.push_back({ "popo" }); Set<String> types; types.insert("spatial"); - Error err = sl.compile(code, dt, rm, ShaderLanguage::VaryingFunctionNames(), types, nullptr); + ShaderLanguage::ShaderCompileInfo info; + info.functions = dt; + info.render_modes = rm; + info.shader_types = types; + + Error err = sl.compile(code, info); if (err) { print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text()); diff --git a/tests/test_shader_lang.h b/tests/servers/test_shader_lang.h index 46a2e6af35..31e1bfbeea 100644 --- a/tests/test_shader_lang.h +++ b/tests/servers/test_shader_lang.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_SHADER_LANG_H #define TEST_SHADER_LANG_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestShaderLang { diff --git a/tests/test_text_server.h b/tests/servers/test_text_server.h index 4edffe3711..0a64237285 100644 --- a/tests/test_text_server.h +++ b/tests/servers/test_text_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -154,6 +154,212 @@ TEST_SUITE("[[TextServer]") { } } + SUBCASE("[TextServer] Text layout: Line break and align points") { + for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { + Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); + TEST_FAIL_COND(ts.is_null(), "Invalid TS interface."); + + RID font1 = ts->create_font(); + ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size); + RID font2 = ts->create_font(); + ts->font_set_data_ptr(font2, _font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size); + RID font3 = ts->create_font(); + ts->font_set_data_ptr(font3, _font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size); + + Vector<RID> font; + font.push_back(font1); + font.push_back(font2); + font.push_back(font3); + + { + String test = U"Test test long text long text\n"; + RID ctx = ts->create_shaped_text(); + TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + ts->shaped_text_update_justification_ops(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 30, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 4 || j == 9 || j == 14 || j == 19 || j == 24) { + TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + } else if (j == 29) { + TEST_FAIL_COND((soft || !space || !hard || virt || elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + ts->free(ctx); + } + + { + String test = U"الحمـد"; + RID ctx = ts->create_shaped_text(); + TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + TEST_FAIL_COND(gl_size != 6, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + + if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) { + ts->shaped_text_update_justification_ops(ctx); + + glyphs = ts->shaped_text_get_glyphs(ctx); + gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 6, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 1) { + TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + } + ts->free(ctx); + } + + { + String test = U"الحمـد الرياضي العربي"; + RID ctx = ts->create_shaped_text(); + TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 21, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 6 || j == 14) { + TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + + if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) { + ts->shaped_text_update_justification_ops(ctx); + + glyphs = ts->shaped_text_get_glyphs(ctx); + gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 23, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 7 || j == 16) { + TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + } else if (j == 3 || j == 9) { + TEST_FAIL_COND((soft || space || hard || !virt || !elo), "Invalid glyph flags."); + } else if (j == 18) { + TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + } + + ts->free(ctx); + } + + { + String test = U"เป็น ภาษา ราชการ และ ภาษา"; + RID ctx = ts->create_shaped_text(); + TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + ts->shaped_text_update_justification_ops(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 25, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 4 || j == 9 || j == 16 || j == 20) { + TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + ts->free(ctx); + } + + if (ts->has_feature(TextServer::FEATURE_BREAK_ITERATORS)) { + String test = U"เป็นภาษาราชการและภาษา"; + RID ctx = ts->create_shaped_text(); + TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed."); + bool ok = ts->shaped_text_add_string(ctx, test, font, 16); + TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); + ts->shaped_text_update_breaks(ctx); + ts->shaped_text_update_justification_ops(ctx); + + const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx); + int gl_size = ts->shaped_text_get_glyph_count(ctx); + + TEST_FAIL_COND(gl_size != 25, "Invalid glyph count."); + for (int j = 0; j < gl_size; j++) { + bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD; + bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT; + bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE; + bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL; + bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION; + if (j == 4 || j == 9 || j == 16 || j == 20) { + TEST_FAIL_COND((!soft || !space || hard || !virt || elo), "Invalid glyph flags."); + } else { + TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags."); + } + } + ts->free(ctx); + } + + for (int j = 0; j < font.size(); j++) { + ts->free(font[j]); + } + font.clear(); + } + } + SUBCASE("[TextServer] Text layout: Line breaking") { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i); diff --git a/tests/test_macros.cpp b/tests/test_macros.cpp index b0b28ab374..aa07f8211a 100644 --- a/tests/test_macros.cpp +++ b/tests/test_macros.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_macros.h b/tests/test_macros.h index 6968f9df1f..ed8a12f155 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,8 @@ #ifndef TEST_MACROS_H #define TEST_MACROS_H -#include "core/object/callable_method_pointer.h" -#include "core/object/class_db.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" +#include "core/input/input_map.h" +#include "core/object/message_queue.h" #include "core/variant/variant.h" // See documentation for doctest at: @@ -135,9 +133,9 @@ int register_test_command(String p_command, TestFunc p_function); // Utility macros to send an event actions to a given object // Requires Message Queue and InputMap to be setup. // SEND_GUI_ACTION - takes an object and a input map key. e.g SEND_GUI_ACTION(code_edit, "ui_text_newline"). -// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, KEY_A | KEY_MASK_CMD). +// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, Key::A | KeyModifierMask::CMD). // SEND_GUI_MOUSE_EVENT - takes an object, position, mouse button and mouse mask e.g SEND_GUI_MOUSE_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE); -// SEND_GUI_DOUBLE_CLICK - takes an object and a postion. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50)); +// SEND_GUI_DOUBLE_CLICK - takes an object and a position. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50)); #define SEND_GUI_ACTION(m_object, m_action) \ { \ @@ -174,7 +172,7 @@ int register_test_command(String p_command, TestFunc p_function); #define SEND_GUI_DOUBLE_CLICK(m_object, m_local_pos) \ { \ - _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_LEFT); \ + _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, MouseButton::LEFT); \ event->set_double_click(true); \ m_object->get_viewport()->push_input(event); \ MessageQueue::get_singleton()->flush(); \ @@ -194,7 +192,7 @@ int register_test_command(String p_command, TestFunc p_function); // // Use SIGNAL_DISCARD("signal_name") to discard records all of the given signal, use only in placed you don't need to check. // -// All signals are automaticaly discared between test/sub test cases. +// All signals are automatically discarded between test/sub test cases. class SignalWatcher : public Object { private: diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 341fb1af61..504b83c2b0 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,62 +30,68 @@ #include "test_main.h" -#include "core/templates/list.h" - -#include "test_aabb.h" -#include "test_array.h" -#include "test_astar.h" -#include "test_basis.h" -#include "test_class_db.h" -#include "test_code_edit.h" -#include "test_color.h" -#include "test_command_queue.h" -#include "test_config_file.h" -#include "test_crypto.h" -#include "test_curve.h" -#include "test_dictionary.h" -#include "test_expression.h" -#include "test_file_access.h" -#include "test_geometry_2d.h" -#include "test_geometry_3d.h" -#include "test_gradient.h" -#include "test_gui.h" -#include "test_hashing_context.h" -#include "test_image.h" -#include "test_json.h" -#include "test_list.h" -#include "test_local_vector.h" -#include "test_lru.h" -#include "test_marshalls.h" -#include "test_math.h" -#include "test_method_bind.h" -#include "test_node_path.h" -#include "test_oa_hash_map.h" -#include "test_object.h" -#include "test_ordered_hash_map.h" -#include "test_paged_array.h" -#include "test_path_3d.h" -#include "test_pck_packer.h" -#include "test_physics_2d.h" -#include "test_physics_3d.h" -#include "test_random_number_generator.h" -#include "test_rect2.h" -#include "test_render.h" -#include "test_resource.h" -#include "test_shader_lang.h" -#include "test_string.h" -#include "test_text_server.h" -#include "test_time.h" -#include "test_translation.h" -#include "test_validate_testing.h" -#include "test_variant.h" -#include "test_vector.h" -#include "test_xml_parser.h" +#include "tests/core/io/test_config_file.h" +#include "tests/core/io/test_file_access.h" +#include "tests/core/io/test_image.h" +#include "tests/core/io/test_json.h" +#include "tests/core/io/test_marshalls.h" +#include "tests/core/io/test_pck_packer.h" +#include "tests/core/io/test_resource.h" +#include "tests/core/io/test_xml_parser.h" +#include "tests/core/math/test_aabb.h" +#include "tests/core/math/test_astar.h" +#include "tests/core/math/test_basis.h" +#include "tests/core/math/test_color.h" +#include "tests/core/math/test_expression.h" +#include "tests/core/math/test_geometry_2d.h" +#include "tests/core/math/test_geometry_3d.h" +#include "tests/core/math/test_math.h" +#include "tests/core/math/test_random_number_generator.h" +#include "tests/core/math/test_rect2.h" +#include "tests/core/math/test_rect2i.h" +#include "tests/core/math/test_vector2.h" +#include "tests/core/math/test_vector2i.h" +#include "tests/core/math/test_vector3.h" +#include "tests/core/math/test_vector3i.h" +#include "tests/core/object/test_class_db.h" +#include "tests/core/object/test_method_bind.h" +#include "tests/core/object/test_object.h" +#include "tests/core/string/test_node_path.h" +#include "tests/core/string/test_string.h" +#include "tests/core/string/test_translation.h" +#include "tests/core/templates/test_command_queue.h" +#include "tests/core/templates/test_list.h" +#include "tests/core/templates/test_local_vector.h" +#include "tests/core/templates/test_lru.h" +#include "tests/core/templates/test_oa_hash_map.h" +#include "tests/core/templates/test_ordered_hash_map.h" +#include "tests/core/templates/test_paged_array.h" +#include "tests/core/templates/test_vector.h" +#include "tests/core/test_crypto.h" +#include "tests/core/test_hashing_context.h" +#include "tests/core/test_time.h" +#include "tests/core/variant/test_array.h" +#include "tests/core/variant/test_dictionary.h" +#include "tests/core/variant/test_variant.h" +#include "tests/scene/test_animation.h" +#include "tests/scene/test_code_edit.h" +#include "tests/scene/test_curve.h" +#include "tests/scene/test_gradient.h" +#include "tests/scene/test_gui.h" +#include "tests/scene/test_path_3d.h" +#include "tests/servers/test_physics_2d.h" +#include "tests/servers/test_physics_3d.h" +#include "tests/servers/test_render.h" +#include "tests/servers/test_shader_lang.h" +#include "tests/servers/test_text_server.h" +#include "tests/test_validate_testing.h" #include "modules/modules_tests.gen.h" #include "tests/test_macros.h" +#include "scene/resources/default_theme/default_theme.h" + int test_main(int argc, char *argv[]) { bool run_tests = true; @@ -199,7 +205,7 @@ struct GodotTestCaseListener : public doctest::IReporter { memnew(InputMap); InputMap::get_singleton()->load_default(); - make_default_theme(false, Ref<Font>()); + make_default_theme(1.0, Ref<Font>()); memnew(SceneTree); SceneTree::get_singleton()->initialize(); diff --git a/tests/test_main.h b/tests/test_main.h index 8c506a776f..8e6a7361fc 100644 --- a/tests/test_main.h +++ b/tests/test_main.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/tests/test_tools.h b/tests/test_tools.h index ec18610f04..8ee7a4718f 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,6 @@ #ifndef TEST_TOOLS_H #define TEST_TOOLS_H -#include "core/error/error_macros.h" - struct ErrorDetector { ErrorDetector() { eh.errfunc = _detect_error; diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index 1666a257a9..11cb6398aa 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "test_utils.h" +#include "tests/test_utils.h" #include "core/os/os.h" diff --git a/tests/test_utils.h b/tests/test_utils.h index f05ab0bdb1..499ddb84b2 100644 --- a/tests/test_utils.h +++ b/tests/test_utils.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TEST_UTILS_H #define TEST_UTILS_H -#include "core/string/ustring.h" +class String; namespace TestUtils { diff --git a/tests/test_validate_testing.h b/tests/test_validate_testing.h index 40b255e18a..413a7e351d 100644 --- a/tests/test_validate_testing.h +++ b/tests/test_validate_testing.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |