diff options
Diffstat (limited to 'tests')
24 files changed, 804 insertions, 187 deletions
diff --git a/tests/core/io/test_json.h b/tests/core/io/test_json.h index 478cf1766e..af450da3b8 100644 --- a/tests/core/io/test_json.h +++ b/tests/core/io/test_json.h @@ -83,7 +83,7 @@ TEST_CASE("[JSON] Parsing single data types") { json.get_error_line() == 0, "Parsing a floating-point number as JSON should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(json.get_data()), 0.123456), + double(json.get_data()) == doctest::Approx(0.123456), "Parsing a floating-point number as JSON should return the expected value."); json.parse("\"hello\""); diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index ebaf441abf..23969556be 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -91,7 +91,7 @@ TEST_CASE("[AABB] Basic setters") { TEST_CASE("[AABB] Volume getters") { AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_volume(), 120), + aabb.get_volume() == doctest::Approx(120), "get_volume() should return the expected value with positive size."); CHECK_MESSAGE( aabb.has_volume(), @@ -99,17 +99,17 @@ TEST_CASE("[AABB] Volume getters") { aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, 5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_volume(), -120), + aabb.get_volume() == doctest::Approx(-120), "get_volume() should return the expected value with negative size (1 component)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_volume(), 120), + aabb.get_volume() == doctest::Approx(120), "get_volume() should return the expected value with negative size (2 components)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, -6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_volume(), -120), + aabb.get_volume() == doctest::Approx(-120), "get_volume() should return the expected value with negative size (3 components)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6)); diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h index a4099ebf7d..dce9d5cec3 100644 --- a/tests/core/math/test_basis.h +++ b/tests/core/math/test_basis.h @@ -223,7 +223,7 @@ TEST_CASE("[Basis] Set axis angle") { // Testing the singularity when the angle is 180°. Basis singularityPi(-1, 0, 0, 0, 1, 0, 0, 0, -1); singularityPi.get_axis_angle(axis, angle); - CHECK(Math::is_equal_approx(angle, pi)); + CHECK(angle == doctest::Approx(pi)); // Testing reversing the an axis (of an 30° angle). float cos30deg = Math::cos(Math::deg_to_rad((real_t)30.0)); @@ -231,17 +231,17 @@ TEST_CASE("[Basis] Set axis angle") { Basis z_negative(cos30deg, 0.5, 0, -0.5, cos30deg, 0, 0, 0, 1); z_positive.get_axis_angle(axis, angle); - CHECK(Math::is_equal_approx(angle, Math::deg_to_rad((real_t)30.0))); + CHECK(angle == doctest::Approx(Math::deg_to_rad((real_t)30.0))); CHECK(axis == Vector3(0, 0, 1)); z_negative.get_axis_angle(axis, angle); - CHECK(Math::is_equal_approx(angle, Math::deg_to_rad((real_t)30.0))); + CHECK(angle == doctest::Approx(Math::deg_to_rad((real_t)30.0))); CHECK(axis == Vector3(0, 0, -1)); // Testing a rotation of 90° on x-y-z. Basis x90deg(1, 0, 0, 0, 0, -1, 0, 1, 0); x90deg.get_axis_angle(axis, angle); - CHECK(Math::is_equal_approx(angle, pi / (real_t)2)); + CHECK(angle == doctest::Approx(pi / (real_t)2)); CHECK(axis == Vector3(1, 0, 0)); Basis y90deg(0, 0, 1, 0, 1, 0, -1, 0, 0); @@ -255,7 +255,7 @@ TEST_CASE("[Basis] Set axis angle") { // Regression test: checks that the method returns a small angle (not 0). Basis tiny(1, 0, 0, 0, 0.9999995, -0.001, 0, 001, 0.9999995); // The min angle possible with float is 0.001rad. tiny.get_axis_angle(axis, angle); - CHECK(Math::is_equal_approx(angle, (real_t)0.001, (real_t)0.0001)); + CHECK(angle == doctest::Approx(0.001).epsilon(0.0001)); // Regression test: checks that the method returns an angle which is a number (not NaN) Basis bugNan(1.00000024, 0, 0.000100001693, 0, 1, 0, -0.000100009143, 0, 1.00000024); diff --git a/tests/core/math/test_color.h b/tests/core/math/test_color.h index 51c3bc8bdc..c6550778e8 100644 --- a/tests/core/math/test_color.h +++ b/tests/core/math/test_color.h @@ -101,13 +101,13 @@ TEST_CASE("[Color] Reading methods") { const Color dark_blue = Color(0, 0, 0.5, 0.4); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_h(), 240.0f / 360.0f), + dark_blue.get_h() == doctest::Approx(240.0f / 360.0f), "The returned HSV hue should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_s(), 1.0f), + dark_blue.get_s() == doctest::Approx(1.0f), "The returned HSV saturation should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_v(), 0.5f), + dark_blue.get_v() == doctest::Approx(0.5f), "The returned HSV value should match the expected value."); } diff --git a/tests/core/math/test_expression.h b/tests/core/math/test_expression.h index 6e3be541b0..9734fd9f36 100644 --- a/tests/core/math/test_expression.h +++ b/tests/core/math/test_expression.h @@ -83,42 +83,42 @@ TEST_CASE("[Expression] Floating-point arithmetic") { expression.parse("-123.456") == OK, "Float identity should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), -123.456), + double(expression.execute()) == doctest::Approx(-123.456), "Float identity should return the expected result."); CHECK_MESSAGE( expression.parse("2.0 + 3.0") == OK, "Float addition should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 5), + double(expression.execute()) == doctest::Approx(5), "Float addition should return the expected result."); CHECK_MESSAGE( expression.parse("3.0 / 10") == OK, "Float / integer division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 0.3), + double(expression.execute()) == doctest::Approx(0.3), "Float / integer division should return the expected result."); CHECK_MESSAGE( expression.parse("3 / 10.0") == OK, "Basic integer / float division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 0.3), + double(expression.execute()) == doctest::Approx(0.3), "Basic integer / float division should return the expected result."); CHECK_MESSAGE( expression.parse("3.0 / 10.0") == OK, "Float / float division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 0.3), + double(expression.execute()) == doctest::Approx(0.3), "Float / float division should return the expected result."); CHECK_MESSAGE( expression.parse("2.5 * (6.0 + 14.25) / 2.0 - 5.12345") == OK, "Float multiplication-addition-subtraction-division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 20.18905), + double(expression.execute()) == doctest::Approx(20.18905), "Float multiplication-addition-subtraction-division should return the expected result."); } @@ -129,7 +129,7 @@ TEST_CASE("[Expression] Scientific notation") { expression.parse("2.e5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 200'000), + double(expression.execute()) == doctest::Approx(200'000), "The expression should return the expected result."); // The middle "e" is ignored here. @@ -137,14 +137,14 @@ TEST_CASE("[Expression] Scientific notation") { expression.parse("2e5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 2e5), + double(expression.execute()) == doctest::Approx(2e5), "The expression should return the expected result."); CHECK_MESSAGE( expression.parse("2e.5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 2), + double(expression.execute()) == doctest::Approx(2), "The expression should return the expected result."); } @@ -176,7 +176,7 @@ TEST_CASE("[Expression] Built-in functions") { expression.parse("snapped(sin(0.5), 0.01)") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(double(expression.execute()), 0.48), + double(expression.execute()) == doctest::Approx(0.48), "`snapped(sin(0.5), 0.01)` should return the expected result."); CHECK_MESSAGE( diff --git a/tests/core/math/test_geometry_2d.h b/tests/core/math/test_geometry_2d.h index 54893a0b87..27c9e7f58b 100644 --- a/tests/core/math/test_geometry_2d.h +++ b/tests/core/math/test_geometry_2d.h @@ -171,43 +171,43 @@ TEST_CASE("[Geometry2D] Segment intersection with circle") { real_t one = 1.0; CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(4, 0), Vector2(0, 0), 1.0), one_quarter), + Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(4, 0), Vector2(0, 0), 1.0) == doctest::Approx(one_quarter), "Segment from inside to outside of circle should intersect it."); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(4, 0), Vector2(0, 0), Vector2(0, 0), 1.0), three_quarters), + Geometry2D::segment_intersects_circle(Vector2(4, 0), Vector2(0, 0), Vector2(0, 0), 1.0) == doctest::Approx(three_quarters), "Segment from outside to inside of circle should intersect it."); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(-2, 0), Vector2(2, 0), Vector2(0, 0), 1.0), one_quarter), + Geometry2D::segment_intersects_circle(Vector2(-2, 0), Vector2(2, 0), Vector2(0, 0), 1.0) == doctest::Approx(one_quarter), "Segment running through circle should intersect it."); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(-2, 0), Vector2(0, 0), 1.0), one_quarter), + Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(-2, 0), Vector2(0, 0), 1.0) == doctest::Approx(one_quarter), "Segment running through circle should intersect it."); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(1, 0), Vector2(0, 0), 1.0), one), + Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(1, 0), Vector2(0, 0), 1.0) == doctest::Approx(one), "Segment starting inside the circle and ending on the circle should intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(0, 0), Vector2(0, 0), 1.0), zero), + Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(0, 0), Vector2(0, 0), 1.0) == doctest::Approx(zero), "Segment starting on the circle and going inwards should intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(2, 0), Vector2(0, 0), 1.0), zero), + Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(2, 0), Vector2(0, 0), 1.0) == doctest::Approx(zero), "Segment starting on the circle and going outwards should intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(1, 0), Vector2(0, 0), 1.0), one), + Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(1, 0), Vector2(0, 0), 1.0) == doctest::Approx(one), "Segment starting outside the circle and ending on the circle intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(-1, 0), Vector2(1, 0), Vector2(0, 0), 2.0), minus_one), + Geometry2D::segment_intersects_circle(Vector2(-1, 0), Vector2(1, 0), Vector2(0, 0), 2.0) == doctest::Approx(minus_one), "Segment completely within the circle should not intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(-1, 0), Vector2(0, 0), 2.0), minus_one), + Geometry2D::segment_intersects_circle(Vector2(1, 0), Vector2(-1, 0), Vector2(0, 0), 2.0) == doctest::Approx(minus_one), "Segment completely within the circle should not intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(3, 0), Vector2(0, 0), 1.0), minus_one), + Geometry2D::segment_intersects_circle(Vector2(2, 0), Vector2(3, 0), Vector2(0, 0), 1.0) == doctest::Approx(minus_one), "Segment completely outside the circle should not intersect it"); CHECK_MESSAGE( - Math::is_equal_approx(Geometry2D::segment_intersects_circle(Vector2(3, 0), Vector2(2, 0), Vector2(0, 0), 1.0), minus_one), + Geometry2D::segment_intersects_circle(Vector2(3, 0), Vector2(2, 0), Vector2(0, 0), 1.0) == doctest::Approx(minus_one), "Segment completely outside the circle should not intersect it"); } diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h new file mode 100644 index 0000000000..c9d14bbd21 --- /dev/null +++ b/tests/core/math/test_math_funcs.h @@ -0,0 +1,549 @@ +/*************************************************************************/ +/* test_math_funcs.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_MATH_FUNCS_H +#define TEST_MATH_FUNCS_H + +#include "tests/test_macros.h" + +namespace TestMath { + +TEST_CASE("[Math] C++ macros") { + CHECK(MIN(-2, 2) == -2); + CHECK(MIN(600, 2) == 2); + + CHECK(MAX(-2, 2) == 2); + CHECK(MAX(600, 2) == 600); + + CHECK(CLAMP(600, -2, 2) == 2); + CHECK(CLAMP(620, 600, 650) == 620); + // `max` is lower than `min`. + CHECK(CLAMP(620, 600, 50) == 50); + + CHECK(ABS(-5) == 5); + CHECK(ABS(0) == 0); + CHECK(ABS(5) == 5); + + CHECK(SIGN(-5) == -1.0); + CHECK(SIGN(0) == 0.0); + CHECK(SIGN(5) == 1.0); +} + +TEST_CASE("[Math] Power of two functions") { + CHECK(next_power_of_2(0) == 0); + CHECK(next_power_of_2(1) == 1); + CHECK(next_power_of_2(16) == 16); + CHECK(next_power_of_2(17) == 32); + CHECK(next_power_of_2(65535) == 65536); + + CHECK(previous_power_of_2(0) == 0); + CHECK(previous_power_of_2(1) == 1); + CHECK(previous_power_of_2(16) == 16); + CHECK(previous_power_of_2(17) == 16); + CHECK(previous_power_of_2(65535) == 32768); + + CHECK(closest_power_of_2(0) == 0); + CHECK(closest_power_of_2(1) == 1); + CHECK(closest_power_of_2(16) == 16); + CHECK(closest_power_of_2(17) == 16); + CHECK(closest_power_of_2(65535) == 65536); + + CHECK(get_shift_from_power_of_2(0) == -1); + CHECK(get_shift_from_power_of_2(1) == 0); + CHECK(get_shift_from_power_of_2(16) == 4); + CHECK(get_shift_from_power_of_2(17) == -1); + CHECK(get_shift_from_power_of_2(65535) == -1); + + CHECK(nearest_shift(0) == 0); + CHECK(nearest_shift(1) == 1); + CHECK(nearest_shift(16) == 5); + CHECK(nearest_shift(17) == 5); + CHECK(nearest_shift(65535) == 16); +} + +TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) { + CHECK(Math::abs((T)-1) == (T)1); + CHECK(Math::abs((T)0) == (T)0); + CHECK(Math::abs((T)1) == (T)1); + CHECK(Math::abs((T)0.1) == (T)0.1); +} + +TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) { + CHECK(Math::round((T)1.5) == (T)2.0); + CHECK(Math::round((T)1.6) == (T)2.0); + CHECK(Math::round((T)-1.5) == (T)-2.0); + CHECK(Math::round((T)-1.1) == (T)-1.0); + + CHECK(Math::floor((T)1.5) == (T)1.0); + CHECK(Math::floor((T)-1.5) == (T)-2.0); + + CHECK(Math::ceil((T)1.5) == (T)2.0); + CHECK(Math::ceil((T)-1.9) == (T)-1.0); +} + +TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) { + CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166)); + CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166)); + CHECK(Math::sin((T)0.5) == doctest::Approx((T)0.4794255386)); + CHECK(Math::sin((T)1.0) == doctest::Approx((T)0.8414709848)); + CHECK(Math::sin((T)1.5) == doctest::Approx((T)0.9974949866)); + CHECK(Math::sin((T)450.0) == doctest::Approx((T)-0.683283725)); + + CHECK(Math::cos((T)-0.1) == doctest::Approx((T)0.99500416530)); + CHECK(Math::cos((T)0.1) == doctest::Approx((T)0.9950041653)); + CHECK(Math::cos((T)0.5) == doctest::Approx((T)0.8775825619)); + CHECK(Math::cos((T)1.0) == doctest::Approx((T)0.5403023059)); + CHECK(Math::cos((T)1.5) == doctest::Approx((T)0.0707372017)); + CHECK(Math::cos((T)450.0) == doctest::Approx((T)-0.7301529642)); + + CHECK(Math::tan((T)-0.1) == doctest::Approx((T)-0.1003346721)); + CHECK(Math::tan((T)0.1) == doctest::Approx((T)0.1003346721)); + CHECK(Math::tan((T)0.5) == doctest::Approx((T)0.5463024898)); + CHECK(Math::tan((T)1.0) == doctest::Approx((T)1.5574077247)); + CHECK(Math::tan((T)1.5) == doctest::Approx((T)14.1014199472)); + CHECK(Math::tan((T)450.0) == doctest::Approx((T)0.9358090134)); +} + +TEST_CASE_TEMPLATE("[Math] sinh/cosh/tanh", T, float, double) { + CHECK(Math::sinh((T)-0.1) == doctest::Approx((T)-0.10016675)); + CHECK(Math::sinh((T)0.1) == doctest::Approx((T)0.10016675)); + CHECK(Math::sinh((T)0.5) == doctest::Approx((T)0.5210953055)); + CHECK(Math::sinh((T)1.0) == doctest::Approx((T)1.1752011936)); + CHECK(Math::sinh((T)1.5) == doctest::Approx((T)2.1292794551)); + + CHECK(Math::cosh((T)-0.1) == doctest::Approx((T)1.0050041681)); + CHECK(Math::cosh((T)0.1) == doctest::Approx((T)1.0050041681)); + CHECK(Math::cosh((T)0.5) == doctest::Approx((T)1.1276259652)); + CHECK(Math::cosh((T)1.0) == doctest::Approx((T)1.5430806348)); + CHECK(Math::cosh((T)1.5) == doctest::Approx((T)2.3524096152)); + + CHECK(Math::tanh((T)-0.1) == doctest::Approx((T)-0.0996679946)); + CHECK(Math::tanh((T)0.1) == doctest::Approx((T)0.0996679946)); + CHECK(Math::tanh((T)0.5) == doctest::Approx((T)0.4621171573)); + CHECK(Math::tanh((T)1.0) == doctest::Approx((T)0.761594156)); + CHECK(Math::tanh((T)1.5) == doctest::Approx((T)0.9051482536)); + CHECK(Math::tanh((T)450.0) == doctest::Approx((T)1.0)); +} + +TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) { + CHECK(Math::asin((T)-0.1) == doctest::Approx((T)-0.1001674212)); + CHECK(Math::asin((T)0.1) == doctest::Approx((T)0.1001674212)); + CHECK(Math::asin((T)0.5) == doctest::Approx((T)0.5235987756)); + CHECK(Math::asin((T)1.0) == doctest::Approx((T)1.5707963268)); + CHECK(Math::is_nan(Math::asin((T)1.5))); + CHECK(Math::is_nan(Math::asin((T)450.0))); + + CHECK(Math::acos((T)-0.1) == doctest::Approx((T)1.670963748)); + CHECK(Math::acos((T)0.1) == doctest::Approx((T)1.4706289056)); + CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512)); + CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::is_nan(Math::acos((T)1.5))); + CHECK(Math::is_nan(Math::acos((T)450.0))); + + CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525)); + CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525)); + CHECK(Math::atan((T)0.5) == doctest::Approx((T)0.463647609)); + CHECK(Math::atan((T)1.0) == doctest::Approx((T)0.7853981634)); + CHECK(Math::atan((T)1.5) == doctest::Approx((T)0.9827937232)); + CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082)); +} + +TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) { + CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665)); + CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665)); + CHECK(Math::sinc((T)0.5) == doctest::Approx((T)0.9588510772)); + CHECK(Math::sinc((T)1.0) == doctest::Approx((T)0.8414709848)); + CHECK(Math::sinc((T)1.5) == doctest::Approx((T)0.6649966577)); + CHECK(Math::sinc((T)450.0) == doctest::Approx((T)-0.0015184083)); + + CHECK(Math::sincn((T)-0.1) == doctest::Approx((T)0.9836316431)); + CHECK(Math::sincn((T)0.1) == doctest::Approx((T)0.9836316431)); + CHECK(Math::sincn((T)0.5) == doctest::Approx((T)0.6366197724)); + CHECK(Math::sincn((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::sincn((T)1.5) == doctest::Approx((T)-0.2122065908)); + CHECK(Math::sincn((T)450.0) == doctest::Approx((T)0.0)); + + CHECK(Math::atan2((T)-0.1, (T)0.5) == doctest::Approx((T)-0.1973955598)); + CHECK(Math::atan2((T)0.1, (T)-0.5) == doctest::Approx((T)2.9441970937)); + CHECK(Math::atan2((T)0.5, (T)1.5) == doctest::Approx((T)0.3217505544)); + CHECK(Math::atan2((T)1.0, (T)2.5) == doctest::Approx((T)0.3805063771)); + CHECK(Math::atan2((T)1.5, (T)1.0) == doctest::Approx((T)0.9827937232)); + CHECK(Math::atan2((T)450.0, (T)1.0) == doctest::Approx((T)1.5685741082)); +} + +TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) { + CHECK(Math::pow((T)-0.1, (T)2.0) == doctest::Approx((T)0.01)); + CHECK(Math::pow((T)0.1, (T)2.5) == doctest::Approx((T)0.0031622777)); + CHECK(Math::pow((T)0.5, (T)0.5) == doctest::Approx((T)0.7071067812)); + CHECK(Math::pow((T)1.0, (T)1.0) == doctest::Approx((T)1.0)); + CHECK(Math::pow((T)1.5, (T)-1.0) == doctest::Approx((T)0.6666666667)); + CHECK(Math::pow((T)450.0, (T)-2.0) == doctest::Approx((T)0.0000049383)); + CHECK(Math::pow((T)450.0, (T)0.0) == doctest::Approx((T)1.0)); + + CHECK(Math::is_nan(Math::log((T)-0.1))); + CHECK(Math::log((T)0.1) == doctest::Approx((T)-2.302585093)); + CHECK(Math::log((T)0.5) == doctest::Approx((T)-0.6931471806)); + CHECK(Math::log((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::log((T)1.5) == doctest::Approx((T)0.4054651081)); + CHECK(Math::log((T)450.0) == doctest::Approx((T)6.1092475828)); + + CHECK(Math::is_nan(Math::log2((T)-0.1))); + CHECK(Math::log2((T)0.1) == doctest::Approx((T)-3.3219280949)); + CHECK(Math::log2((T)0.5) == doctest::Approx((T)-1.0)); + CHECK(Math::log2((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::log2((T)1.5) == doctest::Approx((T)0.5849625007)); + CHECK(Math::log2((T)450.0) == doctest::Approx((T)8.8137811912)); + + CHECK(Math::exp((T)-0.1) == doctest::Approx((T)0.904837418)); + CHECK(Math::exp((T)0.1) == doctest::Approx((T)1.1051709181)); + CHECK(Math::exp((T)0.5) == doctest::Approx((T)1.6487212707)); + CHECK(Math::exp((T)1.0) == doctest::Approx((T)2.7182818285)); + CHECK(Math::exp((T)1.5) == doctest::Approx((T)4.4816890703)); + + CHECK(Math::is_nan(Math::sqrt((T)-0.1))); + CHECK(Math::sqrt((T)0.1) == doctest::Approx((T)0.316228)); + CHECK(Math::sqrt((T)0.5) == doctest::Approx((T)0.707107)); + CHECK(Math::sqrt((T)1.0) == doctest::Approx((T)1.0)); + CHECK(Math::sqrt((T)1.5) == doctest::Approx((T)1.224745)); +} + +TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) { + CHECK(!Math::is_nan((T)0.0)); + CHECK(Math::is_nan((T)NAN)); + + CHECK(!Math::is_inf((T)0.0)); + CHECK(Math::is_inf((T)INFINITY)); +} + +TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) { + CHECK(Math::linear_to_db((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::linear_to_db((T)20.0) == doctest::Approx((T)26.0206)); + CHECK(Math::is_inf(Math::linear_to_db((T)0.0))); + CHECK(Math::is_nan(Math::linear_to_db((T)-20.0))); +} + +TEST_CASE_TEMPLATE("[Math] db_to_linear", T, float, double) { + CHECK(Math::db_to_linear((T)0.0) == doctest::Approx((T)1.0)); + CHECK(Math::db_to_linear((T)1.0) == doctest::Approx((T)1.122018)); + CHECK(Math::db_to_linear((T)20.0) == doctest::Approx((T)10.0)); + CHECK(Math::db_to_linear((T)-20.0) == doctest::Approx((T)0.1)); +} + +TEST_CASE_TEMPLATE("[Math] step_decimals", T, float, double) { + CHECK(Math::step_decimals((T)-0.5) == 1); + CHECK(Math::step_decimals((T)0) == 0); + CHECK(Math::step_decimals((T)1) == 0); + CHECK(Math::step_decimals((T)0.1) == 1); + CHECK(Math::step_decimals((T)0.01) == 2); + CHECK(Math::step_decimals((T)0.001) == 3); + CHECK(Math::step_decimals((T)0.0001) == 4); + CHECK(Math::step_decimals((T)0.00001) == 5); + CHECK(Math::step_decimals((T)0.000001) == 6); + CHECK(Math::step_decimals((T)0.0000001) == 7); + CHECK(Math::step_decimals((T)0.00000001) == 8); + CHECK(Math::step_decimals((T)0.000000001) == 9); + // Too many decimals to handle. + CHECK(Math::step_decimals((T)0.0000000001) == 0); +} + +TEST_CASE_TEMPLATE("[Math] range_step_decimals", T, float, double) { + CHECK(Math::range_step_decimals((T)0.000000001) == 9); + // Too many decimals to handle. + CHECK(Math::range_step_decimals((T)0.0000000001) == 0); + // Should be treated as a step of 0 for use by the editor. + CHECK(Math::range_step_decimals((T)0.0) == 16); + CHECK(Math::range_step_decimals((T)-0.5) == 16); +} + +TEST_CASE_TEMPLATE("[Math] lerp", T, float, double) { + CHECK(Math::lerp((T)2.0, (T)5.0, (T)-0.1) == doctest::Approx((T)1.7)); + CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.0) == doctest::Approx((T)2.0)); + CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.1) == doctest::Approx((T)2.3)); + CHECK(Math::lerp((T)2.0, (T)5.0, (T)1.0) == doctest::Approx((T)5.0)); + CHECK(Math::lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)8.0)); + + CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)-0.1) == doctest::Approx((T)-1.7)); + CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.0) == doctest::Approx((T)-2.0)); + CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.1) == doctest::Approx((T)-2.3)); + CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)1.0) == doctest::Approx((T)-5.0)); + CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)2.0) == doctest::Approx((T)-8.0)); +} + +TEST_CASE_TEMPLATE("[Math] inverse_lerp", T, float, double) { + CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)1.7) == doctest::Approx((T)-0.1)); + CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)0.0)); + CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.3) == doctest::Approx((T)0.1)); + CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)5.0) == doctest::Approx((T)1.0)); + CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)8.0) == doctest::Approx((T)2.0)); + + CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-1.7) == doctest::Approx((T)-0.1)); + CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.0) == doctest::Approx((T)0.0)); + CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.3) == doctest::Approx((T)0.1)); + CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-5.0) == doctest::Approx((T)1.0)); + CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-8.0) == doctest::Approx((T)2.0)); +} + +TEST_CASE_TEMPLATE("[Math] remap", T, float, double) { + CHECK(Math::remap((T)50.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0)); + CHECK(Math::remap((T)100.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0)); + CHECK(Math::remap((T)200.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0)); + CHECK(Math::remap((T)250.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0)); + + CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0)); + CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0)); + CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0)); + CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0)); + + CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)500.0)); + CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)0.0)); + CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1000.0)); + CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0)); +} + +TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) { + // Counter-clockwise rotation. + CHECK(Math::lerp_angle((T)0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)-0.005 * Math_TAU)); + // Counter-clockwise rotation. + CHECK(Math::lerp_angle((T)0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.0)); + // Clockwise rotation. + CHECK(Math::lerp_angle((T)0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.505 * Math_TAU)); + + CHECK(Math::lerp_angle((T)-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx((T)-0.5 * Math_TAU)); + CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx((T)0.4512 * Math_TAU)); + CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx((T)0.4288 * Math_TAU)); + + // Initial and final angles are effectively identical, so the value returned + // should always be the same regardless of the `weight` parameter. + CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx((T)-4.0 * Math_TAU)); + CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx((T)-4.0 * Math_TAU)); + CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx((T)-4.0 * Math_TAU)); + CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx((T)-4.0 * Math_TAU)); + CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx((T)-4.0 * Math_TAU)); +} + +TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) { + CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx((T)1.0)); + CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx((T)4.5)); + CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx((T)5.0)); + CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx((T)-1.0)); + CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx((T)-4.5)); + CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0)); +} + +TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) { + CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0)); + CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625)); + CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)1.0) == doctest::Approx((T)0.5)); + CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)2.0) == doctest::Approx((T)1.0)); +} + +TEST_CASE("[Math] ease") { + CHECK(Math::ease(0.1, 1.0) == doctest::Approx(0.1)); + CHECK(Math::ease(0.1, 2.0) == doctest::Approx(0.01)); + CHECK(Math::ease(0.1, 0.5) == doctest::Approx(0.19)); + CHECK(Math::ease(0.1, 0.0) == doctest::Approx(0)); + CHECK(Math::ease(0.1, -0.5) == doctest::Approx(0.2236067977)); + CHECK(Math::ease(0.1, -1.0) == doctest::Approx(0.1)); + CHECK(Math::ease(0.1, -2.0) == doctest::Approx(0.02)); + + CHECK(Math::ease(-1.0, 1.0) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, 2.0) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, 0.5) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, 0.0) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, -0.5) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, -1.0) == doctest::Approx(0)); + CHECK(Math::ease(-1.0, -2.0) == doctest::Approx(0)); +} + +TEST_CASE("[Math] snapped") { + CHECK(Math::snapped(0.5, 0.04) == doctest::Approx(0.52)); + CHECK(Math::snapped(-0.5, 0.04) == doctest::Approx(-0.48)); + CHECK(Math::snapped(0.0, 0.04) == doctest::Approx(0)); + CHECK(Math::snapped(128'000.025, 0.04) == doctest::Approx(128'000.04)); + + CHECK(Math::snapped(0.5, 400) == doctest::Approx(0)); + CHECK(Math::snapped(-0.5, 400) == doctest::Approx(0)); + CHECK(Math::snapped(0.0, 400) == doctest::Approx(0)); + CHECK(Math::snapped(128'000.025, 400) == doctest::Approx(128'000.0)); + + CHECK(Math::snapped(0.5, 0.0) == doctest::Approx(0.5)); + CHECK(Math::snapped(-0.5, 0.0) == doctest::Approx(-0.5)); + CHECK(Math::snapped(0.0, 0.0) == doctest::Approx(0.0)); + CHECK(Math::snapped(128'000.025, 0.0) == doctest::Approx(128'000.0)); + + CHECK(Math::snapped(0.5, -1.0) == doctest::Approx(0)); + CHECK(Math::snapped(-0.5, -1.0) == doctest::Approx(-1.0)); + CHECK(Math::snapped(0.0, -1.0) == doctest::Approx(0)); + CHECK(Math::snapped(128'000.025, -1.0) == doctest::Approx(128'000.0)); +} + +TEST_CASE("[Math] larger_prime") { + CHECK(Math::larger_prime(0) == 5); + CHECK(Math::larger_prime(1) == 5); + CHECK(Math::larger_prime(2) == 5); + CHECK(Math::larger_prime(5) == 13); + CHECK(Math::larger_prime(500) == 769); + CHECK(Math::larger_prime(1'000'000) == 1'572'869); + CHECK(Math::larger_prime(1'000'000'000) == 1'610'612'741); + + // The next prime is larger than `INT32_MAX` and is not present in the built-in prime table. + ERR_PRINT_OFF; + CHECK(Math::larger_prime(2'000'000'000) == 0); + ERR_PRINT_ON; +} + +TEST_CASE_TEMPLATE("[Math] fmod", T, float, double) { + CHECK(Math::fmod((T)-2.0, (T)0.3) == doctest::Approx((T)-0.2)); + CHECK(Math::fmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2)); + + CHECK(Math::fmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2)); + CHECK(Math::fmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fmod((T)2.0, (T)-0.3) == doctest::Approx((T)0.2)); +} + +TEST_CASE_TEMPLATE("[Math] fposmod", T, float, double) { + CHECK(Math::fposmod((T)-2.0, (T)0.3) == doctest::Approx((T)0.1)); + CHECK(Math::fposmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fposmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2)); + + CHECK(Math::fposmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2)); + CHECK(Math::fposmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fposmod((T)2.0, (T)-0.3) == doctest::Approx((T)-0.1)); +} + +TEST_CASE_TEMPLATE("[Math] fposmodp", T, float, double) { + CHECK(Math::fposmodp((T)-2.0, (T)0.3) == doctest::Approx((T)0.1)); + CHECK(Math::fposmodp((T)0.0, (T)0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fposmodp((T)2.0, (T)0.3) == doctest::Approx((T)0.2)); + + CHECK(Math::fposmodp((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.5)); + CHECK(Math::fposmodp((T)0.0, (T)-0.3) == doctest::Approx((T)0.0)); + CHECK(Math::fposmodp((T)2.0, (T)-0.3) == doctest::Approx((T)0.2)); +} + +TEST_CASE("[Math] posmod") { + CHECK(Math::posmod(-20, 3) == 1); + CHECK(Math::posmod(0, 3) == 0); + CHECK(Math::posmod(20, 3) == 2); + CHECK(Math::posmod(-20, -3) == -2); + CHECK(Math::posmod(0, -3) == 0); + CHECK(Math::posmod(20, -3) == -1); +} + +TEST_CASE("[Math] wrapi") { + CHECK(Math::wrapi(-30, -20, 160) == 150); + CHECK(Math::wrapi(30, -20, 160) == 30); + CHECK(Math::wrapi(300, -20, 160) == 120); + CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120); +} + +TEST_CASE_TEMPLATE("[Math] wrapf", T, float, double) { + CHECK(Math::wrapf((T)-30.0, (T)-20.0, (T)160.0) == doctest::Approx((T)150.0)); + CHECK(Math::wrapf((T)30.0, (T)-2.0, (T)160.0) == doctest::Approx((T)30.0)); + CHECK(Math::wrapf((T)300.0, (T)-20.0, (T)160.0) == doctest::Approx((T)120.0)); + + CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx((T)120.0)); + // float's precision is too low for 300'000'000'000.0, so we reduce it by a factor of 1000. + CHECK(Math::wrapf((float)300'000'000.0, (float)-20.0, (float)160.0) == doctest::Approx((T)128.0)); +} + +TEST_CASE_TEMPLATE("[Math] fract", T, float, double) { + CHECK(Math::fract((T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::fract((T)77.8) == doctest::Approx((T)0.8)); + CHECK(Math::fract((T)-10.1) == doctest::Approx((T)0.9)); +} + +TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) { + CHECK(Math::pingpong((T)0.0, (T)0.0) == doctest::Approx((T)0.0)); + CHECK(Math::pingpong((T)1.0, (T)1.0) == doctest::Approx((T)1.0)); + CHECK(Math::pingpong((T)0.5, (T)2.0) == doctest::Approx((T)0.5)); + CHECK(Math::pingpong((T)3.5, (T)2.0) == doctest::Approx((T)0.5)); + CHECK(Math::pingpong((T)11.5, (T)2.0) == doctest::Approx((T)0.5)); + CHECK(Math::pingpong((T)-2.5, (T)2.0) == doctest::Approx((T)1.5)); +} + +TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) { + CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math_PI)); + CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239)); + + CHECK(Math::rad_to_deg((T)Math_PI) == doctest::Approx((T)180.0)); + CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927)); +} + +TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) { + CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0) == doctest::Approx((T)0.2)); + CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25) == doctest::Approx((T)0.33125)); + CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5) == doctest::Approx((T)0.5)); + CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75) == doctest::Approx((T)0.66875)); + CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0) == doctest::Approx((T)0.8)); + + CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-50.0) == doctest::Approx((T)-6662732.3)); + CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-5.0) == doctest::Approx((T)-9356.3)); + CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)0.0) == doctest::Approx((T)20.2)); + CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)1.0) == doctest::Approx((T)30.1)); + CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)4.0) == doctest::Approx((T)1853.2)); +} + +TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) { + CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI * (1.0 / 6.0))); + CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25) == doctest::Approx((T)0.973566)); + CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5) == doctest::Approx((T)Math_PI / 2.0)); + CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75) == doctest::Approx((T)2.16803)); + CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0))); +} + +TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) { + CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.1625)); + CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.4)); + CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.6375)); + CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.8)); +} + +TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) { + CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0)); + CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964)); + CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627)); + CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394)); + CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0))); +} + +TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) { + CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.0) == doctest::Approx((T)0.0)); + CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.25) == doctest::Approx((T)0.2125)); + CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.5) == doctest::Approx((T)0.5)); + CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.75) == doctest::Approx((T)0.7875)); + CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)1.0) == doctest::Approx((T)1.0)); +} + +} // namespace TestMath + +#endif // TEST_MATH_FUNCS_H diff --git a/tests/core/math/test_rect2.h b/tests/core/math/test_rect2.h index d784875c1c..9984823331 100644 --- a/tests/core/math/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -102,16 +102,16 @@ TEST_CASE("[Rect2] Basic setters") { TEST_CASE("[Rect2] Area getters") { CHECK_MESSAGE( - Math::is_equal_approx(Rect2(0, 100, 1280, 720).get_area(), 921'600), + Rect2(0, 100, 1280, 720).get_area() == doctest::Approx(921'600), "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2(0, 100, -1280, -720).get_area(), 921'600), + Rect2(0, 100, -1280, -720).get_area() == doctest::Approx(921'600), "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2(0, 100, 1280, -720).get_area(), -921'600), + Rect2(0, 100, 1280, -720).get_area() == doctest::Approx(-921'600), "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2(0, 100, -1280, 720).get_area(), -921'600), + Rect2(0, 100, -1280, 720).get_area() == doctest::Approx(-921'600), "get_area() should return the expected value."); CHECK_MESSAGE( Math::is_zero_approx(Rect2(0, 100, 0, 720).get_area()), diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h index f7e9259329..8f8fccd717 100644 --- a/tests/core/math/test_vector2.h +++ b/tests/core/math/test_vector2.h @@ -49,16 +49,16 @@ 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), + vector_x.angle_to(vector_y) == doctest::Approx((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), + vector_y.angle_to(vector_x) == doctest::Approx((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), + vector_x.angle_to_point(vector_y) == doctest::Approx((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), + vector_y.angle_to_point(vector_x) == doctest::Approx((real_t)-Math_TAU / 8), "Vector2 angle_to_point should work as expected."); } @@ -113,10 +113,10 @@ TEST_CASE("[Vector2] Interpolation methods") { Vector2(4, 6).slerp(Vector2(8, 10), 0.5).is_equal_approx(Vector2(5.9076470794008017626, 8.07918879020090480697)), "Vector2 slerp should work as expected."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)4.31959610746631919), + vector1.slerp(vector2, 0.5).length() == doctest::Approx((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)), + vector1.angle_to(vector1.slerp(vector2, 0.5)) * 2 == doctest::Approx(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), @@ -136,19 +136,19 @@ TEST_CASE("[Vector2] Length methods") { 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), + vector1.length() == doctest::Approx(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() == doctest::Approx((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), + vector1.distance_to(vector2) == doctest::Approx((real_t)22.36067977499789696409), "Vector2 distance_to should work as expected."); } @@ -294,7 +294,7 @@ TEST_CASE("[Vector2] Operators") { 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), + vector.aspect() == doctest::Approx((real_t)1.2 / (real_t)3.4), "Vector2 aspect should work as expected."); CHECK_MESSAGE( @@ -443,10 +443,10 @@ TEST_CASE("[Vector2] Linear algebra methods") { vector_y.cross(vector_x) == -1, "Vector2 cross product of Y and X should give negative 1."); CHECK_MESSAGE( - Math::is_equal_approx(a.cross(b), (real_t)-28.1), + a.cross(b) == doctest::Approx((real_t)-28.1), "Vector2 cross should return expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Vector2(-a.x, a.y).cross(Vector2(b.x, -b.y)), (real_t)-28.1), + Vector2(-a.x, a.y).cross(Vector2(b.x, -b.y)) == doctest::Approx((real_t)-28.1), "Vector2 cross should return expected value."); CHECK_MESSAGE( @@ -459,10 +459,10 @@ TEST_CASE("[Vector2] Linear algebra methods") { (vector_x * 10).dot(vector_x * 10) == 100.0, "Vector2 dot product of same direction vectors should behave as expected."); CHECK_MESSAGE( - Math::is_equal_approx(a.dot(b), (real_t)57.3), + a.dot(b) == doctest::Approx((real_t)57.3), "Vector2 dot should return expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Vector2(-a.x, a.y).dot(Vector2(b.x, -b.y)), (real_t)-57.3), + Vector2(-a.x, a.y).dot(Vector2(b.x, -b.y)) == doctest::Approx((real_t)-57.3), "Vector2 dot should return expected value."); } diff --git a/tests/core/math/test_vector2i.h b/tests/core/math/test_vector2i.h index 49b0632e3c..c7a0dccdcc 100644 --- a/tests/core/math/test_vector2i.h +++ b/tests/core/math/test_vector2i.h @@ -79,13 +79,13 @@ TEST_CASE("[Vector2i] Length methods") { 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), + vector1.length() == doctest::Approx(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), + vector2.length() == doctest::Approx(36.05551275463989293119), "Vector2i length should work as expected."); } @@ -127,7 +127,7 @@ TEST_CASE("[Vector2i] Operators") { 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), + vector.aspect() == doctest::Approx((real_t)1.0 / (real_t)3.0), "Vector2i aspect should work as expected."); CHECK_MESSAGE( diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h index 77d3a9d93c..89d73ee6de 100644 --- a/tests/core/math/test_vector3.h +++ b/tests/core/math/test_vector3.h @@ -52,26 +52,26 @@ TEST_CASE("[Vector3] Angle methods") { 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), + vector_x.angle_to(vector_y) == doctest::Approx((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), + vector_x.angle_to(vector_yz) == doctest::Approx((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), + vector_yz.angle_to(vector_x) == doctest::Approx((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), + vector_y.angle_to(vector_yz) == doctest::Approx((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), + vector_x.signed_angle_to(vector_y, vector_y) == doctest::Approx((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), + vector_x.signed_angle_to(vector_yz, vector_y) == doctest::Approx((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), + vector_yz.signed_angle_to(vector_x, vector_y) == doctest::Approx((real_t)Math_TAU / 4), "Vector3 signed_angle_to should work as expected."); } @@ -130,10 +130,10 @@ TEST_CASE("[Vector3] Interpolation methods") { Vector3(4, 6, 2).slerp(Vector3(8, 10, 3), 0.5).is_equal_approx(Vector3(5.90194219811429941053, 8.06758688849378394534, 2.558307894718317120038)), "Vector3 slerp should work as expected."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)6.25831088708303172), + vector1.slerp(vector2, 0.5).length() == doctest::Approx((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)), + vector1.angle_to(vector1.slerp(vector2, 0.5)) * 2 == doctest::Approx(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), @@ -153,19 +153,19 @@ TEST_CASE("[Vector3] Length methods") { 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), + vector1.length() == doctest::Approx(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), + vector2.length() == doctest::Approx((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), + vector1.distance_to(vector2) == doctest::Approx((real_t)37.41657386773941385584), "Vector3 distance_to should work as expected."); } @@ -473,10 +473,10 @@ TEST_CASE("[Vector3] Linear algebra methods") { (vector_x * 10).dot(vector_x * 10) == 100.0, "Vector3 dot product of same direction vectors should behave as expected."); CHECK_MESSAGE( - Math::is_equal_approx(a.dot(b), (real_t)75.24), + a.dot(b) == doctest::Approx((real_t)75.24), "Vector3 dot should return expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Vector3(-a.x, a.y, -a.z).dot(Vector3(b.x, -b.y, b.z)), (real_t)-75.24), + Vector3(-a.x, a.y, -a.z).dot(Vector3(b.x, -b.y, b.z)) == doctest::Approx((real_t)-75.24), "Vector3 dot should return expected value."); } diff --git a/tests/core/math/test_vector3i.h b/tests/core/math/test_vector3i.h index 2050b222d0..56578f99eb 100644 --- a/tests/core/math/test_vector3i.h +++ b/tests/core/math/test_vector3i.h @@ -82,13 +82,13 @@ TEST_CASE("[Vector3i] Length methods") { 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), + vector1.length() == doctest::Approx(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), + vector2.length() == doctest::Approx(53.8516480713450403125), "Vector3i length should work as expected."); } diff --git a/tests/core/math/test_vector4.h b/tests/core/math/test_vector4.h index b31db56f67..6ed85661cb 100644 --- a/tests/core/math/test_vector4.h +++ b/tests/core/math/test_vector4.h @@ -91,19 +91,19 @@ TEST_CASE("[Vector4] Length methods") { vector1.length_squared() == 400, "Vector4 length_squared should work as expected and return exact result."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.length(), 20), + vector1.length() == doctest::Approx(20), "Vector4 length should work as expected."); CHECK_MESSAGE( vector2.length_squared() == 5400, "Vector4 length_squared should work as expected and return exact result."); CHECK_MESSAGE( - Math::is_equal_approx(vector2.length(), (real_t)73.484692283495), + vector2.length() == doctest::Approx((real_t)73.484692283495), "Vector4 length should work as expected."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.distance_to(vector2), (real_t)54.772255750517), + vector1.distance_to(vector2) == doctest::Approx((real_t)54.772255750517), "Vector4 distance_to should work as expected."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.distance_squared_to(vector2), 3000), + vector1.distance_squared_to(vector2) == doctest::Approx(3000), "Vector4 distance_squared_to should work as expected."); } @@ -311,7 +311,7 @@ TEST_CASE("[Vector4] Linear algebra methods") { (vector_x * 10).dot(vector_x * 10) == 100.0, "Vector4 dot product of same direction vectors should behave as expected."); CHECK_MESSAGE( - Math::is_equal_approx((vector1 * 2).dot(vector2 * 4), (real_t)-25.9 * 8), + (vector1 * 2).dot(vector2 * 4) == doctest::Approx((real_t)-25.9 * 8), "Vector4 dot product should work as expected."); } diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h index 309162c3f7..30d38607dd 100644 --- a/tests/core/math/test_vector4i.h +++ b/tests/core/math/test_vector4i.h @@ -82,13 +82,13 @@ TEST_CASE("[Vector4i] Length methods") { vector1.length_squared() == 400, "Vector4i length_squared should work as expected and return exact result."); CHECK_MESSAGE( - Math::is_equal_approx(vector1.length(), 20), + vector1.length() == doctest::Approx(20), "Vector4i length should work as expected."); CHECK_MESSAGE( vector2.length_squared() == 5400, "Vector4i length_squared should work as expected and return exact result."); CHECK_MESSAGE( - Math::is_equal_approx(vector2.length(), 73.4846922835), + vector2.length() == doctest::Approx(73.4846922835), "Vector4i length should work as expected."); } diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index cd1b421ce8..ebb526b37c 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -485,6 +485,7 @@ TEST_CASE("[String] Splitting") { const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" }; const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" }; + const char *slices_3[4] = { "t", "e", "s", "t" }; l = s.split(",", true, 2); CHECK(l.size() == 3); @@ -498,6 +499,13 @@ TEST_CASE("[String] Splitting") { CHECK(l[i] == slices_r[i]); } + s = "test"; + l = s.split(); + CHECK(l.size() == 4); + for (int i = 0; i < l.size(); i++) { + CHECK(l[i] == slices_3[i]); + } + s = "Mars Jupiter Saturn Uranus"; const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" }; l = s.split_spaces(); @@ -508,21 +516,22 @@ TEST_CASE("[String] Splitting") { s = "1.2;2.3 4.5"; const double slices_d[3] = { 1.2, 2.3, 4.5 }; - Vector<float> f; - f = s.split_floats(";"); - CHECK(f.size() == 2); - for (int i = 0; i < f.size(); i++) { - CHECK(ABS(f[i] - slices_d[i]) <= 0.00001); + Vector<double> d_arr; + d_arr = s.split_floats(";"); + CHECK(d_arr.size() == 2); + for (int i = 0; i < d_arr.size(); i++) { + CHECK(ABS(d_arr[i] - slices_d[i]) <= 0.00001); } Vector<String> keys; keys.push_back(";"); keys.push_back(" "); - f = s.split_floats_mk(keys); - CHECK(f.size() == 3); - for (int i = 0; i < f.size(); i++) { - CHECK(ABS(f[i] - slices_d[i]) <= 0.00001); + Vector<float> f_arr; + f_arr = s.split_floats_mk(keys); + CHECK(f_arr.size() == 3); + for (int i = 0; i < f_arr.size(); i++) { + CHECK(ABS(f_arr[i] - slices_d[i]) <= 0.00001); } s = "1;2 4"; diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl index 7bf56e73cd..58ddd08cdd 100644 --- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl +++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl @@ -18,7 +18,7 @@ public: DISABLE_LIGHTING=1, }; - _FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { _version_bind_shader(p_version,p_variant,p_specialization); } + _FORCE_INLINE_ bool version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { return _version_bind_shader(p_version,p_variant,p_specialization); } protected: @@ -35,13 +35,14 @@ protected: {"DISABLE_LIGHTING",false}, }; + static const Feedback* _feedbacks=nullptr; static const char _vertex_code[]={ 10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,51,32,118,101,114,116,101,120,59,10,10,111,117,116,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,32,61,32,118,101,99,52,40,118,101,114,116,101,120,46,120,44,49,44,48,44,49,41,59,10,125,10,10, 0}; static const char _fragment_code[]={ 10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,105,110,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,104,105,103,104,112,32,102,108,111,97,116,32,100,101,112,116,104,32,61,32,40,40,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,122,32,47,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,119,41,32,43,32,49,46,48,41,59,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,101,112,116,104,41,59,10,125,10, 0}; - _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines); + _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_feedbacks,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines); } }; diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json index eaeb5981c0..5ac8092ad0 100644 --- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json +++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json @@ -31,6 +31,7 @@ "texunit_names": [], "ubos": [], "ubo_names": [], + "feedbacks": [], "vertex_included_files": [], "fragment_included_files": [], "reading": "fragment", diff --git a/tests/scene/test_animation.h b/tests/scene/test_animation.h index ca80f0ecab..e921779c23 100644 --- a/tests/scene/test_animation.h +++ b/tests/scene/test_animation.h @@ -40,8 +40,8 @@ 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))); + CHECK(animation->get_length() == doctest::Approx(real_t(1.0))); + CHECK(animation->get_step() == doctest::Approx(real_t(0.1))); } TEST_CASE("[Animation] Create value track") { @@ -59,33 +59,33 @@ TEST_CASE("[Animation] Create value track") { 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(animation->value_track_interpolate(0, -0.2) == doctest::Approx(0.0)); + CHECK(animation->value_track_interpolate(0, 0.0) == doctest::Approx(0.0)); + CHECK(animation->value_track_interpolate(0, 0.2) == doctest::Approx(40.0)); + CHECK(animation->value_track_interpolate(0, 0.4) == doctest::Approx(80.0)); + CHECK(animation->value_track_interpolate(0, 0.5) == doctest::Approx(100.0)); + CHECK(animation->value_track_interpolate(0, 0.6) == doctest::Approx(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))); + CHECK(animation->track_get_key_transition(0, 0) == doctest::Approx(real_t(1.0))); + CHECK(animation->track_get_key_transition(0, 1) == doctest::Approx(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))); + CHECK(animation->track_get_key_transition(0, 2) == doctest::Approx(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))); + CHECK(animation->track_get_key_transition(1, 0) == doctest::Approx(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->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0)); CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); ERR_PRINT_ON; } @@ -123,15 +123,15 @@ TEST_CASE("[Animation] Create 3D position track") { 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))); + CHECK(animation->track_get_key_transition(0, 0) == doctest::Approx(real_t(1.0))); + CHECK(animation->track_get_key_transition(0, 1) == doctest::Approx(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->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0)); CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); ERR_PRINT_ON; } @@ -169,15 +169,15 @@ TEST_CASE("[Animation] Create 3D rotation track") { 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))); + CHECK(animation->track_get_key_transition(0, 0) == doctest::Approx(real_t(1.0))); + CHECK(animation->track_get_key_transition(0, 1) == doctest::Approx(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->bezier_track_interpolate(0, 0.0) == doctest::Approx(real_t(0.0))); CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); ERR_PRINT_ON; } @@ -215,15 +215,15 @@ TEST_CASE("[Animation] Create 3D scale track") { 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))); + CHECK(animation->track_get_key_transition(0, 0) == doctest::Approx(1.0)); + CHECK(animation->track_get_key_transition(0, 1) == doctest::Approx(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->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0)); CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER); ERR_PRINT_ON; } @@ -242,32 +242,32 @@ TEST_CASE("[Animation] Create blend shape track") { 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(r_blend == doctest::Approx(-1.0f)); CHECK(animation->blend_shape_track_get_key(0, 1, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, 1.0f)); + CHECK(r_blend == doctest::Approx(1.0f)); CHECK(animation->blend_shape_track_interpolate(0, -0.2, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, -1.0f)); + CHECK(r_blend == doctest::Approx(-1.0f)); CHECK(animation->blend_shape_track_interpolate(0, 0.0, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, -1.0f)); + CHECK(r_blend == doctest::Approx(-1.0f)); CHECK(animation->blend_shape_track_interpolate(0, 0.2, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, -0.2f)); + CHECK(r_blend == doctest::Approx(-0.2f)); CHECK(animation->blend_shape_track_interpolate(0, 0.4, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, 0.6f)); + CHECK(r_blend == doctest::Approx(0.6f)); CHECK(animation->blend_shape_track_interpolate(0, 0.5, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, 1.0f)); + CHECK(r_blend == doctest::Approx(1.0f)); CHECK(animation->blend_shape_track_interpolate(0, 0.6, &r_blend) == OK); - CHECK(Math::is_equal_approx(r_blend, 1.0f)); + CHECK(r_blend == doctest::Approx(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))); + CHECK(animation->track_get_key_transition(0, 0) == doctest::Approx(real_t(1.0))); + CHECK(animation->track_get_key_transition(0, 1) == doctest::Approx(real_t(1.0))); // This is a blend shape track, so the methods below should return errors. ERR_PRINT_OFF; @@ -275,7 +275,7 @@ TEST_CASE("[Animation] Create blend shape track") { 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->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0)); ERR_PRINT_ON; } @@ -289,15 +289,15 @@ TEST_CASE("[Animation] Create Bezier track") { 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(animation->bezier_track_get_key_value(0, 0) == doctest::Approx(real_t(-1.0))); + CHECK(animation->bezier_track_get_key_value(0, 1) == doctest::Approx(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))); + CHECK(animation->bezier_track_interpolate(0, -0.2) == doctest::Approx(real_t(-1.0))); + CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(real_t(-1.0))); + CHECK(animation->bezier_track_interpolate(0, 0.2) == doctest::Approx(real_t(-0.76057207584381))); + CHECK(animation->bezier_track_interpolate(0, 0.4) == doctest::Approx(real_t(-0.39975279569626))); + CHECK(animation->bezier_track_interpolate(0, 0.5) == doctest::Approx(real_t(1.0))); + CHECK(animation->bezier_track_interpolate(0, 0.6) == doctest::Approx(real_t(1.0))); // This is a bezier track, so the methods below should return errors. ERR_PRINT_OFF; diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h index 4ba431dfc2..c84c66b0e6 100644 --- a/tests/scene/test_audio_stream_wav.h +++ b/tests/scene/test_audio_stream_wav.h @@ -138,7 +138,7 @@ void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, CHECK(stream->get_data() == test_data); SUBCASE("Stream length is computed properly") { - CHECK(Math::is_equal_approx(stream->get_length(), double(wav_count / wav_rate))); + CHECK(stream->get_length() == doctest::Approx(double(wav_count / wav_rate))); } SUBCASE("Stream can be saved as .wav") { diff --git a/tests/scene/test_bit_map.h b/tests/scene/test_bit_map.h index aca7e5fe22..dc47bd7863 100644 --- a/tests/scene/test_bit_map.h +++ b/tests/scene/test_bit_map.h @@ -434,6 +434,37 @@ TEST_CASE("[BitMap] Clip to polygon") { polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128)); CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon"); CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points"); + + reset_bit_map(bit_map); + bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true); + bit_map.set_bit_rect(Rect2i(64, 64, 64, 64), true); + bit_map.set_bit_rect(Rect2i(192, 128, 64, 64), true); + bit_map.set_bit_rect(Rect2i(128, 192, 64, 64), true); + polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256)); + CHECK_MESSAGE(polygons.size() == 4, "We should have exactly 4 polygons"); + CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points"); + CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points"); + CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points"); + CHECK_MESSAGE(polygons[3].size() == 4, "The polygon should have exactly 4 points"); + + reset_bit_map(bit_map); + bit_map.set_bit(0, 0, true); + bit_map.set_bit(2, 0, true); + bit_map.set_bit_rect(Rect2i(1, 1, 1, 2), true); + polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 3, 3)); + CHECK_MESSAGE(polygons.size() == 3, "We should have exactly 3 polygons"); + CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points"); + CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points"); + CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points"); + + reset_bit_map(bit_map); + bit_map.set_bit_rect(Rect2i(0, 0, 2, 1), true); + bit_map.set_bit_rect(Rect2i(0, 2, 3, 1), true); + bit_map.set_bit(0, 1, true); + bit_map.set_bit(2, 1, true); + polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 4, 4)); + CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon"); + CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points"); } } // namespace TestBitmap diff --git a/tests/scene/test_curve.h b/tests/scene/test_curve.h index ad7625ddc5..36ec0c0a4d 100644 --- a/tests/scene/test_curve.h +++ b/tests/scene/test_curve.h @@ -83,54 +83,54 @@ TEST_CASE("[Curve] Custom curve with free tangents") { Math::is_zero_approx(curve->sample(-0.1)), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.1), (real_t)0.352), + curve->sample(0.1) == doctest::Approx((real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.4), (real_t)0.352), + curve->sample(0.4) == doctest::Approx((real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.7), (real_t)0.896), + curve->sample(0.7) == doctest::Approx((real_t)0.896), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(1), 1), + curve->sample(1) == doctest::Approx(1), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(2), 1), + curve->sample(2) == doctest::Approx(1), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( Math::is_zero_approx(curve->sample_baked(-0.1)), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.1), (real_t)0.352), + curve->sample_baked(0.1) == doctest::Approx((real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.4), (real_t)0.352), + curve->sample_baked(0.4) == doctest::Approx((real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.896), + curve->sample_baked(0.7) == doctest::Approx((real_t)0.896), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(1), 1), + curve->sample_baked(1) == doctest::Approx(1), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(2), 1), + curve->sample_baked(2) == doctest::Approx(1), "Custom free curve should return the expected baked value at offset 0.1."); curve->remove_point(1); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.1), 0), + curve->sample(0.1) == doctest::Approx(0), "Custom free curve should return the expected value at offset 0.1 after removing point at index 1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.1), 0), + curve->sample_baked(0.1) == doctest::Approx(0), "Custom free curve should return the expected baked value at offset 0.1 after removing point at index 1."); curve->clear_points(); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.6), 0), + curve->sample(0.6) == doctest::Approx(0), "Custom free curve should return the expected value at offset 0.6 after clearing all points."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.6), 0), + curve->sample_baked(0.6) == doctest::Approx(0), "Custom free curve should return the expected baked value at offset 0.6 after clearing all points."); } @@ -143,7 +143,7 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { curve->add_point(Vector2(0.75, 1), 0, 0, Curve::TangentMode::TANGENT_LINEAR, Curve::TangentMode::TANGENT_LINEAR); CHECK_MESSAGE( - Math::is_equal_approx(curve->get_point_left_tangent(3), 4), + curve->get_point_left_tangent(3) == doctest::Approx(4), "get_point_left_tangent() should return the expected value for point index 3."); CHECK_MESSAGE( Math::is_zero_approx(curve->get_point_right_tangent(3)), @@ -172,48 +172,48 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { Math::is_zero_approx(curve->sample(-0.1)), "Custom linear curve should return the expected value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.1), (real_t)0.4), + curve->sample(0.1) == doctest::Approx((real_t)0.4), "Custom linear curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.4), (real_t)0.4), + curve->sample(0.4) == doctest::Approx((real_t)0.4), "Custom linear curve should return the expected value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.7), (real_t)0.8), + curve->sample(0.7) == doctest::Approx((real_t)0.8), "Custom linear curve should return the expected value at offset 0.7."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(1), 1), + curve->sample(1) == doctest::Approx(1), "Custom linear curve should return the expected value at offset 1.0."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(2), 1), + curve->sample(2) == doctest::Approx(1), "Custom linear curve should return the expected value at offset 2.0."); CHECK_MESSAGE( Math::is_zero_approx(curve->sample_baked(-0.1)), "Custom linear curve should return the expected baked value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.1), (real_t)0.4), + curve->sample_baked(0.1) == doctest::Approx((real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.4), (real_t)0.4), + curve->sample_baked(0.4) == doctest::Approx((real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.8), + curve->sample_baked(0.7) == doctest::Approx((real_t)0.8), "Custom linear curve should return the expected baked value at offset 0.7."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(1), 1), + curve->sample_baked(1) == doctest::Approx(1), "Custom linear curve should return the expected baked value at offset 1.0."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(2), 1), + curve->sample_baked(2) == doctest::Approx(1), "Custom linear curve should return the expected baked value at offset 2.0."); ERR_PRINT_OFF; curve->remove_point(10); ERR_PRINT_ON; CHECK_MESSAGE( - Math::is_equal_approx(curve->sample(0.7), (real_t)0.8), + curve->sample(0.7) == doctest::Approx((real_t)0.8), "Custom free curve should return the expected value at offset 0.7 after removing point at invalid index 10."); CHECK_MESSAGE( - Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.8), + curve->sample_baked(0.7) == doctest::Approx((real_t)0.8), "Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10."); } diff --git a/tests/scene/test_primitives.h b/tests/scene/test_primitives.h index ceec117700..8bac903d93 100644 --- a/tests/scene/test_primitives.h +++ b/tests/scene/test_primitives.h @@ -57,9 +57,9 @@ TEST_CASE("[SceneTree][Primitive][Capsule] Capsule Primitive") { capsule->set_radial_segments(16); capsule->set_rings(32); - CHECK_MESSAGE(Math::is_equal_approx(capsule->get_radius(), 1.3f), + CHECK_MESSAGE(capsule->get_radius() == doctest::Approx(1.3f), "Get/Set radius work with one set."); - CHECK_MESSAGE(Math::is_equal_approx(capsule->get_height(), 7.1f), + CHECK_MESSAGE(capsule->get_height() == doctest::Approx(7.1f), "Get/Set radius work with one set."); CHECK_MESSAGE(capsule->get_radial_segments() == 16, "Get/Set radius work with one set."); @@ -129,7 +129,7 @@ TEST_CASE("[SceneTree][Primitive][Capsule] Capsule Primitive") { if (normals[ii].y == 0.f) { float mag_of_normal = Math::sqrt(normals[ii].x * normals[ii].x + normals[ii].z * normals[ii].z); Vector3 normalized_normal = normals[ii] / mag_of_normal; - CHECK_MESSAGE(Math::is_equal_approx(point_dist_from_yaxis, radius), + CHECK_MESSAGE(point_dist_from_yaxis == doctest::Approx(radius), "Points on the tube of the capsule are radius away from y-axis."); CHECK_MESSAGE(normalized_normal.is_equal_approx(yaxis_to_point), "Normal points orthogonal from mid cylinder."); @@ -244,9 +244,9 @@ TEST_CASE("[SceneTree][Primitive][Cylinder] Cylinder Primitive") { cylinder->set_cap_top(false); cylinder->set_cap_bottom(false); - CHECK(Math::is_equal_approx(cylinder->get_top_radius(), 4.3f)); - CHECK(Math::is_equal_approx(cylinder->get_bottom_radius(), 1.2f)); - CHECK(Math::is_equal_approx(cylinder->get_height(), 9.77f)); + CHECK(cylinder->get_top_radius() == doctest::Approx(4.3f)); + CHECK(cylinder->get_bottom_radius() == doctest::Approx(1.2f)); + CHECK(cylinder->get_height() == doctest::Approx(9.77f)); CHECK(cylinder->get_radial_segments() == 12); CHECK(cylinder->get_rings() == 16); CHECK(!cylinder->is_cap_top()); @@ -478,7 +478,7 @@ TEST_CASE("[SceneTree][Primitive][Prism] Prism Primitive") { prism->set_subdivide_height(5); prism->set_subdivide_depth(64); - CHECK(Math::is_equal_approx(prism->get_left_to_right(), 3.4f)); + CHECK(prism->get_left_to_right() == doctest::Approx(3.4f)); CHECK(prism->get_size().is_equal_approx(size)); CHECK(prism->get_subdivide_width() == 36); CHECK(prism->get_subdivide_height() == 5); @@ -513,8 +513,8 @@ TEST_CASE("[SceneTree][Primitive][Sphere] Sphere Primitive") { sphere->set_rings(5); sphere->set_is_hemisphere(true); - CHECK(Math::is_equal_approx(sphere->get_radius(), 3.4f)); - CHECK(Math::is_equal_approx(sphere->get_height(), 2.2f)); + CHECK(sphere->get_radius() == doctest::Approx(3.4f)); + CHECK(sphere->get_height() == doctest::Approx(2.2f)); CHECK(sphere->get_radial_segments() == 36); CHECK(sphere->get_rings() == 5); CHECK(sphere->get_is_hemisphere()); @@ -581,8 +581,8 @@ TEST_CASE("[SceneTree][Primitive][Torus] Torus Primitive") { torus->set_rings(19); torus->set_ring_segments(43); - CHECK(Math::is_equal_approx(torus->get_inner_radius(), 3.2f)); - CHECK(Math::is_equal_approx(torus->get_outer_radius(), 9.5f)); + CHECK(torus->get_inner_radius() == doctest::Approx(3.2f)); + CHECK(torus->get_outer_radius() == doctest::Approx(9.5f)); CHECK(torus->get_rings() == 19); CHECK(torus->get_ring_segments() == 43); } @@ -610,8 +610,8 @@ TEST_CASE("[SceneTree][Primitive][TubeTrail] TubeTrail Primitive") { Ref<Curve> curve = memnew(Curve); tube->set_curve(curve); - CHECK(Math::is_equal_approx(tube->get_radius(), 7.2f)); - CHECK(Math::is_equal_approx(tube->get_section_length(), 5.5f)); + CHECK(tube->get_radius() == doctest::Approx(7.2f)); + CHECK(tube->get_section_length() == doctest::Approx(5.5f)); CHECK(tube->get_radial_steps() == 9); CHECK(tube->get_sections() == 33); CHECK(tube->get_section_rings() == 12); @@ -670,8 +670,8 @@ TEST_CASE("[SceneTree][Primitive][RibbonTrail] RibbonTrail Primitive") { ribbon->set_section_segments(9); ribbon->set_curve(curve); - CHECK(Math::is_equal_approx(ribbon->get_size(), 4.3f)); - CHECK(Math::is_equal_approx(ribbon->get_section_length(), 1.3f)); + CHECK(ribbon->get_size() == doctest::Approx(4.3f)); + CHECK(ribbon->get_section_length() == doctest::Approx(1.3f)); CHECK(ribbon->get_sections() == 16); CHECK(ribbon->get_section_segments() == 9); CHECK(ribbon->get_curve() == curve); @@ -781,11 +781,11 @@ TEST_CASE("[SceneTree][Primitive][Text] Text Primitive") { CHECK(text->get_structured_text_bidi_override_options() == options); CHECK(text->is_uppercase() == true); CHECK(text->get_offset() == offset); - CHECK(Math::is_equal_approx(text->get_line_spacing(), 1.7f)); - CHECK(Math::is_equal_approx(text->get_width(), width)); - CHECK(Math::is_equal_approx(text->get_depth(), depth)); - CHECK(Math::is_equal_approx(text->get_curve_step(), curve_step)); - CHECK(Math::is_equal_approx(text->get_pixel_size(), pixel_size)); + CHECK(text->get_line_spacing() == doctest::Approx(1.7f)); + CHECK(text->get_width() == doctest::Approx(width)); + CHECK(text->get_depth() == doctest::Approx(depth)); + CHECK(text->get_curve_step() == doctest::Approx(curve_step)); + CHECK(text->get_pixel_size() == doctest::Approx(pixel_size)); } SUBCASE("[Primitive][Text] Set objects multiple times.") { diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h index e34f2970d4..6d1c2f4f2e 100644 --- a/tests/scene/test_text_edit.h +++ b/tests/scene/test_text_edit.h @@ -734,13 +734,20 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { } SUBCASE("[TextEdit] add selection for next occurrence") { - text_edit->set_text("\ntest other_test\nrandom test\nword test word"); + text_edit->set_text("\ntest other_test\nrandom test\nword test word nonrandom"); text_edit->set_caret_column(0); text_edit->set_caret_line(1); - text_edit->select_word_under_caret(); - CHECK(text_edit->has_selection(0)); + // First selection made by the implicit select_word_under_caret call + text_edit->add_selection_for_next_occurrence(); + CHECK(text_edit->get_caret_count() == 1); CHECK(text_edit->get_selected_text(0) == "test"); + CHECK(text_edit->get_selection_from_line(0) == 1); + CHECK(text_edit->get_selection_from_column(0) == 0); + CHECK(text_edit->get_selection_to_line(0) == 1); + CHECK(text_edit->get_selection_to_column(0) == 4); + CHECK(text_edit->get_caret_line(0) == 1); + CHECK(text_edit->get_caret_column(0) == 4); text_edit->add_selection_for_next_occurrence(); CHECK(text_edit->get_caret_count() == 2); @@ -771,6 +778,27 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { CHECK(text_edit->get_selection_to_column(3) == 9); CHECK(text_edit->get_caret_line(3) == 3); CHECK(text_edit->get_caret_column(3) == 9); + + // A different word with a new manually added caret + text_edit->add_caret(2, 1); + text_edit->select(2, 0, 2, 4, 4); + CHECK(text_edit->get_selected_text(4) == "rand"); + + text_edit->add_selection_for_next_occurrence(); + CHECK(text_edit->get_caret_count() == 6); + CHECK(text_edit->get_selected_text(5) == "rand"); + CHECK(text_edit->get_selection_from_line(5) == 3); + CHECK(text_edit->get_selection_from_column(5) == 18); + CHECK(text_edit->get_selection_to_line(5) == 3); + CHECK(text_edit->get_selection_to_column(5) == 22); + CHECK(text_edit->get_caret_line(5) == 3); + CHECK(text_edit->get_caret_column(5) == 22); + + // Make sure the previous selections are still active + CHECK(text_edit->get_selected_text(0) == "test"); + CHECK(text_edit->get_selected_text(1) == "test"); + CHECK(text_edit->get_selected_text(2) == "test"); + CHECK(text_edit->get_selected_text(3) == "test"); } SUBCASE("[TextEdit] deselect on focus loss") { @@ -3233,8 +3261,8 @@ TEST_CASE("[SceneTree][TextEdit] mouse") { CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y - 100), false) == Point2i(90, 0)); CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y)) == Point2i(90, 0)); - CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y + 100)) == Point2i(141, 0)); - CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y + 100)) == Point2i(141, 0)); + CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y + 100)) == Point2i(140, 0)); + CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y + 100)) == Point2i(140, 0)); CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x, end_pos.y - 100)) == Point2i(104, 0)); CHECK(text_edit->get_line_column_at_pos(Point2i(end_pos.x - 100, end_pos.y - 100)) == Point2i(90, 0)); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 45d6a16cb4..d58c19ac32 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -47,6 +47,7 @@ #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_funcs.h" #include "tests/core/math/test_plane.h" #include "tests/core/math/test_quaternion.h" #include "tests/core/math/test_random_number_generator.h" @@ -191,11 +192,8 @@ struct GodotTestCaseListener : public doctest::IReporter { String name = String(p_in.m_name); if (name.find("[SceneTree]") != -1) { - GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); memnew(MessageQueue); - GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); - memnew(Input); Error err = OK; |