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.
This commit is contained in:
George Marques 2022-02-01 21:31:12 -03:00
parent ad6e2e82a9
commit b013c0d544
No known key found for this signature in database
GPG Key ID: 046BD46A3201E43D
3 changed files with 44 additions and 1 deletions

View File

@ -134,12 +134,14 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
if (do_init_languages) {
init_language(p_source_dir);
}
#ifdef DEBUG_ENABLED
// Enable all warnings for GDScript, so we can test them.
ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
}
#endif
// Enable printing to show results
_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() {
if (!make_tests()) {
FAIL("An error occurred while making the tests.");
@ -170,6 +187,9 @@ int GDScriptTestRunner::run_tests() {
GDScriptTest::TestResult result = test.run_test();
String expected = FileAccess::get_file_as_string(test.get_output_file());
#ifndef DEBUG_ENABLED
expected = strip_warnings(expected);
#endif
INFO(test.get_source_file());
if (!result.passed) {
INFO(expected);
@ -233,6 +253,22 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
}
} else {
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";
if (!is_generating && !dir->file_exists(out_file)) {
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.
got += "\n"; // Make sure to insert newline for CI static checks.
#ifndef DEBUG_ENABLED
expected = strip_warnings(expected);
#endif
return got == expected;
}
@ -469,6 +509,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
return result;
}
#ifdef DEBUG_ENABLED
StringBuilder warning_string;
for (const GDScriptWarning &E : parser.get_warnings()) {
const GDScriptWarning warning = E;
@ -482,6 +523,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
warning_string.append("\n");
}
result.output += warning_string.as_string();
#endif
// Test compiling.
GDScriptCompiler compiler;

View File

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

View File

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