diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index f87dc6704e..25dd408dce 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -467,16 +467,17 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b d->change_dir(p_path); String current_dir = d->get_current_dir(); - String candidate = current_dir; bool found = false; Error err; while (true) { + // Set the resource path early so things can be resolved when loading. + resource_path = current_dir; + resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case. err = _load_settings_text_or_binary(current_dir.plus_file("project.godot"), current_dir.plus_file("project.binary")); if (err == OK) { // Optional, we don't mind if it fails. _load_settings_text(current_dir.plus_file("override.cfg")); - candidate = current_dir; found = true; break; } @@ -493,8 +494,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b } } - resource_path = candidate; - resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case. memdelete(d); if (!found) { diff --git a/main/main.cpp b/main/main.cpp index d64e8c5a20..bf7b88bdc9 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -390,6 +390,8 @@ Error Main::test_setup() { register_core_types(); register_core_driver_types(); + packed_data = memnew(PackedData); + globals = memnew(ProjectSettings); GLOBAL_DEF("debug/settings/crash_handler/message", @@ -459,6 +461,9 @@ void Main::test_cleanup() { if (globals) { memdelete(globals); } + if (packed_data) { + memdelete(packed_data); + } if (engine) { memdelete(engine); } diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index c9c5d00aa5..5f590383d0 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -45,6 +45,10 @@ #include "gdscript_parser.h" #include "gdscript_warning.h" +#ifdef TESTS_ENABLED +#include "tests/gdscript_test_runner.h" +#endif + /////////////////////////// GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) { @@ -1766,6 +1770,10 @@ void GDScriptLanguage::init() { for (List::Element *E = singletons.front(); E; E = E->next()) { _add_global(E->get().name, E->get().ptr); } + +#ifdef TESTS_ENABLED + GDScriptTests::GDScriptTestRunner::handle_cmdline(); +#endif } String GDScriptLanguage::get_type() const { diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 19fd3daf20..2d2f94f5e0 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -163,19 +163,19 @@ void unregister_gdscript_types() { #ifdef TESTS_ENABLED void test_tokenizer() { - TestGDScript::test(TestGDScript::TestType::TEST_TOKENIZER); + GDScriptTests::test(GDScriptTests::TestType::TEST_TOKENIZER); } void test_parser() { - TestGDScript::test(TestGDScript::TestType::TEST_PARSER); + GDScriptTests::test(GDScriptTests::TestType::TEST_PARSER); } void test_compiler() { - TestGDScript::test(TestGDScript::TestType::TEST_COMPILER); + GDScriptTests::test(GDScriptTests::TestType::TEST_COMPILER); } void test_bytecode() { - TestGDScript::test(TestGDScript::TestType::TEST_BYTECODE); + GDScriptTests::test(GDScriptTests::TestType::TEST_BYTECODE); } REGISTER_TEST_COMMAND("gdscript-tokenizer", &test_tokenizer); diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp new file mode 100644 index 0000000000..f53c3046e6 --- /dev/null +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -0,0 +1,584 @@ +/*************************************************************************/ +/* gdscript_test_runner.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#include "gdscript_test_runner.h" + +#include "../gdscript.h" +#include "../gdscript_analyzer.h" +#include "../gdscript_compiler.h" +#include "../gdscript_parser.h" + +#include "core/config/project_settings.h" +#include "core/core_string_names.h" +#include "core/io/file_access_pack.h" +#include "core/os/dir_access.h" +#include "core/os/os.h" +#include "core/string/string_builder.h" +#include "scene/resources/packed_scene.h" + +#include "tests/test_macros.h" + +namespace GDScriptTests { + +void init_autoloads() { + Map autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + + // First pass, add the constants so they exist before any script is loaded. + for (Map::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->get(); + + if (info.is_singleton) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->add_global_constant(info.name, Variant()); + } + } + } + + // Second pass, load into global constants. + for (Map::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->get(); + + if (!info.is_singleton) { + // Skip non-singletons since we don't have a scene tree here anyway. + continue; + } + + RES res = ResourceLoader::load(info.path); + ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path); + Node *n = nullptr; + if (res->is_class("PackedScene")) { + Ref ps = res; + n = ps->instance(); + } else if (res->is_class("Script")) { + Ref