2
0
Эх сурвалжийг харах

GDScript: Allow tests to run on release builds

- Fix compilation issues by disabling warnings on release builds. This
  also strips warnings from expected result before the comparison to
  avoid false mismatches.
- Add a `#debug-only` flag to tests. Must be the first line of the test
  script. Those won't run with release builds. Can be used for test
  cases that rely on checks only available on debug builds.
George Marques 3 жил өмнө
parent
commit
b013c0d544

+ 42 - 0
modules/gdscript/tests/gdscript_test_runner.cpp

@@ -134,12 +134,14 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
 	if (do_init_languages) {
 	if (do_init_languages) {
 		init_language(p_source_dir);
 		init_language(p_source_dir);
 	}
 	}
+#ifdef DEBUG_ENABLED
 	// Enable all warnings for GDScript, so we can test them.
 	// Enable all warnings for GDScript, so we can test them.
 	ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
 	ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
 	for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
 	for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
 		String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
 		String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
 		ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
 		ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
 	}
 	}
+#endif
 
 
 	// Enable printing to show results
 	// Enable printing to show results
 	_print_line_enabled = true;
 	_print_line_enabled = true;
@@ -153,6 +155,21 @@ GDScriptTestRunner::~GDScriptTestRunner() {
 	}
 	}
 }
 }
 
 
+#ifndef DEBUG_ENABLED
+static String strip_warnings(const String &p_expected) {
+	// On release builds we don't have warnings. Here we remove them from the output before comparison
+	// so it doesn't fail just because of difference in warnings.
+	String expected_no_warnings;
+	for (String line : p_expected.split("\n")) {
+		if (line.begins_with(">> ")) {
+			continue;
+		}
+		expected_no_warnings += line + "\n";
+	}
+	return expected_no_warnings.strip_edges() + "\n";
+}
+#endif
+
 int GDScriptTestRunner::run_tests() {
 int GDScriptTestRunner::run_tests() {
 	if (!make_tests()) {
 	if (!make_tests()) {
 		FAIL("An error occurred while making the tests.");
 		FAIL("An error occurred while making the tests.");
@@ -170,6 +187,9 @@ int GDScriptTestRunner::run_tests() {
 		GDScriptTest::TestResult result = test.run_test();
 		GDScriptTest::TestResult result = test.run_test();
 
 
 		String expected = FileAccess::get_file_as_string(test.get_output_file());
 		String expected = FileAccess::get_file_as_string(test.get_output_file());
+#ifndef DEBUG_ENABLED
+		expected = strip_warnings(expected);
+#endif
 		INFO(test.get_source_file());
 		INFO(test.get_source_file());
 		if (!result.passed) {
 		if (!result.passed) {
 			INFO(expected);
 			INFO(expected);
@@ -233,6 +253,22 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
 			}
 			}
 		} else {
 		} else {
 			if (next.get_extension().to_lower() == "gd") {
 			if (next.get_extension().to_lower() == "gd") {
+#ifndef DEBUG_ENABLED
+				// On release builds, skip tests marked as debug only.
+				Error open_err = OK;
+				FileAccessRef script_file(FileAccess::open(current_dir.plus_file(next), FileAccess::READ, &open_err));
+				if (open_err != OK) {
+					ERR_PRINT(vformat(R"(Couldn't open test file "%s".)", next));
+					next = dir->get_next();
+					continue;
+				} else {
+					if (script_file->get_line() == "#debug-only") {
+						next = dir->get_next();
+						continue;
+					}
+				}
+#endif
+
 				String out_file = next.get_basename() + ".out";
 				String out_file = next.get_basename() + ".out";
 				if (!is_generating && !dir->file_exists(out_file)) {
 				if (!is_generating && !dir->file_exists(out_file)) {
 					ERR_FAIL_V_MSG(false, "Could not find output file for " + next);
 					ERR_FAIL_V_MSG(false, "Could not find output file for " + next);
@@ -387,6 +423,10 @@ bool GDScriptTest::check_output(const String &p_output) const {
 	String got = p_output.strip_edges(); // TODO: may be hacky.
 	String got = p_output.strip_edges(); // TODO: may be hacky.
 	got += "\n"; // Make sure to insert newline for CI static checks.
 	got += "\n"; // Make sure to insert newline for CI static checks.
 
 
+#ifndef DEBUG_ENABLED
+	expected = strip_warnings(expected);
+#endif
+
 	return got == expected;
 	return got == expected;
 }
 }
 
 
@@ -469,6 +509,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
 		return result;
 		return result;
 	}
 	}
 
 
+#ifdef DEBUG_ENABLED
 	StringBuilder warning_string;
 	StringBuilder warning_string;
 	for (const GDScriptWarning &E : parser.get_warnings()) {
 	for (const GDScriptWarning &E : parser.get_warnings()) {
 		const GDScriptWarning warning = E;
 		const GDScriptWarning warning = E;
@@ -482,6 +523,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
 		warning_string.append("\n");
 		warning_string.append("\n");
 	}
 	}
 	result.output += warning_string.as_string();
 	result.output += warning_string.as_string();
+#endif
 
 
 	// Test compiling.
 	// Test compiling.
 	GDScriptCompiler compiler;
 	GDScriptCompiler compiler;

+ 1 - 0
modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.gd

@@ -1,3 +1,4 @@
+#debug-only
 func test():
 func test():
 	var node := Node.new()
 	var node := Node.new()
 	var inside_tree = node.is_inside_tree
 	var inside_tree = node.is_inside_tree

+ 1 - 1
modules/gdscript/tests/scripts/runtime/errors/callable_call_after_free_object.out

@@ -2,5 +2,5 @@ GDTEST_RUNTIME_ERROR
 >> SCRIPT ERROR
 >> SCRIPT ERROR
 >> on function: test()
 >> on function: test()
 >> runtime/errors/callable_call_after_free_object.gd
 >> runtime/errors/callable_call_after_free_object.gd
->> 5
+>> 6
 >> Attempt to call function 'null::is_inside_tree (Callable)' on a null instance.
 >> Attempt to call function 'null::is_inside_tree (Callable)' on a null instance.