summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_color.h6
-rw-r--r--tests/test_command_queue.h4
-rw-r--r--tests/test_curve.h28
-rw-r--r--tests/test_dictionary.h159
-rw-r--r--tests/test_expression.h24
-rw-r--r--tests/test_geometry_2d.h10
-rw-r--r--tests/test_hashing_context.h165
-rw-r--r--tests/test_image.h20
-rw-r--r--tests/test_json.h4
-rw-r--r--tests/test_list.h2
-rw-r--r--tests/test_main.cpp38
-rw-r--r--tests/test_math.cpp4
-rw-r--r--tests/test_path_3d.h85
-rw-r--r--tests/test_pck_packer.h8
-rw-r--r--tests/test_physics_2d.cpp11
-rw-r--r--tests/test_physics_3d.cpp19
-rw-r--r--tests/test_rect2.h12
-rw-r--r--tests/test_render.cpp4
-rw-r--r--tests/test_shader_lang.cpp2
-rw-r--r--tests/test_string.h40
-rw-r--r--tests/test_text_server.h3
-rw-r--r--tests/test_translation.h150
-rw-r--r--tests/test_vector.h496
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