diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_color.h | 6 | ||||
| -rw-r--r-- | tests/test_command_queue.h | 4 | ||||
| -rw-r--r-- | tests/test_curve.h | 28 | ||||
| -rw-r--r-- | tests/test_dictionary.h | 159 | ||||
| -rw-r--r-- | tests/test_expression.h | 24 | ||||
| -rw-r--r-- | tests/test_geometry_2d.h | 10 | ||||
| -rw-r--r-- | tests/test_hashing_context.h | 165 | ||||
| -rw-r--r-- | tests/test_image.h | 20 | ||||
| -rw-r--r-- | tests/test_json.h | 4 | ||||
| -rw-r--r-- | tests/test_list.h | 2 | ||||
| -rw-r--r-- | tests/test_main.cpp | 38 | ||||
| -rw-r--r-- | tests/test_math.cpp | 4 | ||||
| -rw-r--r-- | tests/test_path_3d.h | 85 | ||||
| -rw-r--r-- | tests/test_pck_packer.h | 8 | ||||
| -rw-r--r-- | tests/test_physics_2d.cpp | 11 | ||||
| -rw-r--r-- | tests/test_physics_3d.cpp | 19 | ||||
| -rw-r--r-- | tests/test_rect2.h | 12 | ||||
| -rw-r--r-- | tests/test_render.cpp | 4 | ||||
| -rw-r--r-- | tests/test_shader_lang.cpp | 2 | ||||
| -rw-r--r-- | tests/test_string.h | 40 | ||||
| -rw-r--r-- | tests/test_text_server.h | 3 | ||||
| -rw-r--r-- | tests/test_translation.h | 150 | ||||
| -rw-r--r-- | tests/test_vector.h | 496 |
23 files changed, 1191 insertions, 103 deletions
diff --git a/tests/test_color.h b/tests/test_color.h index eb8d7dcbd4..ad4a7cd3f2 100644 --- a/tests/test_color.h +++ b/tests/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 / 360.0), + Math::is_equal_approx(dark_blue.get_h(), 240.0f / 360.0f), "The returned HSV hue should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_s(), 1), + Math::is_equal_approx(dark_blue.get_s(), 1.0f), "The returned HSV saturation should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_v(), 0.5), + Math::is_equal_approx(dark_blue.get_v(), 0.5f), "The returned HSV value should match the expected value."); } diff --git a/tests/test_command_queue.h b/tests/test_command_queue.h index b4fa63ad2b..2f0f62f5c8 100644 --- a/tests/test_command_queue.h +++ b/tests/test_command_queue.h @@ -31,14 +31,14 @@ #ifndef TEST_COMMAND_QUEUE_H #define TEST_COMMAND_QUEUE_H -#include "test_command_queue.h" - #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" #if !defined(NO_THREADS) diff --git a/tests/test_curve.h b/tests/test_curve.h index 019941a7ce..3055cfd97b 100644 --- a/tests/test_curve.h +++ b/tests/test_curve.h @@ -83,13 +83,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") { Math::is_equal_approx(curve->interpolate(-0.1), 0), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.1), 0.352), + Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.4), 0.352), + Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.896), + Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.896), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate(1), 1), @@ -102,13 +102,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") { Math::is_equal_approx(curve->interpolate_baked(-0.1), 0), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.1), 0.352), + Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.4), 0.352), + Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.7), 0.896), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.896), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate_baked(1), 1), @@ -172,13 +172,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { Math::is_equal_approx(curve->interpolate(-0.1), 0), "Custom linear curve should return the expected value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.1), 0.4), + Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.4), "Custom linear curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.4), 0.4), + Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.4), "Custom linear curve should return the expected value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.8), + Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8), "Custom linear curve should return the expected value at offset 0.7."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate(1), 1), @@ -191,13 +191,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { Math::is_equal_approx(curve->interpolate_baked(-0.1), 0), "Custom linear curve should return the expected baked value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.1), 0.4), + Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.4), 0.4), + Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8), "Custom linear curve should return the expected baked value at offset 0.7."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate_baked(1), 1), @@ -210,10 +210,10 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { curve->remove_point(10); ERR_PRINT_ON; CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.8), + Math::is_equal_approx(curve->interpolate(0.7), (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->interpolate_baked(0.7), 0.8), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8), "Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10."); } } // namespace TestCurve diff --git a/tests/test_dictionary.h b/tests/test_dictionary.h new file mode 100644 index 0000000000..b94cf36109 --- /dev/null +++ b/tests/test_dictionary.h @@ -0,0 +1,159 @@ +/*************************************************************************/ +/* test_dictionary.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_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 { + +TEST_CASE("[Dictionary] Assignment using bracket notation ([])") { + Dictionary map; + map["Hello"] = 0; + CHECK(int(map["Hello"]) == 0); + map["Hello"] = 3; + CHECK(int(map["Hello"]) == 3); + map["World!"] = 4; + CHECK(int(map["World!"]) == 4); + + // Test non-string keys, since keys can be of any Variant type. + map[12345] = -5; + CHECK(int(map[12345]) == -5); + map[false] = 128; + CHECK(int(map[false]) == 128); + map[Vector2(10, 20)] = 30; + CHECK(int(map[Vector2(10, 20)]) == 30); + map[0] = 400; + CHECK(int(map[0]) == 400); + // Check that assigning 0 doesn't overwrite the value for `false`. + CHECK(int(map[false]) == 128); +} + +TEST_CASE("[Dictionary] == and != operators") { + Dictionary map1; + Dictionary map2; + CHECK(map1 != map2); + map1[1] = 3; + map2 = map1; + CHECK(map1 == map2); +} + +TEST_CASE("[Dictionary] get_key_lists()") { + Dictionary map; + List<Variant> keys; + List<Variant> *ptr = &keys; + map.get_key_list(ptr); + CHECK(keys.is_empty()); + map[1] = 3; + map.get_key_list(ptr); + CHECK(keys.size() == 1); + CHECK(int(keys[0]) == 1); + map[2] = 4; + map.get_key_list(ptr); + CHECK(keys.size() == 3); +} + +TEST_CASE("[Dictionary] get_key_at_index()") { + Dictionary map; + map[4] = 3; + Variant val = map.get_key_at_index(0); + CHECK(int(val) == 4); + map[3] = 1; + val = map.get_key_at_index(0); + CHECK(int(val) == 4); + val = map.get_key_at_index(1); + CHECK(int(val) == 3); +} + +TEST_CASE("[Dictionary] getptr()") { + Dictionary map; + map[1] = 3; + Variant *key = map.getptr(1); + CHECK(int(*key) == 3); + key = map.getptr(2); + CHECK(key == nullptr); +} + +TEST_CASE("[Dictionary] get_valid()") { + Dictionary map; + map[1] = 3; + Variant val = map.get_valid(1); + CHECK(int(val) == 3); +} +TEST_CASE("[Dictionary] get()") { + Dictionary map; + map[1] = 3; + Variant val = map.get(1, -1); + CHECK(int(val) == 3); +} + +TEST_CASE("[Dictionary] size(), empty() and clear()") { + Dictionary map; + CHECK(map.size() == 0); + CHECK(map.is_empty()); + map[1] = 3; + CHECK(map.size() == 1); + CHECK(!map.is_empty()); + map.clear(); + CHECK(map.size() == 0); + CHECK(map.is_empty()); +} + +TEST_CASE("[Dictionary] has() and has_all()") { + Dictionary map; + CHECK(map.has(1) == false); + map[1] = 3; + CHECK(map.has(1)); + Array keys; + keys.push_back(1); + CHECK(map.has_all(keys)); + keys.push_back(2); + CHECK(map.has_all(keys) == false); +} + +TEST_CASE("[Dictionary] keys() and values()") { + Dictionary map; + Array keys = map.keys(); + Array values = map.values(); + CHECK(keys.is_empty()); + CHECK(values.is_empty()); + map[1] = 3; + keys = map.keys(); + values = map.values(); + CHECK(int(keys[0]) == 1); + CHECK(int(values[0]) == 3); +} +} // namespace TestDictionary +#endif // TEST_DICTIONARY_H diff --git a/tests/test_expression.h b/tests/test_expression.h index 0ef60d1a19..cb1d29389f 100644 --- a/tests/test_expression.h +++ b/tests/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(float(expression.execute()), -123.456), + Math::is_equal_approx(double(expression.execute()), -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(float(expression.execute()), 5), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 20.18905), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 200'000), + Math::is_equal_approx(double(expression.execute()), 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(float(expression.execute()), 25), + Math::is_equal_approx(double(expression.execute()), 25), "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(float(expression.execute()), 2), + Math::is_equal_approx(double(expression.execute()), 2), "The expression should return the expected result."); } @@ -176,14 +176,14 @@ 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(float(expression.execute()), 0.48), + Math::is_equal_approx(double(expression.execute()), 0.48), "`snapped(sin(0.5), 0.01)` should return the expected result."); CHECK_MESSAGE( expression.parse("pow(2.0, -2500)") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_zero_approx(float(expression.execute())), + Math::is_zero_approx(double(expression.execute())), "`pow(2.0, -2500)` should return the expected result (asymptotically zero)."); } @@ -410,7 +410,7 @@ TEST_CASE("[Expression] Unusual expressions") { "The expression should parse successfully."); ERR_PRINT_OFF; CHECK_MESSAGE( - Math::is_inf(float(expression.execute())), + Math::is_inf(double(expression.execute())), "`-25.4 / 0` should return inf."); ERR_PRINT_ON; diff --git a/tests/test_geometry_2d.h b/tests/test_geometry_2d.h index ea02d1114f..32d4114a1c 100644 --- a/tests/test_geometry_2d.h +++ b/tests/test_geometry_2d.h @@ -50,7 +50,7 @@ TEST_CASE("[Geometry2D] Point in circle") { CHECK(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.7)); CHECK_FALSE(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.5)); - // This tests points on the edge of the circle. They are treated as beeing inside the circle. + // This tests points on the edge of the circle. They are treated as being inside the circle. // In `is_point_in_triangle` and `is_point_in_polygon` they are treated as being outside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK(Geometry2D::is_point_in_circle(Vector2(1.0, 0.0), Vector2(0, 0), 1.0)); @@ -65,7 +65,7 @@ TEST_CASE("[Geometry2D] Point in triangle") { CHECK(Geometry2D::is_point_in_triangle(Vector2(-3, -2.5), Vector2(-1, -4), Vector2(-3, -2), Vector2(-5, -4))); CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(0, 0), Vector2(1, 4), Vector2(3, 2), Vector2(5, 4))); - // This tests points on the edge of the triangle. They are treated as beeing outside the triangle. + // This tests points on the edge of the triangle. They are treated as being outside the triangle. // In `is_point_in_circle` they are treated as being inside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(1, 1), Vector2(-1, 1), Vector2(0, -1), Vector2(1, 1))); @@ -95,7 +95,7 @@ TEST_CASE("[Geometry2D] Point in polygon") { CHECK(Geometry2D::is_point_in_polygon(Vector2(370, 55), p)); CHECK(Geometry2D::is_point_in_polygon(Vector2(-160, 190), p)); - // This tests points on the edge of the polygon. They are treated as beeing outside the polygon. + // This tests points on the edge of the polygon. They are treated as being outside the polygon. // In `is_point_in_circle` they are treated as being inside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK_FALSE(Geometry2D::is_point_in_polygon(Vector2(68, 112), p)); @@ -113,7 +113,7 @@ TEST_CASE("[Geometry2D] Polygon clockwise") { p.push_back(Vector2(1, 5)); CHECK(Geometry2D::is_polygon_clockwise(p)); - p.invert(); + p.reverse(); CHECK_FALSE(Geometry2D::is_polygon_clockwise(p)); } @@ -227,7 +227,7 @@ TEST_CASE("[Geometry2D] Polygon intersection") { CHECK(r[0][2].is_equal_approx(Point2(160.52632, 92.63157))); } - SUBCASE("[Geometry2D] Intersection with one polygon beeing completly inside the other polygon") { + SUBCASE("[Geometry2D] Intersection with one polygon being completely inside the other polygon") { b.push_back(Point2(80, 100)); b.push_back(Point2(50, 50)); b.push_back(Point2(150, 50)); diff --git a/tests/test_hashing_context.h b/tests/test_hashing_context.h new file mode 100644 index 0000000000..728a5f2cfa --- /dev/null +++ b/tests/test_hashing_context.h @@ -0,0 +1,165 @@ +/*************************************************************************/ +/* test_hashing_context.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_HASHING_CONTEXT_H +#define TEST_HASHING_CONTEXT_H + +#include "core/crypto/hashing_context.h" + +#include "tests/test_macros.h" + +namespace TestHashingContext { + +TEST_CASE("[HashingContext] Default - MD5/SHA1/SHA256") { + HashingContext ctx; + + static const uint8_t md5_expected[] = { + 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e + }; + static const uint8_t sha1_expected[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09 + }; + static const uint8_t sha256_expected[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 + }; + + CHECK(ctx.start(HashingContext::HASH_MD5) == OK); + PackedByteArray result = ctx.finish(); + REQUIRE(result.size() == 16); + CHECK(memcmp(result.ptr(), md5_expected, 16) == 0); + + CHECK(ctx.start(HashingContext::HASH_SHA1) == OK); + result = ctx.finish(); + REQUIRE(result.size() == 20); + CHECK(memcmp(result.ptr(), sha1_expected, 20) == 0); + + CHECK(ctx.start(HashingContext::HASH_SHA256) == OK); + result = ctx.finish(); + REQUIRE(result.size() == 32); + CHECK(memcmp(result.ptr(), sha256_expected, 32) == 0); +} + +TEST_CASE("[HashingContext] Multiple updates - MD5/SHA1/SHA256") { + HashingContext ctx; + const String s = "xyz"; + + const PackedByteArray s_byte_parts[] = { + String("x").to_ascii_buffer(), + String("y").to_ascii_buffer(), + String("z").to_ascii_buffer() + }; + + static const uint8_t md5_expected[] = { + 0xd1, 0x6f, 0xb3, 0x6f, 0x09, 0x11, 0xf8, 0x78, 0x99, 0x8c, 0x13, 0x61, 0x91, 0xaf, 0x70, 0x5e + }; + static const uint8_t sha1_expected[] = { + 0x66, 0xb2, 0x74, 0x17, 0xd3, 0x7e, 0x02, 0x4c, 0x46, 0x52, 0x6c, 0x2f, 0x6d, 0x35, 0x8a, 0x75, + 0x4f, 0xc5, 0x52, 0xf3 + }; + static const uint8_t sha256_expected[] = { + 0x36, 0x08, 0xbc, 0xa1, 0xe4, 0x4e, 0xa6, 0xc4, 0xd2, 0x68, 0xeb, 0x6d, 0xb0, 0x22, 0x60, 0x26, + 0x98, 0x92, 0xc0, 0xb4, 0x2b, 0x86, 0xbb, 0xf1, 0xe7, 0x7a, 0x6f, 0xa1, 0x6c, 0x3c, 0x92, 0x82 + }; + + CHECK(ctx.start(HashingContext::HASH_MD5) == OK); + CHECK(ctx.update(s_byte_parts[0]) == OK); + CHECK(ctx.update(s_byte_parts[1]) == OK); + CHECK(ctx.update(s_byte_parts[2]) == OK); + PackedByteArray result = ctx.finish(); + REQUIRE(result.size() == 16); + CHECK(memcmp(result.ptr(), md5_expected, 16) == 0); + + CHECK(ctx.start(HashingContext::HASH_SHA1) == OK); + CHECK(ctx.update(s_byte_parts[0]) == OK); + CHECK(ctx.update(s_byte_parts[1]) == OK); + CHECK(ctx.update(s_byte_parts[2]) == OK); + result = ctx.finish(); + REQUIRE(result.size() == 20); + CHECK(memcmp(result.ptr(), sha1_expected, 20) == 0); + + CHECK(ctx.start(HashingContext::HASH_SHA256) == OK); + CHECK(ctx.update(s_byte_parts[0]) == OK); + CHECK(ctx.update(s_byte_parts[1]) == OK); + CHECK(ctx.update(s_byte_parts[2]) == OK); + result = ctx.finish(); + REQUIRE(result.size() == 32); + CHECK(memcmp(result.ptr(), sha256_expected, 32) == 0); +} + +TEST_CASE("[HashingContext] Invalid use of start") { + HashingContext ctx; + + ERR_PRINT_OFF; + CHECK_MESSAGE( + ctx.start(static_cast<HashingContext::HashType>(-1)) == ERR_UNAVAILABLE, + "Using invalid hash types should fail."); + ERR_PRINT_ON; + + REQUIRE(ctx.start(HashingContext::HASH_MD5) == OK); + + ERR_PRINT_OFF; + CHECK_MESSAGE( + ctx.start(HashingContext::HASH_MD5) == ERR_ALREADY_IN_USE, + "Calling 'start' twice before 'finish' should fail."); + ERR_PRINT_ON; +} + +TEST_CASE("[HashingContext] Invalid use of update") { + HashingContext ctx; + + ERR_PRINT_OFF; + CHECK_MESSAGE( + ctx.update(PackedByteArray()) == ERR_UNCONFIGURED, + "Calling 'update' before 'start' should fail."); + ERR_PRINT_ON; + + REQUIRE(ctx.start(HashingContext::HASH_MD5) == OK); + + ERR_PRINT_OFF; + CHECK_MESSAGE( + ctx.update(PackedByteArray()) == FAILED, + "Calling 'update' with an empty byte array should fail."); + ERR_PRINT_ON; +} + +TEST_CASE("[HashingContext] Invalid use of finish") { + HashingContext ctx; + + ERR_PRINT_OFF; + CHECK_MESSAGE( + ctx.finish() == PackedByteArray(), + "Calling 'finish' before 'start' should return an empty byte array."); + ERR_PRINT_ON; +} +} // namespace TestHashingContext + +#endif // TEST_HASHING_CONTEXT_H diff --git a/tests/test_image.h b/tests/test_image.h index d73717f5b7..99c2a9380d 100644 --- a/tests/test_image.h +++ b/tests/test_image.h @@ -101,8 +101,8 @@ TEST_CASE("[Image] Saving and loading") { Ref<Image> image_bmp = memnew(Image()); FileAccessRef f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err); PackedByteArray data_bmp; - data_bmp.resize(f_bmp->get_len() + 1); - f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_len()); + data_bmp.resize(f_bmp->get_length() + 1); + f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_length()); CHECK_MESSAGE( image_bmp->load_bmp_from_buffer(data_bmp) == OK, "The BMP image should load successfully."); @@ -111,8 +111,8 @@ TEST_CASE("[Image] Saving and loading") { Ref<Image> image_jpg = memnew(Image()); FileAccessRef f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err); PackedByteArray data_jpg; - data_jpg.resize(f_jpg->get_len() + 1); - f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_len()); + data_jpg.resize(f_jpg->get_length() + 1); + f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_length()); CHECK_MESSAGE( image_jpg->load_jpg_from_buffer(data_jpg) == OK, "The JPG image should load successfully."); @@ -121,8 +121,8 @@ TEST_CASE("[Image] Saving and loading") { Ref<Image> image_webp = memnew(Image()); FileAccessRef f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err); PackedByteArray data_webp; - data_webp.resize(f_webp->get_len() + 1); - f_webp->get_buffer(data_webp.ptrw(), f_webp->get_len()); + data_webp.resize(f_webp->get_length() + 1); + f_webp->get_buffer(data_webp.ptrw(), f_webp->get_length()); CHECK_MESSAGE( image_webp->load_webp_from_buffer(data_webp) == OK, "The WEBP image should load successfully."); @@ -131,8 +131,8 @@ TEST_CASE("[Image] Saving and loading") { Ref<Image> image_png = memnew(Image()); FileAccessRef f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err); PackedByteArray data_png; - data_png.resize(f_png->get_len() + 1); - f_png->get_buffer(data_png.ptrw(), f_png->get_len()); + data_png.resize(f_png->get_length() + 1); + f_png->get_buffer(data_png.ptrw(), f_png->get_length()); CHECK_MESSAGE( image_png->load_png_from_buffer(data_png) == OK, "The PNG image should load successfully."); @@ -141,8 +141,8 @@ TEST_CASE("[Image] Saving and loading") { Ref<Image> image_tga = memnew(Image()); FileAccessRef f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err); PackedByteArray data_tga; - data_tga.resize(f_tga->get_len() + 1); - f_tga->get_buffer(data_tga.ptrw(), f_tga->get_len()); + data_tga.resize(f_tga->get_length() + 1); + f_tga->get_buffer(data_tga.ptrw(), f_tga->get_length()); CHECK_MESSAGE( image_tga->load_tga_from_buffer(data_tga) == OK, "The TGA image should load successfully."); diff --git a/tests/test_json.h b/tests/test_json.h index e652a8fced..f1cb4799dc 100644 --- a/tests/test_json.h +++ b/tests/test_json.h @@ -80,7 +80,7 @@ TEST_CASE("[JSON] Parsing single data types") { err_line == 0, "Parsing an integer number as JSON should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(result, 123'456), + (int)result == 123'456, "Parsing an integer number as JSON should return the expected value."); json.parse("0.123456", result, err_str, err_line); @@ -155,7 +155,7 @@ TEST_CASE("[JSON] Parsing objects (dictionaries)") { dictionary["bugs"] == Variant(), "The parsed JSON should contain the expected values."); CHECK_MESSAGE( - Math::is_equal_approx(Dictionary(dictionary["apples"])["blue"], -20), + (int)Dictionary(dictionary["apples"])["blue"] == -20, "The parsed JSON should contain the expected values."); CHECK_MESSAGE( dictionary["empty_object"].hash() == Dictionary().hash(), diff --git a/tests/test_list.h b/tests/test_list.h index 1c70b6e961..52d5edff70 100644 --- a/tests/test_list.h +++ b/tests/test_list.h @@ -260,7 +260,7 @@ TEST_CASE("[List] Invert") { List<int>::Element *n[4]; populate_integers(list, n, 4); - list.invert(); + list.reverse(); CHECK(list.front()->get() == 3); CHECK(list.front()->next()->get() == 2); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 7e9f8319a0..54327caf3d 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -42,12 +42,14 @@ #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" @@ -61,6 +63,7 @@ #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" @@ -71,8 +74,10 @@ #include "test_shader_lang.h" #include "test_string.h" #include "test_text_server.h" +#include "test_translation.h" #include "test_validate_testing.h" #include "test_variant.h" +#include "test_vector.h" #include "test_xml_parser.h" #include "modules/modules_tests.gen.h" @@ -116,24 +121,27 @@ int test_main(int argc, char *argv[]) { test_args.push_back(arg); } } - // Convert Godot command line arguments back to standard arguments. - char **doctest_args = new char *[test_args.size()]; - for (int x = 0; x < test_args.size(); x++) { - // Operation to convert Godot string to non wchar string. - CharString cs = test_args[x].utf8(); - const char *str = cs.get_data(); - // Allocate the string copy. - doctest_args[x] = new char[strlen(str) + 1]; - // Copy this into memory. - memcpy(doctest_args[x], str, strlen(str) + 1); - } - test_context.applyCommandLine(test_args.size(), doctest_args); + if (test_args.size() > 0) { + // Convert Godot command line arguments back to standard arguments. + char **doctest_args = new char *[test_args.size()]; + for (int x = 0; x < test_args.size(); x++) { + // Operation to convert Godot string to non wchar string. + CharString cs = test_args[x].utf8(); + const char *str = cs.get_data(); + // Allocate the string copy. + doctest_args[x] = new char[strlen(str) + 1]; + // Copy this into memory. + memcpy(doctest_args[x], str, strlen(str) + 1); + } + + test_context.applyCommandLine(test_args.size(), doctest_args); - for (int x = 0; x < test_args.size(); x++) { - delete[] doctest_args[x]; + for (int x = 0; x < test_args.size(); x++) { + delete[] doctest_args[x]; + } + delete[] doctest_args; } - delete[] doctest_args; return test_context.run(); } diff --git a/tests/test_math.cpp b/tests/test_math.cpp index 26c2aa2088..88c32713ed 100644 --- a/tests/test_math.cpp +++ b/tests/test_math.cpp @@ -529,8 +529,8 @@ MainLoop *test() { ERR_FAIL_COND_V_MSG(!fa, nullptr, "Could not open file: " + test); Vector<uint8_t> buf; - int flen = fa->get_len(); - buf.resize(fa->get_len() + 1); + uint64_t flen = fa->get_length(); + buf.resize(fa->get_length() + 1); fa->get_buffer(buf.ptrw(), flen); buf.write[flen] = 0; diff --git a/tests/test_path_3d.h b/tests/test_path_3d.h new file mode 100644 index 0000000000..9961ae6e97 --- /dev/null +++ b/tests/test_path_3d.h @@ -0,0 +1,85 @@ +/*************************************************************************/ +/* test_path_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_PATH_3D_H +#define TEST_PATH_3D_H + +#include "scene/3d/path_3d.h" +#include "scene/resources/curve.h" + +#include "tests/test_macros.h" + +namespace TestPath3D { + +TEST_CASE("[Path3D] Initialization") { + SUBCASE("Path should be empty right after initialization") { + Path3D *test_path = memnew(Path3D); + CHECK(test_path->get_curve() == nullptr); + memdelete(test_path); + } +} + +TEST_CASE("[Path3D] Curve setter and getter") { + SUBCASE("Curve passed to the class should remain the same") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve = memnew(Curve3D); + + test_path->set_curve(curve); + CHECK(test_path->get_curve() == curve); + memdelete(test_path); + } + SUBCASE("Curve passed many times to the class should remain the same") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve = memnew(Curve3D); + + test_path->set_curve(curve); + test_path->set_curve(curve); + test_path->set_curve(curve); + CHECK(test_path->get_curve() == curve); + memdelete(test_path); + } + SUBCASE("Curve rewrite testing") { + Path3D *test_path = memnew(Path3D); + const Ref<Curve3D> &curve1 = memnew(Curve3D); + const Ref<Curve3D> &curve2 = memnew(Curve3D); + + test_path->set_curve(curve1); + test_path->set_curve(curve2); + CHECK_MESSAGE(test_path->get_curve() != curve1, + "After rewrite, second curve should be in class"); + CHECK_MESSAGE(test_path->get_curve() == curve2, + "After rewrite, second curve should be in class"); + memdelete(test_path); + } +} + +} // namespace TestPath3D + +#endif // TEST_PATH_3D diff --git a/tests/test_pck_packer.h b/tests/test_pck_packer.h index 8e4721b821..06e4e64963 100644 --- a/tests/test_pck_packer.h +++ b/tests/test_pck_packer.h @@ -62,10 +62,10 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") { err == OK, "The generated empty PCK file should be opened successfully."); CHECK_MESSAGE( - f->get_len() >= 100, + f->get_length() >= 100, "The generated empty PCK file shouldn't be too small (it should have the PCK header)."); CHECK_MESSAGE( - f->get_len() <= 500, + f->get_length() <= 500, "The generated empty PCK file shouldn't be too large."); } @@ -103,10 +103,10 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") { err == OK, "The generated non-empty PCK file should be opened successfully."); CHECK_MESSAGE( - f->get_len() >= 25000, + f->get_length() >= 25000, "The generated non-empty PCK file should be large enough to actually hold the contents specified above."); CHECK_MESSAGE( - f->get_len() <= 35000, + f->get_length() <= 35000, "The generated non-empty PCK file shouldn't be too large."); } } // namespace TestPCKPacker diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp index 570e1897d6..a9e2e92b34 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/test_physics_2d.cpp @@ -216,10 +216,10 @@ protected: if (mm.is_valid()) { Point2 p = mm->get_position(); - if (mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { ray_to = p; _do_ray_query(); - } else if (mm->get_button_mask() & BUTTON_MASK_RIGHT) { + } else if (mm->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) { ray_from = p; _do_ray_query(); } @@ -243,9 +243,7 @@ protected: Size2 imgsize(5, 5); //vs->texture_get_width(body_shape_data[p_shape].image), vs->texture_get_height(body_shape_data[p_shape].image)); vs->canvas_item_add_texture_rect(sprite, Rect2(-imgsize / 2.0, imgsize), body_shape_data[p_shape].image); - ps->body_set_force_integration_callback(body, this, "_body_moved", sprite); - //RID q = ps->query_create(this,"_body_moved",sprite); - //ps->query_body_state(q,body); + ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics2DMainLoop::_body_moved), sprite); return body; } @@ -310,7 +308,6 @@ protected: } static void _bind_methods() { - ClassDB::bind_method(D_METHOD("_body_moved"), &TestPhysics2DMainLoop::_body_moved); ClassDB::bind_method(D_METHOD("_ray_query_callback"), &TestPhysics2DMainLoop::_ray_query_callback); } @@ -323,7 +320,7 @@ public: ps->space_set_active(space, true); ps->set_active(true); ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1)); - ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 98); + ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 980); { RID vp = vs->viewport_create(); diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp index 74afbad9d1..727c44b3ac 100644 --- a/tests/test_physics_3d.cpp +++ b/tests/test_physics_3d.cpp @@ -30,8 +30,8 @@ #include "test_physics_3d.h" +#include "core/math/convex_hull.h" #include "core/math/math_funcs.h" -#include "core/math/quick_hull.h" #include "core/os/main_loop.h" #include "core/os/os.h" #include "core/string/print_string.h" @@ -77,10 +77,6 @@ class TestPhysics3DMainLoop : public MainLoop { bool quit; protected: - static void _bind_methods() { - ClassDB::bind_method("body_changed_transform", &TestPhysics3DMainLoop::body_changed_transform); - } - RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) { RenderingServer *vs = RenderingServer::get_singleton(); PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); @@ -93,7 +89,7 @@ protected: ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0); //todo set space ps->body_add_shape(body, type_shape_map[p_shape]); - ps->body_set_force_integration_callback(body, this, "body_changed_transform", mesh_instance); + ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance); ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location); bodies.push_back(body); @@ -173,7 +169,7 @@ protected: RID convex_mesh = vs->mesh_create(); Geometry3D::MeshData convex_data = Geometry3D::build_convex_mesh(convex_planes); - QuickHull::build(convex_data.vertices, convex_data); + ConvexHullComputer::convex_hull(convex_data.vertices, convex_data); vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data); type_mesh_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_mesh; @@ -187,8 +183,10 @@ protected: RenderingServer *vs = RenderingServer::get_singleton(); PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON); - ps->shape_set_data(trimesh_shape, p_faces); - p_faces = ps->shape_get_data(trimesh_shape); // optimized one + Dictionary trimesh_params; + trimesh_params["faces"] = p_faces; + trimesh_params["backface_collision"] = false; + ps->shape_set_data(trimesh_shape, trimesh_params); Vector<Vector3> normals; // for drawing for (int i = 0; i < p_faces.size() / 3; i++) { Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]); @@ -368,8 +366,7 @@ public: ps->body_set_space(character, space); //todo add space ps->body_add_shape(character, capsule_shape); - - ps->body_set_force_integration_callback(character, this, "body_changed_transform", mesh_instance); + ps->body_set_force_integration_callback(character, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance); ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2))); bodies.push_back(character); diff --git a/tests/test_rect2.h b/tests/test_rect2.h index b94a8b7d05..821aa69970 100644 --- a/tests/test_rect2.h +++ b/tests/test_rect2.h @@ -144,7 +144,7 @@ TEST_CASE("[Rect2] Absolute coordinates") { "abs() should return the expected Rect2."); } -TEST_CASE("[Rect2] Intersecton") { +TEST_CASE("[Rect2] Intersection") { CHECK_MESSAGE( Rect2(0, 100, 1280, 720).intersection(Rect2(0, 300, 100, 100)).is_equal_approx(Rect2(0, 300, 100, 100)), "intersection() with fully enclosed Rect2 should return the expected result."); @@ -312,19 +312,19 @@ TEST_CASE("[Rect2i] Basic setters") { TEST_CASE("[Rect2i] Area getters") { CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, 1280, 720).get_area(), 921'600), + Rect2i(0, 100, 1280, 720).get_area() == 921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, -1280, -720).get_area(), 921'600), + Rect2i(0, 100, -1280, -720).get_area() == 921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, 1280, -720).get_area(), -921'600), + Rect2i(0, 100, 1280, -720).get_area() == -921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, -1280, 720).get_area(), -921'600), + Rect2i(0, 100, -1280, 720).get_area() == -921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_zero_approx(Rect2i(0, 100, 0, 720).get_area()), + Rect2i(0, 100, 0, 720).get_area() == 0, "get_area() should return the expected value."); CHECK_MESSAGE( diff --git a/tests/test_render.cpp b/tests/test_render.cpp index 72b2840098..9737fd03f3 100644 --- a/tests/test_render.cpp +++ b/tests/test_render.cpp @@ -30,8 +30,8 @@ #include "test_render.h" +#include "core/math/convex_hull.h" #include "core/math/math_funcs.h" -#include "core/math/quick_hull.h" #include "core/os/keyboard.h" #include "core/os/main_loop.h" #include "core/os/os.h" @@ -118,7 +118,7 @@ public: vts.push_back(Vector3(-1, -1, -1)); Geometry3D::MeshData md; - Error err = QuickHull::build(vts, md); + Error err = ConvexHullComputer::convex_hull(vts, md); print_line("ERR: " + itos(err)); test_cube = vs->mesh_create(); vs->mesh_add_surface_from_mesh_data(test_cube, md); diff --git a/tests/test_shader_lang.cpp b/tests/test_shader_lang.cpp index a023f35506..2169350c02 100644 --- a/tests/test_shader_lang.cpp +++ b/tests/test_shader_lang.cpp @@ -344,7 +344,7 @@ MainLoop *test() { Set<String> types; types.insert("spatial"); - Error err = sl.compile(code, dt, rm, types, nullptr); + Error err = sl.compile(code, dt, rm, ShaderLanguage::VaryingFunctionNames(), types, nullptr); if (err) { print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text()); diff --git a/tests/test_string.h b/tests/test_string.h index 17f24fb0d8..6e214574af 100644 --- a/tests/test_string.h +++ b/tests/test_string.h @@ -299,6 +299,7 @@ TEST_CASE("[String] hex_encode_buffer") { TEST_CASE("[String] Substr") { String s = "Killer Baby"; CHECK(s.substr(3, 4) == "ler "); + CHECK(s.substr(3) == "ler Baby"); } TEST_CASE("[String] Find") { @@ -860,10 +861,10 @@ TEST_CASE("[String] match") { } TEST_CASE("[String] IPVX address to string") { - IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); - IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); - IP_Address ip2("fe80::52e5:49ff:fe93:1baf"); - IP_Address ip3("::ffff:192.168.0.1"); + IPAddress ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + IPAddress ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); + IPAddress ip2("fe80::52e5:49ff:fe93:1baf"); + IPAddress ip3("::ffff:192.168.0.1"); String ip4 = "192.168.0.1"; CHECK(ip4.is_valid_ip_address()); @@ -1045,7 +1046,7 @@ TEST_CASE("[String] lstrip and rstrip") { TEST_CASE("[String] ensuring empty string into parse_utf8 passes empty string") { String empty; - CHECK(empty.parse_utf8(NULL, -1)); + CHECK(empty.parse_utf8(nullptr, -1)); } TEST_CASE("[String] Cyrillic to_lower()") { @@ -1156,6 +1157,17 @@ TEST_CASE("[String] uri_encode/unescape") { String s = "Godot Engine:'docs'"; String t = "Godot%20Engine%3A%27docs%27"; + String x1 = "T%C4%93%C5%A1t"; + static const uint8_t u8str[] = { 0x54, 0xC4, 0x93, 0xC5, 0xA1, 0x74, 0x00 }; + String x2 = String::utf8((const char *)u8str); + String x3 = U"Tēšt"; + + CHECK(x1.uri_decode() == x2); + CHECK(x1.uri_decode() == x3); + CHECK((x1 + x3).uri_decode() == (x2 + x3)); // Mixed unicode and URL encoded string, e.g. GTK+ bookmark. + CHECK(x2.uri_encode() == x1); + CHECK(x3.uri_encode() == x1); + CHECK(s.uri_encode() == t); CHECK(t.uri_decode() == s); } @@ -1241,8 +1253,10 @@ TEST_CASE("[String] Trim") { TEST_CASE("[String] Right/Left") { String s = "aaaTestbbb"; // ^ - CHECK(s.right(6) == "tbbb"); + CHECK(s.right(6) == "estbbb"); + CHECK(s.right(-6) == "tbbb"); CHECK(s.left(6) == "aaaTes"); + CHECK(s.left(-6) == "aaaT"); } TEST_CASE("[String] Repeat") { @@ -1318,6 +1332,20 @@ TEST_CASE("[String] humanize_size") { CHECK(String::humanize_size(100523550) == "95.86 MiB"); CHECK(String::humanize_size(5345555000) == "4.97 GiB"); } + +TEST_CASE("[String] validate_node_name") { + String numeric_only = "12345"; + CHECK(numeric_only.validate_node_name() == "12345"); + + String name_with_spaces = "Name with spaces"; + CHECK(name_with_spaces.validate_node_name() == "Name with spaces"); + + String name_with_kana = "Name with kana ゴドツ"; + CHECK(name_with_kana.validate_node_name() == "Name with kana ゴドツ"); + + String name_with_invalid_chars = "Name with invalid characters :.@removed!"; + CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!"); +} } // namespace TestString #endif // TEST_STRING_H diff --git a/tests/test_text_server.h b/tests/test_text_server.h index b0b40447fe..3d700f8ec4 100644 --- a/tests/test_text_server.h +++ b/tests/test_text_server.h @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifdef TOOLS_ENABLED + #ifndef TEST_TEXT_SERVER_H #define TEST_TEXT_SERVER_H @@ -247,3 +249,4 @@ TEST_SUITE("[[TextServer]") { }; // namespace TestTextServer #endif // TEST_TEXT_SERVER_H +#endif // TOOLS_ENABLED diff --git a/tests/test_translation.h b/tests/test_translation.h new file mode 100644 index 0000000000..52ff49bf9b --- /dev/null +++ b/tests/test_translation.h @@ -0,0 +1,150 @@ +/*************************************************************************/ +/* test_translation.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_TRANSLATION_H +#define TEST_TRANSLATION_H + +#include "core/string/optimized_translation.h" +#include "core/string/translation.h" +#include "core/string/translation_po.h" + +#include "thirdparty/doctest/doctest.h" + +namespace TestTranslation { + +TEST_CASE("[Translation] Messages") { + Ref<Translation> translation = memnew(Translation); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + CHECK(translation->get_message("Hello") == "Bonjour"); + + translation->erase_message("Hello"); + // The message no longer exists, so it returns an empty string instead. + CHECK(translation->get_message("Hello") == ""); + + List<StringName> messages; + translation->get_message_list(&messages); + CHECK(translation->get_message_count() == 0); + CHECK(messages.size() == 0); + + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello3", "Bonjour3"); + messages.clear(); + translation->get_message_list(&messages); + CHECK(translation->get_message_count() == 2); + CHECK(messages.size() == 2); + // Messages are stored in a Map, don't assume ordering. + CHECK(messages.find("Hello2")); + CHECK(messages.find("Hello3")); +} + +TEST_CASE("[TranslationPO] Messages with context") { + Ref<TranslationPO> translation = memnew(TranslationPO); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + translation->add_message("Hello", "Salut", "friendly"); + CHECK(translation->get_message("Hello") == "Bonjour"); + CHECK(translation->get_message("Hello", "friendly") == "Salut"); + CHECK(translation->get_message("Hello", "nonexistent_context") == ""); + + // Only remove the message for the default context, not the "friendly" context. + translation->erase_message("Hello"); + // The message no longer exists, so it returns an empty string instead. + CHECK(translation->get_message("Hello") == ""); + CHECK(translation->get_message("Hello", "friendly") == "Salut"); + CHECK(translation->get_message("Hello", "nonexistent_context") == ""); + + List<StringName> messages; + translation->get_message_list(&messages); + + // `get_message_count()` takes all contexts into account. + CHECK(translation->get_message_count() == 1); + // Only the default context is taken into account. + // Since "Hello" is now only present in a non-default context, it is not counted in the list of messages. + CHECK(messages.size() == 0); + + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello2", "Salut2", "friendly"); + translation->add_message("Hello3", "Bonjour3"); + messages.clear(); + translation->get_message_list(&messages); + + // `get_message_count()` takes all contexts into account. + CHECK(translation->get_message_count() == 4); + // Only the default context is taken into account. + CHECK(messages.size() == 2); + // Messages are stored in a Map, don't assume ordering. + CHECK(messages.find("Hello2")); + CHECK(messages.find("Hello3")); +} + +TEST_CASE("[TranslationPO] Plural messages") { + Ref<TranslationPO> translation = memnew(TranslationPO); + translation->set_locale("fr"); + translation->set_plural_rule("Plural-Forms: nplurals=2; plural=(n >= 2);"); + CHECK(translation->get_plural_forms() == 2); + + PackedStringArray plurals; + plurals.push_back("Il y a %d pomme"); + plurals.push_back("Il y a %d pommes"); + translation->add_plural_message("There are %d apples", plurals); + ERR_PRINT_OFF; + // This is invalid, as the number passed to `get_plural_message()` may not be negative. + CHECK(vformat(translation->get_plural_message("There are %d apples", "", -1), -1) == ""); + ERR_PRINT_ON; + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 0), 0) == "Il y a 0 pomme"); + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 1), 1) == "Il y a 1 pomme"); + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 2), 2) == "Il y a 2 pommes"); +} + +TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") { + Ref<Translation> translation = memnew(Translation); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello3", "Bonjour3"); + + Ref<OptimizedTranslation> optimized_translation = memnew(OptimizedTranslation); + optimized_translation->generate(translation); + CHECK(optimized_translation->get_message("Hello") == "Bonjour"); + CHECK(optimized_translation->get_message("Hello2") == "Bonjour2"); + CHECK(optimized_translation->get_message("Hello3") == "Bonjour3"); + CHECK(optimized_translation->get_message("DoesNotExist") == ""); + + List<StringName> messages; + // `get_message_list()` can't return the list of messages stored in an OptimizedTranslation. + optimized_translation->get_message_list(&messages); + CHECK(optimized_translation->get_message_count() == 0); + CHECK(messages.size() == 0); +} + +} // namespace TestTranslation + +#endif // TEST_TRANSLATION_H diff --git a/tests/test_vector.h b/tests/test_vector.h new file mode 100644 index 0000000000..02c56e59f6 --- /dev/null +++ b/tests/test_vector.h @@ -0,0 +1,496 @@ +/*************************************************************************/ +/* test_vector.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_VECTOR_H +#define TEST_VECTOR_H + +#include "core/templates/vector.h" + +#include "tests/test_macros.h" + +namespace TestVector { + +TEST_CASE("[Vector] Push back and append") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + // Alias for `push_back`. + vector.append(4); + + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Append array") { + Vector<int> vector; + vector.push_back(1); + vector.push_back(2); + + Vector<int> vector_other; + vector_other.push_back(128); + vector_other.push_back(129); + vector.append_array(vector_other); + + CHECK(vector.size() == 4); + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 128); + CHECK(vector[3] == 129); +} + +TEST_CASE("[Vector] Insert") { + Vector<int> vector; + vector.insert(0, 2); + vector.insert(0, 8); + vector.insert(2, 5); + vector.insert(1, 5); + vector.insert(0, -2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == -2); + CHECK(vector[1] == 8); + CHECK(vector[2] == 5); + CHECK(vector[3] == 2); + CHECK(vector[4] == 5); +} + +TEST_CASE("[Vector] Ordered insert") { + Vector<int> vector; + vector.ordered_insert(2); + vector.ordered_insert(8); + vector.ordered_insert(5); + vector.ordered_insert(5); + vector.ordered_insert(-2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == -2); + CHECK(vector[1] == 2); + CHECK(vector[2] == 5); + CHECK(vector[3] == 5); + CHECK(vector[4] == 8); +} + +TEST_CASE("[Vector] Insert + Ordered insert") { + Vector<int> vector; + vector.ordered_insert(2); + vector.ordered_insert(8); + vector.insert(0, 5); + vector.ordered_insert(5); + vector.insert(1, -2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == 5); + CHECK(vector[1] == -2); + CHECK(vector[2] == 2); + CHECK(vector[3] == 5); + CHECK(vector[4] == 8); +} + +TEST_CASE("[Vector] Fill large array and modify it") { + Vector<int> vector; + vector.resize(1'000'000); + vector.fill(0x60d07); + + vector.write[200] = 0; + CHECK(vector.size() == 1'000'000); + CHECK(vector[0] == 0x60d07); + CHECK(vector[200] == 0); + CHECK(vector[499'999] == 0x60d07); + CHECK(vector[999'999] == 0x60d07); + vector.remove(200); + CHECK(vector[200] == 0x60d07); + + vector.clear(); + CHECK(vector.size() == 0); +} + +TEST_CASE("[Vector] Copy creation") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + Vector<int> vector_other = Vector<int>(vector); + vector_other.remove(0); + CHECK(vector_other[0] == 1); + CHECK(vector_other[1] == 2); + CHECK(vector_other[2] == 3); + CHECK(vector_other[3] == 4); + + // Make sure the original vector isn't modified. + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Duplicate") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + Vector<int> vector_other = vector.duplicate(); + vector_other.remove(0); + CHECK(vector_other[0] == 1); + CHECK(vector_other[1] == 2); + CHECK(vector_other[2] == 3); + CHECK(vector_other[3] == 4); + + // Make sure the original vector isn't modified. + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Get, set") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + CHECK(vector.get(0) == 0); + CHECK(vector.get(1) == 1); + vector.set(2, 256); + CHECK(vector.get(2) == 256); + CHECK(vector.get(3) == 3); + + ERR_PRINT_OFF; + // Invalid (but should not crash): setting out of bounds. + vector.set(6, 500); + ERR_PRINT_ON; + + CHECK(vector.get(4) == 4); +} + +TEST_CASE("[Vector] To byte array") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(-1); + vector.push_back(2008); + vector.push_back(999999999); + + Vector<uint8_t> byte_array = vector.to_byte_array(); + CHECK(byte_array.size() == 16); + // vector[0] + CHECK(byte_array[0] == 0); + CHECK(byte_array[1] == 0); + CHECK(byte_array[2] == 0); + CHECK(byte_array[3] == 0); + + // vector[1] + CHECK(byte_array[4] == 255); + CHECK(byte_array[5] == 255); + CHECK(byte_array[6] == 255); + CHECK(byte_array[7] == 255); + + // vector[2] + CHECK(byte_array[8] == 216); + CHECK(byte_array[9] == 7); + CHECK(byte_array[10] == 0); + CHECK(byte_array[11] == 0); + + // vector[3] + CHECK(byte_array[12] == 255); + CHECK(byte_array[13] == 201); + CHECK(byte_array[14] == 154); + CHECK(byte_array[15] == 59); +} + +TEST_CASE("[Vector] Subarray") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + 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); +} + +TEST_CASE("[Vector] Find, has") { + Vector<int> vector; + vector.push_back(3); + vector.push_back(1); + vector.push_back(4); + vector.push_back(0); + vector.push_back(2); + + CHECK(vector[0] == 3); + CHECK(vector[1] == 1); + CHECK(vector[2] == 4); + CHECK(vector[3] == 0); + CHECK(vector[4] == 2); + + CHECK(vector.find(0) == 3); + CHECK(vector.find(1) == 1); + CHECK(vector.find(2) == 4); + CHECK(vector.find(3) == 0); + CHECK(vector.find(4) == 2); + + CHECK(vector.find(-1) == -1); + CHECK(vector.find(5) == -1); + + CHECK(vector.has(0)); + CHECK(vector.has(1)); + CHECK(vector.has(2)); + CHECK(vector.has(3)); + CHECK(vector.has(4)); + + CHECK(!vector.has(-1)); + CHECK(!vector.has(5)); +} + +TEST_CASE("[Vector] Remove") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + vector.remove(0); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 3); + CHECK(vector[3] == 4); + + vector.remove(2); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 4); + + vector.remove(1); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 4); + + vector.remove(0); + + CHECK(vector[0] == 4); +} + +TEST_CASE("[Vector] Remove and find") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + CHECK(vector.size() == 5); + + vector.remove(0); + + CHECK(vector.size() == 4); + + CHECK(vector.find(0) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(2) != -1); + CHECK(vector.find(3) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(3)); + + CHECK(vector.size() == 3); + + CHECK(vector.find(3) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(2) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(2)); + + CHECK(vector.size() == 2); + + CHECK(vector.find(2) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(4)); + + CHECK(vector.size() == 1); + + CHECK(vector.find(4) == -1); + CHECK(vector.find(1) != -1); + + vector.remove(0); + + CHECK(vector.is_empty()); + CHECK(vector.size() == 0); +} + +TEST_CASE("[Vector] Erase") { + Vector<int> vector; + vector.push_back(1); + vector.push_back(3); + vector.push_back(0); + vector.push_back(2); + vector.push_back(4); + + CHECK(vector.find(2) == 3); + + vector.erase(2); + + CHECK(vector.find(2) == -1); + CHECK(vector.size() == 4); +} + +TEST_CASE("[Vector] Size, resize, reserve") { + Vector<int> vector; + CHECK(vector.is_empty()); + CHECK(vector.size() == 0); + + vector.resize(10); + + CHECK(vector.size() == 10); + + vector.resize(5); + + CHECK(vector.size() == 5); + + vector.remove(0); + vector.remove(0); + vector.remove(0); + + CHECK(vector.size() == 2); + + vector.clear(); + + CHECK(vector.size() == 0); + CHECK(vector.is_empty()); + + vector.push_back(0); + vector.push_back(0); + vector.push_back(0); + + CHECK(vector.size() == 3); + + vector.push_back(0); + + CHECK(vector.size() == 4); +} + +TEST_CASE("[Vector] Sort") { + Vector<int> vector; + vector.push_back(2); + vector.push_back(8); + vector.push_back(-4); + vector.push_back(5); + vector.sort(); + + CHECK(vector.size() == 4); + CHECK(vector[0] == -4); + CHECK(vector[1] == 2); + CHECK(vector[2] == 5); + CHECK(vector[3] == 8); +} + +TEST_CASE("[Vector] Sort custom") { + Vector<String> vector; + vector.push_back("world"); + vector.push_back("World"); + vector.push_back("Hello"); + vector.push_back("10Hello"); + vector.push_back("12Hello"); + vector.push_back("01Hello"); + vector.push_back("1Hello"); + vector.push_back(".Hello"); + vector.sort_custom<NaturalNoCaseComparator>(); + + CHECK(vector.size() == 8); + CHECK(vector[0] == ".Hello"); + CHECK(vector[1] == "01Hello"); + CHECK(vector[2] == "1Hello"); + CHECK(vector[3] == "10Hello"); + CHECK(vector[4] == "12Hello"); + CHECK(vector[5] == "Hello"); + CHECK(vector[6] == "world"); + CHECK(vector[7] == "World"); +} + +TEST_CASE("[Vector] Operators") { + Vector<int> vector; + vector.push_back(2); + vector.push_back(8); + vector.push_back(-4); + vector.push_back(5); + + Vector<int> vector_other; + vector_other.push_back(2); + vector_other.push_back(8); + vector_other.push_back(-4); + vector_other.push_back(5); + + CHECK(vector == vector_other); + + vector_other.push_back(10); + CHECK(vector != vector_other); +} + +} // namespace TestVector + +#endif // TEST_VECTOR_H |