summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core/math/test_quaternion.h50
-rw-r--r--tests/core/object/test_object.h6
-rw-r--r--tests/core/string/test_string.h118
-rw-r--r--tests/create_test.py132
-rw-r--r--tests/python_build/conftest.py26
-rw-r--r--tests/python_build/fixtures/gles3/_included.glsl1
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment.glsl34
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl50
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json52
-rw-r--r--tests/python_build/fixtures/glsl/_included.glsl1
-rw-r--r--tests/python_build/fixtures/glsl/compute.glsl12
-rw-r--r--tests/python_build/fixtures/glsl/compute_expected_full.glsl8
-rw-r--r--tests/python_build/fixtures/glsl/compute_expected_parts.json3
-rw-r--r--tests/python_build/fixtures/glsl/vertex_fragment.glsl32
-rw-r--r--tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl8
-rw-r--r--tests/python_build/fixtures/glsl/vertex_fragment_expected_parts.json3
-rw-r--r--tests/python_build/fixtures/rd_glsl/_included.glsl1
-rw-r--r--tests/python_build/fixtures/rd_glsl/compute.glsl13
-rw-r--r--tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl20
-rw-r--r--tests/python_build/fixtures/rd_glsl/compute_expected_parts.json28
-rw-r--r--tests/python_build/fixtures/rd_glsl/vertex_fragment.glsl25
-rw-r--r--tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl23
-rw-r--r--tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_parts.json40
-rw-r--r--tests/python_build/test_gles3_builder.py31
-rw-r--r--tests/python_build/test_glsl_builder.py37
-rw-r--r--tests/scene/test_code_edit.h10
-rw-r--r--tests/scene/test_path_follow_2d.h94
-rw-r--r--tests/scene/test_path_follow_3d.h94
28 files changed, 816 insertions, 136 deletions
diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h
index 94eef6c463..1b80ffba0b 100644
--- a/tests/core/math/test_quaternion.h
+++ b/tests/core/math/test_quaternion.h
@@ -41,9 +41,9 @@
namespace TestQuaternion {
Quaternion quat_euler_yxz_deg(Vector3 angle) {
- double yaw = Math::deg2rad(angle[1]);
- double pitch = Math::deg2rad(angle[0]);
- double roll = Math::deg2rad(angle[2]);
+ double yaw = Math::deg_to_rad(angle[1]);
+ double pitch = Math::deg_to_rad(angle[0]);
+ double roll = Math::deg_to_rad(angle[2]);
// Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler
// constructor and quaternion product, both tested separately.
@@ -77,7 +77,7 @@ TEST_CASE("[Quaternion] Construct x,y,z,w") {
TEST_CASE("[Quaternion] Construct AxisAngle 1") {
// Easy to visualize: 120 deg about X-axis.
- Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0));
// 0.866 isn't close enough; doctest::Approx doesn't cut much slack!
CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle.
@@ -88,7 +88,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 1") {
TEST_CASE("[Quaternion] Construct AxisAngle 2") {
// Easy to visualize: 30 deg about Y-axis.
- Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+ Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0));
CHECK(q[0] == doctest::Approx(0.0));
CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle.
@@ -98,7 +98,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 2") {
TEST_CASE("[Quaternion] Construct AxisAngle 3") {
// Easy to visualize: 60 deg about Z-axis.
- Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+ Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0));
CHECK(q[0] == doctest::Approx(0.0));
CHECK(q[1] == doctest::Approx(0.0));
@@ -109,7 +109,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") {
TEST_CASE("[Quaternion] Construct AxisAngle 4") {
// More complex & hard to visualize, so test w/ data from online calculator.
Vector3 axis(1.0, 2.0, 0.5);
- Quaternion q(axis.normalized(), Math::deg2rad(35.0));
+ Quaternion q(axis.normalized(), Math::deg_to_rad(35.0));
CHECK(q[0] == doctest::Approx(0.131239));
CHECK(q[1] == doctest::Approx(0.262478));
@@ -119,7 +119,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") {
TEST_CASE("[Quaternion] Construct from Quaternion") {
Vector3 axis(1.0, 2.0, 0.5);
- Quaternion q_src(axis.normalized(), Math::deg2rad(35.0));
+ Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0));
Quaternion q(q_src);
CHECK(q[0] == doctest::Approx(0.131239));
@@ -129,9 +129,9 @@ TEST_CASE("[Quaternion] Construct from Quaternion") {
}
TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
Quaternion q_y(euler_y);
@@ -156,9 +156,9 @@ TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
}
TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
// Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler
// constructor and quaternion product, both tested separately.
@@ -187,9 +187,9 @@ TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
}
TEST_CASE("[Quaternion] Construct Basis Euler") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_yxz(pitch, yaw, roll);
Quaternion q_yxz(euler_yxz);
Basis basis_axes(euler_yxz);
@@ -199,7 +199,7 @@ TEST_CASE("[Quaternion] Construct Basis Euler") {
TEST_CASE("[Quaternion] Construct Basis Axes") {
// Arbitrary Euler angles.
- Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
// Basis vectors from online calculation of rotation matrix.
Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
@@ -248,9 +248,9 @@ TEST_CASE("[Quaternion] Product (book)") {
}
TEST_CASE("[Quaternion] Product") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
Quaternion q_y(euler_y);
@@ -292,7 +292,7 @@ TEST_CASE("[Quaternion] Product") {
TEST_CASE("[Quaternion] xform unit vectors") {
// Easy to visualize: 120 deg about X-axis.
// Transform the i, j, & k unit vectors.
- Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0));
Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0));
Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0));
Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -305,7 +305,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
CHECK(k_t.length_squared() == doctest::Approx(1.0));
// Easy to visualize: 30 deg about Y-axis.
- q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+ q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0));
i_t = q.xform(Vector3(1.0, 0.0, 0.0));
j_t = q.xform(Vector3(0.0, 1.0, 0.0));
k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -318,7 +318,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
CHECK(k_t.length_squared() == doctest::Approx(1.0));
// Easy to visualize: 60 deg about Z-axis.
- q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+ q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0));
i_t = q.xform(Vector3(1.0, 0.0, 0.0));
j_t = q.xform(Vector3(0.0, 1.0, 0.0));
k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -333,7 +333,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
TEST_CASE("[Quaternion] xform vector") {
// Arbitrary quaternion rotates an arbitrary vector.
- Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
Basis basis_axes(euler_yzx);
Quaternion q(basis_axes);
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 88a3e4ccad..f5c5de7fdf 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -82,6 +82,12 @@ public:
Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override {
return Variant::PACKED_FLOAT32_ARRAY;
}
+ bool property_can_revert(const StringName &p_name) const override {
+ return false;
+ };
+ bool property_get_revert(const StringName &p_name, Variant &r_ret) const override {
+ return false;
+ };
void get_method_list(List<MethodInfo> *p_list) const override {
}
bool has_method(const StringName &p_method) const override {
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 8914dbfd9a..62d2051eee 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -619,7 +619,7 @@ TEST_CASE("[String] sprintf") {
output = format.sprintf(args, &error);
REQUIRE(error == false);
CHECK(output == String("fish % frog"));
- //////// INTS
+ ///// Ints
// Int
format = "fish %d frog";
@@ -727,7 +727,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish 143 frog"));
- ////// REALS
+ ///// Reals
// Real
format = "fish %f frog";
@@ -737,7 +737,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish 99.990000 frog"));
- // Real left-padded
+ // Real left-padded.
format = "fish %11f frog";
args.clear();
args.push_back(99.99);
@@ -745,7 +745,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish 99.990000 frog"));
- // Real right-padded
+ // Real right-padded.
format = "fish %-11f frog";
args.clear();
args.push_back(99.99);
@@ -769,7 +769,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish +99.990000 frog"));
- // Real with 1 decimals.
+ // Real with 1 decimal.
format = "fish %.1f frog";
args.clear();
args.push_back(99.99);
@@ -803,7 +803,97 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish -99.990000 frog"));
- /////// Strings.
+ ///// Vectors
+
+ // Vector2
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector2(19.99, 1.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000) frog"));
+
+ // Vector3
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000, -2.050000) frog"));
+
+ // Vector4
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector4(19.99, 1.00, -2.05, 5.5)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000, 1.000000, -2.050000, 5.500000) frog"));
+
+ // Vector with negative values.
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector2(-19.99, -1.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (-19.990000, -1.000000) frog"));
+
+ // Vector left-padded.
+ format = "fish %11v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish ( 19.990000, 1.000000, -2.050000) frog"));
+
+ // Vector right-padded.
+ format = "fish %-11v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.990000 , 1.000000 , -2.050000 ) frog"));
+
+ // Vector left-padded with zeros.
+ format = "fish %011v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (0019.990000, 0001.000000, -002.050000) frog"));
+
+ // Vector given Vector3i.
+ format = "fish %v frog";
+ args.clear();
+ args.push_back(Variant(Vector3i(19, 1, -2)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.000000, 1.000000, -2.000000) frog"));
+
+ // Vector with 1 decimal.
+ format = "fish %.1v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (20.0, 1.0, -2.0) frog"));
+
+ // Vector with 12 decimals.
+ format = "fish %.12v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.00, 1.00, -2.00)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (19.000000000000, 1.000000000000, -2.000000000000) frog"));
+
+ // Vector with no decimals.
+ format = "fish %.v frog";
+ args.clear();
+ args.push_back(Variant(Vector3(19.99, 1.00, -2.05)));
+ output = format.sprintf(args, &error);
+ REQUIRE(error == false);
+ CHECK(output == String("fish (20, 1, -2) frog"));
+
+ ///// Strings
// String
format = "fish %s frog";
@@ -813,7 +903,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish cheese frog"));
- // String left-padded
+ // String left-padded.
format = "fish %10s frog";
args.clear();
args.push_back("cheese");
@@ -821,7 +911,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
CHECK(output == String("fish cheese frog"));
- // String right-padded
+ // String right-padded.
format = "fish %-10s frog";
args.clear();
args.push_back("cheese");
@@ -849,7 +939,7 @@ TEST_CASE("[String] sprintf") {
///// Dynamic width
- // String dynamic width
+ // String dynamic width.
format = "fish %*s frog";
args.clear();
args.push_back(10);
@@ -858,7 +948,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
REQUIRE(output == String("fish cheese frog"));
- // Int dynamic width
+ // Int dynamic width.
format = "fish %*d frog";
args.clear();
args.push_back(10);
@@ -867,7 +957,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error == false);
REQUIRE(output == String("fish 99 frog"));
- // Float dynamic width
+ // Float dynamic width.
format = "fish %*.*f frog";
args.clear();
args.push_back(10);
@@ -904,7 +994,7 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error);
CHECK(output == "incomplete format");
- // Bad character in format string
+ // Bad character in format string.
format = "fish %&f frog";
args.clear();
args.push_back("cheese");
@@ -920,14 +1010,14 @@ TEST_CASE("[String] sprintf") {
REQUIRE(error);
CHECK(output == "too many decimal points in format");
- // * not a number
+ // * not a number or vector.
format = "fish %*f frog";
args.clear();
args.push_back("cheese");
args.push_back(99.99);
output = format.sprintf(args, &error);
REQUIRE(error);
- CHECK(output == "* wants number");
+ CHECK(output == "* wants number or vector");
// Character too long.
format = "fish %c frog";
diff --git a/tests/create_test.py b/tests/create_test.py
new file mode 100644
index 0000000000..5a0439084f
--- /dev/null
+++ b/tests/create_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import re
+import sys
+from subprocess import call
+
+
+def main():
+ # Change to the directory where the script is located,
+ # so that the script can be run from any location.
+ os.chdir(os.path.dirname(os.path.realpath(__file__)))
+
+ parser = argparse.ArgumentParser(description="Creates a new unit test file.")
+ parser.add_argument("name", type=str, help="The unit test name in PascalCase notation")
+ parser.add_argument(
+ "path",
+ type=str,
+ nargs="?",
+ help="The path to the unit test file relative to the tests folder (default: .)",
+ default=".",
+ )
+ parser.add_argument(
+ "-i",
+ "--invasive",
+ action="store_true",
+ help="if set, the script will automatically insert the include directive in test_main.cpp. Use with caution!",
+ )
+ args = parser.parse_args()
+
+ snake_case_regex = re.compile(r"(?<!^)(?=[A-Z])")
+ name_snake_case = snake_case_regex.sub("_", args.name).lower()
+
+ file_path = os.path.normpath(os.path.join(args.path, f"test_{name_snake_case}.h"))
+
+ print(file_path)
+ if os.path.isfile(file_path):
+ print(f'ERROR: The file "{file_path}" already exists.')
+ sys.exit(1)
+ with open(file_path, "w") as file:
+ file.write(
+ """/*************************************************************************/
+/* test_{name_snake_case}.h {padding} */
+/*************************************************************************/
+/* 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_{name_upper_snake_case}_H
+#define TEST_{name_upper_snake_case}_H
+
+#include "tests/test_macros.h"
+
+namespace Test{name_pascal_case} {{
+
+TEST_CASE("[{name_pascal_case}] Example test case") {{
+ // TODO: Remove this comment and write your test code here.
+}}
+
+}} // namespace Test{name_pascal_case}
+
+#endif // TEST_{name_upper_snake_case}_H
+""".format(
+ name_snake_case=name_snake_case,
+ # Capitalize the first letter but keep capitalization for the rest of the string.
+ # This is done in case the user passes a camelCase string instead of PascalCase.
+ name_pascal_case=args.name[0].upper() + args.name[1:],
+ name_upper_snake_case=name_snake_case.upper(),
+ # The padding length depends on the test name length.
+ padding=" " * (60 - len(name_snake_case)),
+ )
+ )
+
+ # Print an absolute path so it can be Ctrl + clicked in some IDEs and terminal emulators.
+ print("Test header file created:")
+ print(os.path.abspath(file_path))
+
+ if args.invasive:
+ print("Trying to insert include directive in test_main.cpp...")
+ with open("test_main.cpp", "r") as file:
+ contents = file.read()
+ match = re.search(r'#include "tests.*\n', contents)
+
+ if match:
+ new_string = contents[: match.start()] + f'#include "tests/{file_path}"\n' + contents[match.start() :]
+
+ with open("test_main.cpp", "w") as file:
+ file.write(new_string)
+ print("Done.")
+ # Use clang format to sort include directives afster insertion.
+ clang_format_args = ["clang-format", "test_main.cpp", "-i"]
+ retcode = call(clang_format_args)
+ if retcode != 0:
+ print(
+ "Include directives in test_main.cpp could not be sorted automatically using clang-format. Please sort them manually."
+ )
+ else:
+ print("Could not find a valid position in test_main.cpp to insert the include directive.")
+
+ else:
+ print("\nRemember to #include the new test header in this file (following alphabetical order):")
+ print(os.path.abspath("test_main.cpp"))
+ print("Insert the following line in the appropriate place:")
+ print(f'#include "tests/{file_path}"')
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/python_build/conftest.py b/tests/python_build/conftest.py
new file mode 100644
index 0000000000..617230926a
--- /dev/null
+++ b/tests/python_build/conftest.py
@@ -0,0 +1,26 @@
+import os
+import sys
+from pathlib import Path
+
+import pytest
+
+CWD = Path(__file__).parent
+ROOT = CWD.parent.parent
+# append directory with build files to sys.path to import them
+sys.path.append(str(ROOT))
+
+
+@pytest.fixture
+def shader_files(request):
+ shader_path = request.param
+
+ res = {
+ "path_input": str(CWD / "fixtures" / f"{shader_path}.glsl"),
+ "path_output": str(CWD / "fixtures" / f"{shader_path}.glsl.gen.h"),
+ "path_expected_full": str(CWD / "fixtures" / f"{shader_path}_expected_full.glsl"),
+ "path_expected_parts": str(CWD / "fixtures" / f"{shader_path}_expected_parts.json"),
+ }
+ yield res
+
+ if not os.getenv("PYTEST_KEEP_GENERATED_FILES"):
+ os.remove(res["path_output"])
diff --git a/tests/python_build/fixtures/gles3/_included.glsl b/tests/python_build/fixtures/gles3/_included.glsl
new file mode 100644
index 0000000000..adf5f702d3
--- /dev/null
+++ b/tests/python_build/fixtures/gles3/_included.glsl
@@ -0,0 +1 @@
+#define M_PI 3.14159265359
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment.glsl b/tests/python_build/fixtures/gles3/vertex_fragment.glsl
new file mode 100644
index 0000000000..3004e22f25
--- /dev/null
+++ b/tests/python_build/fixtures/gles3/vertex_fragment.glsl
@@ -0,0 +1,34 @@
+#include "_included.glsl"
+
+#[modes]
+
+mode_ninepatch = #define USE_NINEPATCH
+
+#[specializations]
+
+DISABLE_LIGHTING = false
+
+#[vertex]
+
+precision highp float;
+precision highp int;
+
+layout(location = 0) in highp vec3 vertex;
+
+out highp vec4 position_interp;
+
+void main() {
+ position_interp = vec4(vertex.x,1,0,1);
+}
+
+#[fragment]
+
+precision highp float;
+precision highp int;
+
+in highp vec4 position_interp;
+
+void main() {
+ highp float depth = ((position_interp.z / position_interp.w) + 1.0);
+ frag_color = vec4(depth);
+}
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
new file mode 100644
index 0000000000..7bf56e73cd
--- /dev/null
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
@@ -0,0 +1,50 @@
+/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
+#ifndef VERTEX_FRAGMENT_GLSL_GEN_HGLES3_GLES3
+#define VERTEX_FRAGMENT_GLSL_GEN_HGLES3_GLES3
+
+
+#include "drivers/gles3/shader_gles3.h"
+
+
+class VertexFragmentShaderGLES3 : public ShaderGLES3 {
+
+public:
+
+ enum ShaderVariant {
+ MODE_NINEPATCH,
+ };
+
+ enum Specializations {
+ DISABLE_LIGHTING=1,
+ };
+
+ _FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { _version_bind_shader(p_version,p_variant,p_specialization); }
+
+protected:
+
+ virtual void _init() override {
+
+ static const char **_uniform_strings=nullptr;
+ static const char* _variant_defines[]={
+ "#define USE_NINEPATCH",
+ };
+
+ static TexUnitPair *_texunit_pairs=nullptr;
+ static UBOPair *_ubo_pairs=nullptr;
+ static Specialization _spec_pairs[]={
+ {"DISABLE_LIGHTING",false},
+ };
+
+ static const char _vertex_code[]={
+10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,51,32,118,101,114,116,101,120,59,10,10,111,117,116,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,32,61,32,118,101,99,52,40,118,101,114,116,101,120,46,120,44,49,44,48,44,49,41,59,10,125,10,10, 0};
+
+ static const char _fragment_code[]={
+10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,105,110,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,104,105,103,104,112,32,102,108,111,97,116,32,100,101,112,116,104,32,61,32,40,40,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,122,32,47,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,119,41,32,43,32,49,46,48,41,59,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,101,112,116,104,41,59,10,125,10, 0};
+
+ _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
+ }
+
+};
+
+#endif
+
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
new file mode 100644
index 0000000000..eaeb5981c0
--- /dev/null
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
@@ -0,0 +1,52 @@
+{
+ "vertex_lines": [
+ "",
+ "precision highp float;",
+ "precision highp int;",
+ "",
+ "layout(location = 0) in highp vec3 vertex;",
+ "",
+ "out highp vec4 position_interp;",
+ "",
+ "void main() {",
+ "\tposition_interp = vec4(vertex.x,1,0,1);",
+ "}",
+ ""
+ ],
+ "fragment_lines": [
+ "",
+ "precision highp float;",
+ "precision highp int;",
+ "",
+ "in highp vec4 position_interp;",
+ "",
+ "void main() {",
+ "\thighp float depth = ((position_interp.z / position_interp.w) + 1.0);",
+ "\tfrag_color = vec4(depth);",
+ "}"
+ ],
+ "uniforms": [],
+ "fbos": [],
+ "texunits": [],
+ "texunit_names": [],
+ "ubos": [],
+ "ubo_names": [],
+ "vertex_included_files": [],
+ "fragment_included_files": [],
+ "reading": "fragment",
+ "line_offset": 33,
+ "vertex_offset": 10,
+ "fragment_offset": 23,
+ "variant_defines": [
+ "#define USE_NINEPATCH"
+ ],
+ "variant_names": [
+ "MODE_NINEPATCH"
+ ],
+ "specialization_names": [
+ "DISABLE_LIGHTING"
+ ],
+ "specialization_values": [
+ " false\n"
+ ]
+}
diff --git a/tests/python_build/fixtures/glsl/_included.glsl b/tests/python_build/fixtures/glsl/_included.glsl
new file mode 100644
index 0000000000..adf5f702d3
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/_included.glsl
@@ -0,0 +1 @@
+#define M_PI 3.14159265359
diff --git a/tests/python_build/fixtures/glsl/compute.glsl b/tests/python_build/fixtures/glsl/compute.glsl
new file mode 100644
index 0000000000..e81f48d463
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/compute.glsl
@@ -0,0 +1,12 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+
+#include "_included.glsl"
+
+void main() {
+ vec3 static_light = vec3(0, 1, 0);
+}
diff --git a/tests/python_build/fixtures/glsl/compute_expected_full.glsl b/tests/python_build/fixtures/glsl/compute_expected_full.glsl
new file mode 100644
index 0000000000..b937d732c8
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/compute_expected_full.glsl
@@ -0,0 +1,8 @@
+/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
+#ifndef COMPUTE_SHADER_GLSL_RAW_H
+#define COMPUTE_SHADER_GLSL_RAW_H
+
+static const char compute_shader_glsl[] = {
+ 35,91,99,111,109,112,117,116,101,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,118,101,99,51,32,115,116,97,116,105,99,95,108,105,103,104,116,32,61,32,118,101,99,51,40,48,44,32,49,44,32,48,41,59,10,125,10,0
+};
+#endif
diff --git a/tests/python_build/fixtures/glsl/compute_expected_parts.json b/tests/python_build/fixtures/glsl/compute_expected_parts.json
new file mode 100644
index 0000000000..025c568ae0
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/compute_expected_parts.json
@@ -0,0 +1,3 @@
+{
+ "code": "#[compute]\n\n#version 450\n\n#VERSION_DEFINES\n\n\n#define M_PI 3.14159265359\n\nvoid main() {\n\tvec3 static_light = vec3(0, 1, 0);\n}\n"
+}
diff --git a/tests/python_build/fixtures/glsl/vertex_fragment.glsl b/tests/python_build/fixtures/glsl/vertex_fragment.glsl
new file mode 100644
index 0000000000..0bdce783d7
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/vertex_fragment.glsl
@@ -0,0 +1,32 @@
+#[versions]
+
+lines = "#define MODE_LINES";
+
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) out vec3 uv_interp;
+
+void main() {
+
+#ifdef MODE_LINES
+ uv_interp = vec3(0,0,1);
+#endif
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "_included.glsl"
+
+layout(location = 0) out vec4 dst_color;
+
+void main() {
+ dst_color = vec4(1,1,0,0);
+}
diff --git a/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl
new file mode 100644
index 0000000000..3f53a17fac
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/vertex_fragment_expected_full.glsl
@@ -0,0 +1,8 @@
+/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
+#ifndef VERTEX_FRAGMENT_SHADER_GLSL_RAW_H
+#define VERTEX_FRAGMENT_SHADER_GLSL_RAW_H
+
+static const char vertex_fragment_shader_glsl[] = {
+ 35,91,118,101,114,115,105,111,110,115,93,10,10,108,105,110,101,115,32,61,32,34,35,100,101,102,105,110,101,32,77,79,68,69,95,76,73,78,69,83,34,59,10,10,35,91,118,101,114,116,101,120,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,51,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,35,105,102,100,101,102,32,77,79,68,69,95,76,73,78,69,83,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,51,40,48,44,48,44,49,41,59,10,35,101,110,100,105,102,10,125,10,10,35,91,102,114,97,103,109,101,110,116,93,10,10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,100,115,116,95,99,111,108,111,114,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,100,115,116,95,99,111,108,111,114,32,61,32,118,101,99,52,40,49,44,49,44,48,44,48,41,59,10,125,10,0
+};
+#endif
diff --git a/tests/python_build/fixtures/glsl/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/glsl/vertex_fragment_expected_parts.json
new file mode 100644
index 0000000000..38312367a0
--- /dev/null
+++ b/tests/python_build/fixtures/glsl/vertex_fragment_expected_parts.json
@@ -0,0 +1,3 @@
+{
+ "code": "#[versions]\n\nlines = \"#define MODE_LINES\";\n\n#[vertex]\n\n#version 450\n\n#VERSION_DEFINES\n\nlayout(location = 0) out vec3 uv_interp;\n\nvoid main() {\n\n#ifdef MODE_LINES\n\tuv_interp = vec3(0,0,1);\n#endif\n}\n\n#[fragment]\n\n#version 450\n\n#VERSION_DEFINES\n\n#define M_PI 3.14159265359\n\nlayout(location = 0) out vec4 dst_color;\n\nvoid main() {\n\tdst_color = vec4(1,1,0,0);\n}\n"
+}
diff --git a/tests/python_build/fixtures/rd_glsl/_included.glsl b/tests/python_build/fixtures/rd_glsl/_included.glsl
new file mode 100644
index 0000000000..adf5f702d3
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/_included.glsl
@@ -0,0 +1 @@
+#define M_PI 3.14159265359
diff --git a/tests/python_build/fixtures/rd_glsl/compute.glsl b/tests/python_build/fixtures/rd_glsl/compute.glsl
new file mode 100644
index 0000000000..66fbbeb401
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/compute.glsl
@@ -0,0 +1,13 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define BLOCK_SIZE 8
+
+#include "_included.glsl"
+
+void main() {
+ uint t = BLOCK_SIZE + 1;
+}
diff --git a/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl b/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl
new file mode 100644
index 0000000000..b59923e28a
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/compute_expected_full.glsl
@@ -0,0 +1,20 @@
+/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
+#ifndef COMPUTE_GLSL_GEN_H_RD
+#define COMPUTE_GLSL_GEN_H_RD
+
+#include "servers/rendering/renderer_rd/shader_rd.h"
+
+class ComputeShaderRD : public ShaderRD {
+
+public:
+
+ ComputeShaderRD() {
+
+ static const char _compute_code[] = {
+10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,66,76,79,67,75,95,83,73,90,69,32,56,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,105,110,116,32,116,32,61,32,66,76,79,67,75,95,83,73,90,69,32,43,32,49,59,10,125,10,0
+ };
+ setup(nullptr, nullptr, _compute_code, "ComputeShaderRD");
+ }
+};
+
+#endif
diff --git a/tests/python_build/fixtures/rd_glsl/compute_expected_parts.json b/tests/python_build/fixtures/rd_glsl/compute_expected_parts.json
new file mode 100644
index 0000000000..26ba9e4fc4
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/compute_expected_parts.json
@@ -0,0 +1,28 @@
+{
+ "vertex_lines": [],
+ "fragment_lines": [],
+ "compute_lines": [
+ "",
+ "#version 450",
+ "",
+ "#VERSION_DEFINES",
+ "",
+ "#define BLOCK_SIZE 8",
+ "",
+ "#define M_PI 3.14159265359",
+ "",
+ "void main() {",
+ "\tuint t = BLOCK_SIZE + 1;",
+ "}"
+ ],
+ "vertex_included_files": [],
+ "fragment_included_files": [],
+ "compute_included_files": [
+ "tests/python_build/fixtures/rd_glsl/_included.glsl"
+ ],
+ "reading": "compute",
+ "line_offset": 13,
+ "vertex_offset": 0,
+ "fragment_offset": 0,
+ "compute_offset": 1
+}
diff --git a/tests/python_build/fixtures/rd_glsl/vertex_fragment.glsl b/tests/python_build/fixtures/rd_glsl/vertex_fragment.glsl
new file mode 100644
index 0000000000..27be08a857
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/vertex_fragment.glsl
@@ -0,0 +1,25 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "_included.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+
+void main() {
+ uv_interp = vec2(0, 1);
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
+
+void main() {
+ uv_interp = vec2(1, 0);
+}
diff --git a/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl
new file mode 100644
index 0000000000..ff804dbf89
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_full.glsl
@@ -0,0 +1,23 @@
+/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
+#ifndef VERTEX_FRAGMENT_GLSL_GEN_H_RD
+#define VERTEX_FRAGMENT_GLSL_GEN_H_RD
+
+#include "servers/rendering/renderer_rd/shader_rd.h"
+
+class VertexFragmentShaderRD : public ShaderRD {
+
+public:
+
+ VertexFragmentShaderRD() {
+
+ static const char _vertex_code[] = {
+10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,35,100,101,102,105,110,101,32,77,95,80,73,32,51,46,49,52,49,53,57,50,54,53,51,53,57,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,50,40,48,44,32,49,41,59,10,125,10,10,0
+ };
+ static const char _fragment_code[] = {
+10,35,118,101,114,115,105,111,110,32,52,53,48,10,10,35,86,69,82,83,73,79,78,95,68,69,70,73,78,69,83,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,117,118,95,105,110,116,101,114,112,32,61,32,118,101,99,50,40,49,44,32,48,41,59,10,125,10,0
+ };
+ setup(_vertex_code, _fragment_code, nullptr, "VertexFragmentShaderRD");
+ }
+};
+
+#endif
diff --git a/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_parts.json
new file mode 100644
index 0000000000..dbf833edea
--- /dev/null
+++ b/tests/python_build/fixtures/rd_glsl/vertex_fragment_expected_parts.json
@@ -0,0 +1,40 @@
+{
+ "vertex_lines": [
+ "",
+ "#version 450",
+ "",
+ "#VERSION_DEFINES",
+ "",
+ "#define M_PI 3.14159265359",
+ "",
+ "layout(location = 0) out vec2 uv_interp;",
+ "",
+ "void main() {",
+ "\tuv_interp = vec2(0, 1);",
+ "}",
+ ""
+ ],
+ "fragment_lines": [
+ "",
+ "#version 450",
+ "",
+ "#VERSION_DEFINES",
+ "",
+ "layout(location = 0) in vec2 uv_interp;",
+ "",
+ "void main() {",
+ "\tuv_interp = vec2(1, 0);",
+ "}"
+ ],
+ "compute_lines": [],
+ "vertex_included_files": [
+ "tests/python_build/fixtures/rd_glsl/_included.glsl"
+ ],
+ "fragment_included_files": [],
+ "compute_included_files": [],
+ "reading": "fragment",
+ "line_offset": 25,
+ "vertex_offset": 1,
+ "fragment_offset": 15,
+ "compute_offset": 0
+}
diff --git a/tests/python_build/test_gles3_builder.py b/tests/python_build/test_gles3_builder.py
new file mode 100644
index 0000000000..861e0b84c4
--- /dev/null
+++ b/tests/python_build/test_gles3_builder.py
@@ -0,0 +1,31 @@
+import json
+
+import pytest
+
+from gles3_builders import build_gles3_header, GLES3HeaderStruct
+
+
+@pytest.mark.parametrize(
+ ["shader_files", "builder", "header_struct"],
+ [
+ ("gles3/vertex_fragment", build_gles3_header, GLES3HeaderStruct),
+ ],
+ indirect=["shader_files"],
+)
+def test_gles3_builder(shader_files, builder, header_struct):
+ header = header_struct()
+
+ builder(shader_files["path_input"], "drivers/gles3/shader_gles3.h", "GLES3", header_data=header)
+
+ with open(shader_files["path_expected_parts"], "r") as f:
+ expected_parts = json.load(f)
+ assert expected_parts == header.__dict__
+
+ with open(shader_files["path_output"], "r") as f:
+ actual_output = f.read()
+ assert actual_output
+
+ with open(shader_files["path_expected_full"], "r") as f:
+ expected_output = f.read()
+
+ assert actual_output == expected_output
diff --git a/tests/python_build/test_glsl_builder.py b/tests/python_build/test_glsl_builder.py
new file mode 100644
index 0000000000..b9dcef48ac
--- /dev/null
+++ b/tests/python_build/test_glsl_builder.py
@@ -0,0 +1,37 @@
+import json
+
+import pytest
+
+from glsl_builders import build_raw_header, RAWHeaderStruct, build_rd_header, RDHeaderStruct
+
+
+@pytest.mark.parametrize(
+ [
+ "shader_files",
+ "builder",
+ "header_struct",
+ ],
+ [
+ ("glsl/vertex_fragment", build_raw_header, RAWHeaderStruct),
+ ("glsl/compute", build_raw_header, RAWHeaderStruct),
+ ("rd_glsl/vertex_fragment", build_rd_header, RDHeaderStruct),
+ ("rd_glsl/compute", build_rd_header, RDHeaderStruct),
+ ],
+ indirect=["shader_files"],
+)
+def test_glsl_builder(shader_files, builder, header_struct):
+ header = header_struct()
+ builder(shader_files["path_input"], header_data=header)
+
+ with open(shader_files["path_expected_parts"], "r") as f:
+ expected_parts = json.load(f)
+ assert expected_parts == header.__dict__
+
+ with open(shader_files["path_output"], "r") as f:
+ actual_output = f.read()
+ assert actual_output
+
+ with open(shader_files["path_expected_full"], "r") as f:
+ expected_output = f.read()
+
+ assert actual_output == expected_output
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index 7605f24cf8..be2e18bdf4 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -74,7 +74,7 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
code_edit->set_line_as_breakpoint(0, true);
CHECK(code_edit->is_line_breakpointed(0));
- CHECK(code_edit->get_breakpointed_lines()[0] == Variant(0));
+ CHECK(code_edit->get_breakpointed_lines()[0] == 0);
SIGNAL_CHECK("breakpoint_toggled", args);
code_edit->set_line_as_breakpoint(0, false);
@@ -451,7 +451,7 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
ERR_PRINT_ON;
code_edit->set_line_as_bookmarked(0, true);
- CHECK(code_edit->get_bookmarked_lines()[0] == Variant(0));
+ CHECK(code_edit->get_bookmarked_lines()[0] == 0);
CHECK(code_edit->is_line_bookmarked(0));
code_edit->set_line_as_bookmarked(0, false);
@@ -657,7 +657,7 @@ TEST_CASE("[SceneTree][CodeEdit] line gutters") {
ERR_PRINT_ON;
code_edit->set_line_as_executing(0, true);
- CHECK(code_edit->get_executing_lines()[0] == Variant(0));
+ CHECK(code_edit->get_executing_lines()[0] == 0);
CHECK(code_edit->is_line_executing(0));
code_edit->set_line_as_executing(0, false);
@@ -2943,6 +2943,10 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
code_edit->set_code_completion_enabled(true);
CHECK(code_edit->get_code_completion_selected_index() == -1);
+ // Need to flush here since `NOTIFICATION_THEME_CHANGED` is called deferred from `NOTIFICATION_ENTER_TREE`,
+ // and `update_code_completion_options` requires access to the theme's font size.
+ MessageQueue::get_singleton()->flush();
+
code_edit->update_code_completion_options();
code_edit->set_code_completion_selected_index(1);
CHECK(code_edit->get_code_completion_selected_index() == -1);
diff --git a/tests/scene/test_path_follow_2d.h b/tests/scene/test_path_follow_2d.h
index abd12fe862..57261116a2 100644
--- a/tests/scene/test_path_follow_2d.h
+++ b/tests/scene/test_path_follow_2d.h
@@ -37,7 +37,7 @@
namespace TestPathFollow2D {
-TEST_CASE("[PathFollow2D] Sampling with unit offset") {
+TEST_CASE("[PathFollow2D] Sampling with progress ratio") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -49,37 +49,37 @@ TEST_CASE("[PathFollow2D] Sampling with unit offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0);
+ path_follow_2d->set_progress_ratio(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
- path_follow_2d->set_unit_offset(0.125);
+ path_follow_2d->set_progress_ratio(0.125);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
- path_follow_2d->set_unit_offset(0.25);
+ path_follow_2d->set_progress_ratio(0.25);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
- path_follow_2d->set_unit_offset(0.375);
+ path_follow_2d->set_progress_ratio(0.375);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
- path_follow_2d->set_unit_offset(0.625);
+ path_follow_2d->set_progress_ratio(0.625);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
- path_follow_2d->set_unit_offset(0.75);
+ path_follow_2d->set_progress_ratio(0.75);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
- path_follow_2d->set_unit_offset(0.875);
+ path_follow_2d->set_progress_ratio(0.875);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
- path_follow_2d->set_unit_offset(1);
+ path_follow_2d->set_progress_ratio(1);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
}
-TEST_CASE("[PathFollow2D] Sampling with offset") {
+TEST_CASE("[PathFollow2D] Sampling with progress") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -91,31 +91,31 @@ TEST_CASE("[PathFollow2D] Sampling with offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_offset(0);
+ path_follow_2d->set_progress(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
- path_follow_2d->set_offset(50);
+ path_follow_2d->set_progress(50);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
- path_follow_2d->set_offset(100);
+ path_follow_2d->set_progress(100);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
- path_follow_2d->set_offset(200);
+ path_follow_2d->set_progress(200);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
- path_follow_2d->set_offset(250);
+ path_follow_2d->set_progress(250);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
- path_follow_2d->set_offset(300);
+ path_follow_2d->set_progress(300);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
- path_follow_2d->set_offset(350);
+ path_follow_2d->set_progress(350);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
- path_follow_2d->set_offset(400);
+ path_follow_2d->set_progress(400);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
@@ -131,7 +131,7 @@ TEST_CASE("[PathFollow2D] Removal of a point in curve") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
curve->remove_point(1);
@@ -152,7 +152,7 @@ TEST_CASE("[PathFollow2D] Setting h_offset and v_offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
path_follow_2d->set_h_offset(25);
@@ -175,32 +175,32 @@ TEST_CASE("[PathFollow2D] Unit offset out of range") {
path_follow_2d->set_loop(true);
- path_follow_2d->set_unit_offset(-0.3);
+ path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0.7,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress_ratio() == 0.7,
+ "Progress Ratio should loop back from the end in the opposite direction");
- path_follow_2d->set_unit_offset(1.3);
+ path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0.3,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress_ratio() == 0.3,
+ "Progress Ratio should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
- path_follow_2d->set_unit_offset(-0.3);
+ path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0,
- "Unit Offset should be clamped at 0");
+ path_follow_2d->get_progress_ratio() == 0,
+ "Progress Ratio should be clamped at 0");
- path_follow_2d->set_unit_offset(1.3);
+ path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 1,
- "Unit Offset should be clamped at 1");
+ path_follow_2d->get_progress_ratio() == 1,
+ "Progress Ratio should be clamped at 1");
memdelete(path);
}
-TEST_CASE("[PathFollow2D] Offset out of range") {
+TEST_CASE("[PathFollow2D] Progress out of range") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -211,27 +211,27 @@ TEST_CASE("[PathFollow2D] Offset out of range") {
path_follow_2d->set_loop(true);
- path_follow_2d->set_offset(-50);
+ path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
- path_follow_2d->set_offset(-50);
+ path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 0,
- "Offset should be clamped at 0");
+ path_follow_2d->get_progress() == 0,
+ "Progress should be clamped at 0");
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 100,
- "Offset should be clamped at 1");
+ path_follow_2d->get_progress() == 100,
+ "Progress should be clamped at 1");
memdelete(path);
}
diff --git a/tests/scene/test_path_follow_3d.h b/tests/scene/test_path_follow_3d.h
index 9ffe49e3d6..6334fa56de 100644
--- a/tests/scene/test_path_follow_3d.h
+++ b/tests/scene/test_path_follow_3d.h
@@ -37,7 +37,7 @@
namespace TestPathFollow3D {
-TEST_CASE("[PathFollow3D] Sampling with unit offset") {
+TEST_CASE("[PathFollow3D] Sampling with progress ratio") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -49,37 +49,37 @@ TEST_CASE("[PathFollow3D] Sampling with unit offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_unit_offset(0);
+ path_follow_3d->set_progress_ratio(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
- path_follow_3d->set_unit_offset(0.125);
+ path_follow_3d->set_progress_ratio(0.125);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
- path_follow_3d->set_unit_offset(0.25);
+ path_follow_3d->set_progress_ratio(0.25);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
- path_follow_3d->set_unit_offset(0.375);
+ path_follow_3d->set_progress_ratio(0.375);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
- path_follow_3d->set_unit_offset(0.5);
+ path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
- path_follow_3d->set_unit_offset(0.625);
+ path_follow_3d->set_progress_ratio(0.625);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
- path_follow_3d->set_unit_offset(0.75);
+ path_follow_3d->set_progress_ratio(0.75);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
- path_follow_3d->set_unit_offset(0.875);
+ path_follow_3d->set_progress_ratio(0.875);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
- path_follow_3d->set_unit_offset(1);
+ path_follow_3d->set_progress_ratio(1);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Sampling with offset") {
+TEST_CASE("[PathFollow3D] Sampling with progress") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -91,31 +91,31 @@ TEST_CASE("[PathFollow3D] Sampling with offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_offset(0);
+ path_follow_3d->set_progress(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
- path_follow_3d->set_offset(50);
+ path_follow_3d->set_progress(50);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
- path_follow_3d->set_offset(100);
+ path_follow_3d->set_progress(100);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
- path_follow_3d->set_offset(200);
+ path_follow_3d->set_progress(200);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
- path_follow_3d->set_offset(250);
+ path_follow_3d->set_progress(250);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
- path_follow_3d->set_offset(300);
+ path_follow_3d->set_progress(300);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
- path_follow_3d->set_offset(350);
+ path_follow_3d->set_progress(350);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
- path_follow_3d->set_offset(400);
+ path_follow_3d->set_progress(400);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
@@ -131,7 +131,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_unit_offset(0.5);
+ path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(100, 0, 0)));
curve->remove_point(1);
@@ -143,7 +143,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Unit offset out of range") {
+TEST_CASE("[PathFollow3D] Progress ratio out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -154,32 +154,32 @@ TEST_CASE("[PathFollow3D] Unit offset out of range") {
path_follow_3d->set_loop(true);
- path_follow_3d->set_unit_offset(-0.3);
+ path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0.7,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress_ratio() == 0.7,
+ "Progress Ratio should loop back from the end in the opposite direction");
- path_follow_3d->set_unit_offset(1.3);
+ path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0.3,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress_ratio() == 0.3,
+ "Progress Ratio should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
- path_follow_3d->set_unit_offset(-0.3);
+ path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0,
- "Unit Offset should be clamped at 0");
+ path_follow_3d->get_progress_ratio() == 0,
+ "Progress Ratio should be clamped at 0");
- path_follow_3d->set_unit_offset(1.3);
+ path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 1,
- "Unit Offset should be clamped at 1");
+ path_follow_3d->get_progress_ratio() == 1,
+ "Progress Ratio should be clamped at 1");
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Offset out of range") {
+TEST_CASE("[PathFollow3D] Progress out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -190,27 +190,27 @@ TEST_CASE("[PathFollow3D] Offset out of range") {
path_follow_3d->set_loop(true);
- path_follow_3d->set_offset(-50);
+ path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
- path_follow_3d->set_offset(-50);
+ path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 0,
- "Offset should be clamped at 0");
+ path_follow_3d->get_progress() == 0,
+ "Progress should be clamped at 0");
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 100,
- "Offset should be clamped at max value of curve");
+ path_follow_3d->get_progress() == 100,
+ "Progress should be clamped at max value of curve");
memdelete(path);
}