Merge pull request #40148 from RevoluPowered/unit-test-revamp
Added doctest unit test framework
This commit is contained in:
commit
3f1fc5af7a
24 changed files with 7417 additions and 1397 deletions
5
.github/workflows/linux_builds.yml
vendored
5
.github/workflows/linux_builds.yml
vendored
|
@ -62,6 +62,11 @@ jobs:
|
|||
run: |
|
||||
scons -j2 verbose=yes warnings=all werror=yes platform=linuxbsd tools=yes target=release_debug module_mono_enabled=yes mono_glue=no
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
./bin/godot.linuxbsd.opt.tools.64.mono --test
|
||||
|
||||
linux-template:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: Template w/ Mono (target=release, tools=no)
|
||||
|
|
5
.github/workflows/macos_builds.yml
vendored
5
.github/workflows/macos_builds.yml
vendored
|
@ -51,6 +51,11 @@ jobs:
|
|||
run: |
|
||||
scons -j2 verbose=yes warnings=all werror=yes platform=osx tools=yes target=release_debug
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
./bin/godot.osx.opt.tools.64 --test
|
||||
|
||||
macos-template:
|
||||
runs-on: "macos-latest"
|
||||
name: Template (target=release, tools=no)
|
||||
|
|
5
.github/workflows/windows_builds.yml
vendored
5
.github/workflows/windows_builds.yml
vendored
|
@ -56,6 +56,11 @@ jobs:
|
|||
run: |
|
||||
scons -j2 verbose=yes warnings=all werror=yes platform=windows tools=yes target=release_debug
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
./bin/godot.windows.opt.tools.64.exe --test
|
||||
|
||||
# Build Product Upload (tested and working)
|
||||
# sorry this is disabled until github can give us some more space as we would hit our limit very quickly
|
||||
# tested this code and it works fine so just enable it to get them back
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -11,11 +11,13 @@ doc/_build/
|
|||
# CLion
|
||||
cmake-build-debug
|
||||
|
||||
# clangd
|
||||
.clangd/
|
||||
|
||||
# Android specific
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
.idea
|
||||
.gradletasknamecache
|
||||
project.properties
|
||||
platform/android/java/lib/.cxx/
|
||||
|
|
|
@ -126,6 +126,11 @@ Copyright: 2018, Eric Lasota
|
|||
2018, Microsoft Corp.
|
||||
License: Expat
|
||||
|
||||
Files: ./thirdparty/doctest/
|
||||
Comment: doctest
|
||||
Copyright: 2016-2019, Viktor Kirilov
|
||||
License: Expat
|
||||
|
||||
Files: ./thirdparty/enet/
|
||||
Comment: ENet
|
||||
Copyright: 2002-2020, Lee Salzman
|
||||
|
|
|
@ -641,6 +641,9 @@ if selected_platform in platform_list:
|
|||
}
|
||||
)
|
||||
|
||||
# enable test framework globally and inform it of configuration method
|
||||
env.Append(CPPDEFINES=["DOCTEST_CONFIG_IMPLEMENT"])
|
||||
|
||||
scons_cache_path = os.environ.get("SCONS_CACHE")
|
||||
if scons_cache_path != None:
|
||||
CacheDir(scons_cache_path)
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "core/safe_refcount.h"
|
||||
#include "core/ustring.h"
|
||||
|
||||
class Main;
|
||||
|
||||
struct StaticCString {
|
||||
const char *ptr;
|
||||
static StaticCString create(const char *p_ptr);
|
||||
|
@ -73,7 +75,7 @@ class StringName {
|
|||
void unref();
|
||||
friend void register_core_types();
|
||||
friend void unregister_core_types();
|
||||
|
||||
friend class Main;
|
||||
static Mutex mutex;
|
||||
static void setup();
|
||||
static void cleanup();
|
||||
|
|
|
@ -9,7 +9,6 @@ env.main_sources = []
|
|||
|
||||
env.add_source_files(env.main_sources, "*.cpp")
|
||||
|
||||
|
||||
env.Depends("#main/splash.gen.h", "#main/splash.png")
|
||||
env.CommandNoCache("#main/splash.gen.h", "#main/splash.png", run_in_subprocess(main_builders.make_splash))
|
||||
|
||||
|
|
395
main/main.cpp
395
main/main.cpp
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
#include "core/core_string_names.h"
|
||||
#include "core/crypto/crypto.h"
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/input/input.h"
|
||||
|
@ -75,12 +76,14 @@
|
|||
#include "servers/xr_server.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "editor/doc_data.h"
|
||||
#include "editor/doc_data_class_path.gen.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/progress_dialog.h"
|
||||
#include "editor/project_manager.h"
|
||||
|
||||
#endif
|
||||
|
||||
/* Static members */
|
||||
|
@ -186,7 +189,8 @@ static String get_full_version_string() {
|
|||
// to have less code in main.cpp.
|
||||
void initialize_physics() {
|
||||
/// 3D Physics Server
|
||||
physics_server = PhysicsServer3DManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name));
|
||||
physics_server = PhysicsServer3DManager::new_server(
|
||||
ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name));
|
||||
if (!physics_server) {
|
||||
// Physics server not found, Use the default physics
|
||||
physics_server = PhysicsServer3DManager::new_default_server();
|
||||
|
@ -195,7 +199,8 @@ void initialize_physics() {
|
|||
physics_server->init();
|
||||
|
||||
/// 2D Physics server
|
||||
physics_2d_server = PhysicsServer2DManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name));
|
||||
physics_2d_server = PhysicsServer2DManager::new_server(
|
||||
ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name));
|
||||
if (!physics_2d_server) {
|
||||
// Physics server not found, Use the default physics
|
||||
physics_2d_server = PhysicsServer2DManager::new_default_server();
|
||||
|
@ -254,20 +259,25 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print(" -h, --help Display this help message.\n");
|
||||
OS::get_singleton()->print(" --version Display the version string.\n");
|
||||
OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
|
||||
OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
|
||||
OS::get_singleton()->print("\n");
|
||||
|
||||
OS::get_singleton()->print("Run options:\n");
|
||||
#ifdef TOOLS_ENABLED
|
||||
OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n");
|
||||
OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n");
|
||||
OS::get_singleton()->print(
|
||||
" -p, --project-manager Start the project manager, even if a project is auto-detected.\n");
|
||||
#endif
|
||||
OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n");
|
||||
OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
|
||||
OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
|
||||
OS::get_singleton()->print(
|
||||
" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
|
||||
OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
|
||||
OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
|
||||
OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
|
||||
OS::get_singleton()->print(
|
||||
" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
|
||||
OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
|
||||
OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n");
|
||||
|
||||
|
@ -308,9 +318,12 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
|
||||
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
|
||||
OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
|
||||
OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
|
||||
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --no-window Disable window creation (Windows only). Useful together with --script.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
|
||||
OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
|
||||
for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
|
||||
|
@ -324,35 +337,51 @@ void Main::print_help(const char *p_binary) {
|
|||
|
||||
OS::get_singleton()->print("Debug options:\n");
|
||||
OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n");
|
||||
OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
|
||||
OS::get_singleton()->print(
|
||||
" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
|
||||
OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
|
||||
OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n");
|
||||
OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
|
||||
#if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED)
|
||||
OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
|
||||
OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
|
||||
#endif
|
||||
OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
|
||||
OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
|
||||
OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
|
||||
OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
|
||||
OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
|
||||
OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n");
|
||||
OS::get_singleton()->print("\n");
|
||||
|
||||
OS::get_singleton()->print("Standalone tools:\n");
|
||||
OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
|
||||
OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --check-only Only parse for errors and quit (use with --script).\n");
|
||||
#ifdef TOOLS_ENABLED
|
||||
OS::get_singleton()->print(" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n");
|
||||
OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n");
|
||||
OS::get_singleton()->print(
|
||||
" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
|
||||
OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n");
|
||||
OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
|
||||
OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
|
||||
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
|
||||
OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --no-docbase Disallow dumping the base types (used with --doctool).\n");
|
||||
OS::get_singleton()->print(
|
||||
" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
|
||||
OS::get_singleton()->print(
|
||||
" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
|
||||
#endif
|
||||
OS::get_singleton()->print(" --test <test> Run a unit test [");
|
||||
const char **test_names = tests_get_names();
|
||||
|
@ -366,6 +395,23 @@ void Main::print_help(const char *p_binary) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int Main::test_entrypoint(int argc, char *argv[], bool &tests_need_run) {
|
||||
#ifdef TOOLS_ENABLED // templates can't run unit test tool
|
||||
OS::get_singleton()->initialize();
|
||||
StringName::setup();
|
||||
for (int x = 0; x < argc; x++) {
|
||||
if (strncmp(argv[x], "--test", 6)) {
|
||||
tests_need_run = true;
|
||||
return test_main(argc, argv);
|
||||
}
|
||||
}
|
||||
StringName::cleanup();
|
||||
OS::get_singleton()->finalize();
|
||||
#endif
|
||||
tests_need_run = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Engine initialization
|
||||
*
|
||||
* Consists of several methods that are called by each platform's specific main(argc, argv).
|
||||
|
@ -418,7 +464,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
ClassDB::register_class<Performance>();
|
||||
engine->add_singleton(Engine::Singleton("Performance", performance));
|
||||
|
||||
GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
|
||||
GLOBAL_DEF("debug/settings/crash_handler/message",
|
||||
String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
|
||||
|
||||
MAIN_PRINT("Main: Parse CMDLine");
|
||||
|
||||
|
@ -523,7 +570,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
OS::get_singleton()->print("Unknown audio driver '%s', aborting.\nValid options are ", audio_driver.utf8().get_data());
|
||||
OS::get_singleton()->print("Unknown audio driver '%s', aborting.\nValid options are ",
|
||||
audio_driver.utf8().get_data());
|
||||
|
||||
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
|
||||
if (i == AudioDriverManager::get_driver_count() - 1) {
|
||||
|
@ -559,7 +607,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
OS::get_singleton()->print("Unknown display driver '%s', aborting.\nValid options are ", display_driver.utf8().get_data());
|
||||
OS::get_singleton()->print("Unknown display driver '%s', aborting.\nValid options are ",
|
||||
display_driver.utf8().get_data());
|
||||
|
||||
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
|
||||
if (i == DisplayServer::get_create_function_count() - 1) {
|
||||
|
@ -607,7 +656,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
OS::get_singleton()->print("Unknown tablet driver '%s', aborting.\n", tablet_driver.utf8().get_data());
|
||||
OS::get_singleton()->print("Unknown tablet driver '%s', aborting.\n",
|
||||
tablet_driver.utf8().get_data());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -629,7 +679,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
if (vm.find("x") == -1) { // invalid parameter format
|
||||
|
||||
OS::get_singleton()->print("Invalid resolution '%s', it should be e.g. '1280x720'.\n", vm.utf8().get_data());
|
||||
OS::get_singleton()->print("Invalid resolution '%s', it should be e.g. '1280x720'.\n",
|
||||
vm.utf8().get_data());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -637,7 +688,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
int h = vm.get_slice("x", 1).to_int();
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
OS::get_singleton()->print("Invalid resolution '%s', width and height must be above 0.\n", vm.utf8().get_data());
|
||||
OS::get_singleton()->print("Invalid resolution '%s', width and height must be above 0.\n",
|
||||
vm.utf8().get_data());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -658,7 +710,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
if (vm.find(",") == -1) { // invalid parameter format
|
||||
|
||||
OS::get_singleton()->print("Invalid position '%s', it should be e.g. '80,128'.\n", vm.utf8().get_data());
|
||||
OS::get_singleton()->print("Invalid position '%s', it should be e.g. '80,128'.\n",
|
||||
vm.utf8().get_data());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -754,7 +807,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
// We still pass it to the main arguments since the argument handling itself is not done in this function
|
||||
main_args.push_back(I->get());
|
||||
#endif
|
||||
} else if (I->get() == "--export" || I->get() == "--export-debug" || I->get() == "--export-pack") { // Export project
|
||||
} else if (I->get() == "--export" || I->get() == "--export-debug" ||
|
||||
I->get() == "--export-pack") { // Export project
|
||||
|
||||
editor = true;
|
||||
main_args.push_back(I->get());
|
||||
|
@ -847,7 +901,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
if (I->next()) {
|
||||
debug_uri = I->next()->get();
|
||||
if (debug_uri.find("://") == -1) { // wrong address
|
||||
OS::get_singleton()->print("Invalid debug host address, it should be of the form <protocol>://<host/IP>:<port>.\n");
|
||||
OS::get_singleton()->print(
|
||||
"Invalid debug host address, it should be of the form <protocol>://<host/IP>:<port>.\n");
|
||||
goto error;
|
||||
}
|
||||
N = I->next()->next();
|
||||
|
@ -888,7 +943,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (editor && project_manager) {
|
||||
OS::get_singleton()->print("Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting.\n");
|
||||
OS::get_singleton()->print(
|
||||
"Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting.\n");
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
@ -935,15 +991,35 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
OS::get_singleton()->ensure_user_data_dir();
|
||||
|
||||
GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc", PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1")); // No negative and limit to 500 due to crashes
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc",
|
||||
PropertyInfo(Variant::INT,
|
||||
"memory/limits/multithreaded_server/rid_pool_prealloc",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,500,1")); // No negative and limit to 500 due to crashes
|
||||
GLOBAL_DEF("network/limits/debugger/max_chars_per_second", 32768);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_chars_per_second", PropertyInfo(Variant::INT, "network/limits/debugger/max_chars_per_second", PROPERTY_HINT_RANGE, "0, 4096, 1, or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_chars_per_second",
|
||||
PropertyInfo(Variant::INT,
|
||||
"network/limits/debugger/max_chars_per_second",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0, 4096, 1, or_greater"));
|
||||
GLOBAL_DEF("network/limits/debugger/max_queued_messages", 2048);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_queued_messages", PropertyInfo(Variant::INT, "network/limits/debugger/max_queued_messages", PROPERTY_HINT_RANGE, "0, 8192, 1, or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_queued_messages",
|
||||
PropertyInfo(Variant::INT,
|
||||
"network/limits/debugger/max_queued_messages",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0, 8192, 1, or_greater"));
|
||||
GLOBAL_DEF("network/limits/debugger/max_errors_per_second", 400);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_errors_per_second", PropertyInfo(Variant::INT, "network/limits/debugger/max_errors_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_errors_per_second",
|
||||
PropertyInfo(Variant::INT,
|
||||
"network/limits/debugger/max_errors_per_second",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0, 200, 1, or_greater"));
|
||||
GLOBAL_DEF("network/limits/debugger/max_warnings_per_second", 400);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_warnings_per_second", PropertyInfo(Variant::INT, "network/limits/debugger/max_warnings_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger/max_warnings_per_second",
|
||||
PropertyInfo(Variant::INT,
|
||||
"network/limits/debugger/max_warnings_per_second",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0, 200, 1, or_greater"));
|
||||
|
||||
EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints);
|
||||
|
||||
|
@ -978,8 +1054,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
GLOBAL_DEF("logging/file_logging/enable_file_logging.pc", true);
|
||||
GLOBAL_DEF("logging/file_logging/log_path", "user://logs/godot.log");
|
||||
GLOBAL_DEF("logging/file_logging/max_log_files", 5);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("logging/file_logging/max_log_files", PropertyInfo(Variant::INT, "logging/file_logging/max_log_files", PROPERTY_HINT_RANGE, "0,20,1,or_greater")); //no negative numbers
|
||||
if (!project_manager && !editor && FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) && GLOBAL_GET("logging/file_logging/enable_file_logging")) {
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("logging/file_logging/max_log_files",
|
||||
PropertyInfo(Variant::INT,
|
||||
"logging/file_logging/max_log_files",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,20,1,or_greater")); //no negative numbers
|
||||
if (!project_manager && !editor && FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) &&
|
||||
GLOBAL_GET("logging/file_logging/enable_file_logging")) {
|
||||
// Don't create logs for the project manager as they would be written to
|
||||
// the current working directory, which is inconvenient.
|
||||
String base_path = GLOBAL_GET("logging/file_logging/log_path");
|
||||
|
@ -1020,7 +1101,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
OS::get_singleton()->set_cmdline(execpath, main_args);
|
||||
|
||||
GLOBAL_DEF("rendering/quality/driver/driver_name", "Vulkan");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name", PropertyInfo(Variant::STRING, "rendering/quality/driver/driver_name", PROPERTY_HINT_ENUM, "Vulkan,GLES2"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"rendering/quality/driver/driver_name",
|
||||
PROPERTY_HINT_ENUM, "Vulkan,GLES2"));
|
||||
if (display_driver == "") {
|
||||
display_driver = GLOBAL_GET("rendering/quality/driver/driver_name");
|
||||
}
|
||||
|
@ -1029,24 +1113,39 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
GLOBAL_DEF("rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround", false);
|
||||
|
||||
GLOBAL_DEF("display/window/size/width", 1024);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width", PropertyInfo(Variant::INT, "display/window/size/width", PROPERTY_HINT_RANGE, "0,7680,or_greater")); // 8K resolution
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width",
|
||||
PropertyInfo(Variant::INT, "display/window/size/width",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,7680,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/height", 600);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/height", PropertyInfo(Variant::INT, "display/window/size/height", PROPERTY_HINT_RANGE, "0,4320,or_greater")); // 8K resolution
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/height",
|
||||
PropertyInfo(Variant::INT, "display/window/size/height",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,4320,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/resizable", true);
|
||||
GLOBAL_DEF("display/window/size/borderless", false);
|
||||
GLOBAL_DEF("display/window/size/fullscreen", false);
|
||||
GLOBAL_DEF("display/window/size/always_on_top", false);
|
||||
GLOBAL_DEF("display/window/size/test_width", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,or_greater")); // 8K resolution
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width",
|
||||
PropertyInfo(Variant::INT,
|
||||
"display/window/size/test_width",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,7680,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/test_height", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_height", PropertyInfo(Variant::INT, "display/window/size/test_height", PROPERTY_HINT_RANGE, "0,4320,or_greater")); // 8K resolution
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_height",
|
||||
PropertyInfo(Variant::INT,
|
||||
"display/window/size/test_height",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,4320,or_greater")); // 8K resolution
|
||||
|
||||
if (use_custom_res) {
|
||||
if (!force_res) {
|
||||
window_size.width = GLOBAL_GET("display/window/size/width");
|
||||
window_size.height = GLOBAL_GET("display/window/size/height");
|
||||
|
||||
if (globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) {
|
||||
if (globals->has_setting("display/window/size/test_width") &&
|
||||
globals->has_setting("display/window/size/test_height")) {
|
||||
int tw = globals->get("display/window/size/test_width");
|
||||
if (tw > 0) {
|
||||
window_size.width = tw;
|
||||
|
@ -1106,8 +1205,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
}
|
||||
|
||||
/* todo restore
|
||||
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
|
||||
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
|
||||
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
|
||||
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
|
||||
*/
|
||||
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
|
||||
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
|
||||
|
@ -1180,10 +1279,15 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
}
|
||||
|
||||
Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps", PropertyInfo(Variant::INT, "physics/common/physics_fps", PROPERTY_HINT_RANGE, "1,120,1,or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps",
|
||||
PropertyInfo(Variant::INT, "physics/common/physics_fps",
|
||||
PROPERTY_HINT_RANGE, "1,120,1,or_greater"));
|
||||
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
|
||||
Engine::get_singleton()->set_target_fps(GLOBAL_DEF("debug/settings/fps/force_fps", 0));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps", PropertyInfo(Variant::INT, "debug/settings/fps/force_fps", PROPERTY_HINT_RANGE, "0,120,1,or_greater"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps",
|
||||
PropertyInfo(Variant::INT,
|
||||
"debug/settings/fps/force_fps",
|
||||
PROPERTY_HINT_RANGE, "0,120,1,or_greater"));
|
||||
|
||||
GLOBAL_DEF("debug/settings/stdout/print_fps", false);
|
||||
GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);
|
||||
|
@ -1194,12 +1298,21 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
|
||||
if (frame_delay == 0) {
|
||||
frame_delay = GLOBAL_DEF("application/run/frame_delay_msec", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/run/frame_delay_msec", PropertyInfo(Variant::INT, "application/run/frame_delay_msec", PROPERTY_HINT_RANGE, "0,100,1,or_greater")); // No negative numbers
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/run/frame_delay_msec",
|
||||
PropertyInfo(Variant::INT,
|
||||
"application/run/frame_delay_msec",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,100,1,or_greater")); // No negative numbers
|
||||
}
|
||||
|
||||
OS::get_singleton()->set_low_processor_usage_mode(GLOBAL_DEF("application/run/low_processor_mode", false));
|
||||
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(GLOBAL_DEF("application/run/low_processor_mode_sleep_usec", 6900)); // Roughly 144 FPS
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/run/low_processor_mode_sleep_usec", PropertyInfo(Variant::INT, "application/run/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "0,33200,1,or_greater")); // No negative numbers
|
||||
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(
|
||||
GLOBAL_DEF("application/run/low_processor_mode_sleep_usec", 6900)); // Roughly 144 FPS
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/run/low_processor_mode_sleep_usec",
|
||||
PropertyInfo(Variant::INT,
|
||||
"application/run/low_processor_mode_sleep_usec",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"0,33200,1,or_greater")); // No negative numbers
|
||||
|
||||
GLOBAL_DEF("display/window/ios/hide_home_indicator", true);
|
||||
|
||||
|
@ -1286,14 +1399,16 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
String rendering_driver; // temp broken
|
||||
|
||||
Error err;
|
||||
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err);
|
||||
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags,
|
||||
window_size, err);
|
||||
if (err != OK) {
|
||||
//ok i guess we can't use this display server, try other ones
|
||||
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
|
||||
if (i == display_driver_idx) {
|
||||
continue; //don't try the same twice
|
||||
}
|
||||
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err);
|
||||
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags,
|
||||
window_size, err);
|
||||
if (err == OK) {
|
||||
break;
|
||||
}
|
||||
|
@ -1314,7 +1429,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
|
||||
rendering_server = memnew(RenderingServerRaster);
|
||||
if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) {
|
||||
rendering_server = memnew(RenderingServerWrapMT(rendering_server, OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD));
|
||||
rendering_server = memnew(RenderingServerWrapMT(rendering_server,
|
||||
OS::get_singleton()->get_render_thread_mode() ==
|
||||
OS::RENDER_SEPARATE_THREAD));
|
||||
}
|
||||
|
||||
rendering_server->init();
|
||||
|
@ -1379,7 +1496,10 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
String boot_logo_path = GLOBAL_DEF("application/boot_splash/image", String());
|
||||
bool boot_logo_scale = GLOBAL_DEF("application/boot_splash/fullsize", true);
|
||||
bool boot_logo_filter = GLOBAL_DEF("application/boot_splash/use_filter", true);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/image", PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/image",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"application/boot_splash/image",
|
||||
PROPERTY_HINT_FILE, "*.png"));
|
||||
|
||||
Ref<Image> boot_logo;
|
||||
|
||||
|
@ -1396,7 +1516,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
Color boot_bg_color = GLOBAL_DEF("application/boot_splash/bg_color", boot_splash_bg_color);
|
||||
if (boot_logo.is_valid()) {
|
||||
OS::get_singleton()->_msec_splash = OS::get_singleton()->get_ticks_msec();
|
||||
RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, boot_logo_filter);
|
||||
RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale,
|
||||
boot_logo_filter);
|
||||
|
||||
} else {
|
||||
#ifndef NO_DEFAULT_BOOT_LOGO
|
||||
|
@ -1421,21 +1542,31 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
}
|
||||
|
||||
MAIN_PRINT("Main: DCC");
|
||||
RenderingServer::get_singleton()->set_default_clear_color(GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3)));
|
||||
RenderingServer::get_singleton()->set_default_clear_color(
|
||||
GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3)));
|
||||
MAIN_PRINT("Main: END");
|
||||
|
||||
GLOBAL_DEF("application/config/icon", String());
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon", PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.webp"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon",
|
||||
PropertyInfo(Variant::STRING, "application/config/icon",
|
||||
PROPERTY_HINT_FILE, "*.png,*.webp"));
|
||||
|
||||
GLOBAL_DEF("application/config/macos_native_icon", String());
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/macos_native_icon", PropertyInfo(Variant::STRING, "application/config/macos_native_icon", PROPERTY_HINT_FILE, "*.icns"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/macos_native_icon",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"application/config/macos_native_icon",
|
||||
PROPERTY_HINT_FILE, "*.icns"));
|
||||
|
||||
GLOBAL_DEF("application/config/windows_native_icon", String());
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/windows_native_icon", PropertyInfo(Variant::STRING, "application/config/windows_native_icon", PROPERTY_HINT_FILE, "*.ico"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/windows_native_icon",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"application/config/windows_native_icon",
|
||||
PROPERTY_HINT_FILE, "*.ico"));
|
||||
|
||||
Input *id = Input::get_singleton();
|
||||
if (id) {
|
||||
if (bool(GLOBAL_DEF("input_devices/pointing/emulate_touch_from_mouse", false)) && !(editor || project_manager)) {
|
||||
if (bool(GLOBAL_DEF("input_devices/pointing/emulate_touch_from_mouse", false)) &&
|
||||
!(editor || project_manager)) {
|
||||
bool found_touchscreen = false;
|
||||
for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
|
||||
if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) {
|
||||
|
@ -1460,10 +1591,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
GLOBAL_DEF("display/mouse_cursor/custom_image", String());
|
||||
GLOBAL_DEF("display/mouse_cursor/custom_image_hotspot", Vector2());
|
||||
GLOBAL_DEF("display/mouse_cursor/tooltip_position_offset", Point2(10, 10));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/mouse_cursor/custom_image", PropertyInfo(Variant::STRING, "display/mouse_cursor/custom_image", PROPERTY_HINT_FILE, "*.png,*.webp"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/mouse_cursor/custom_image",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"display/mouse_cursor/custom_image",
|
||||
PROPERTY_HINT_FILE, "*.png,*.webp"));
|
||||
|
||||
if (String(ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image")) != String()) {
|
||||
Ref<Texture2D> cursor = ResourceLoader::load(ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image"));
|
||||
Ref<Texture2D> cursor = ResourceLoader::load(
|
||||
ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image"));
|
||||
if (cursor.is_valid()) {
|
||||
Vector2 hotspot = ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image_hotspot");
|
||||
Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot);
|
||||
|
@ -1544,7 +1679,6 @@ bool Main::start() {
|
|||
String positional_arg;
|
||||
String game_path;
|
||||
String script;
|
||||
String test;
|
||||
bool check_only = false;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -1555,10 +1689,12 @@ bool Main::start() {
|
|||
#endif
|
||||
|
||||
main_timer_sync.init(OS::get_singleton()->get_ticks_usec());
|
||||
|
||||
List<String> args = OS::get_singleton()->get_cmdline_args();
|
||||
|
||||
// parameters that do not have an argument to the right
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
//parameters that do not have an argument to the right
|
||||
// Doctest Unit Testing Handler
|
||||
// Designed to override and pass arguments to the unit test handler.
|
||||
if (args[i] == "--check-only") {
|
||||
check_only = true;
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -1591,8 +1727,6 @@ bool Main::start() {
|
|||
bool parsed_pair = true;
|
||||
if (args[i] == "-s" || args[i] == "--script") {
|
||||
script = args[i + 1];
|
||||
} else if (args[i] == "--test") {
|
||||
test = args[i + 1];
|
||||
#ifdef TOOLS_ENABLED
|
||||
} else if (args[i] == "--doctool") {
|
||||
doc_tool = args[i + 1];
|
||||
|
@ -1624,7 +1758,8 @@ bool Main::start() {
|
|||
String main_loop_type;
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (doc_tool != "") {
|
||||
Engine::get_singleton()->set_editor_hint(true); // Needed to instance editor-only classes for their default values
|
||||
Engine::get_singleton()->set_editor_hint(
|
||||
true); // Needed to instance editor-only classes for their default values
|
||||
|
||||
{
|
||||
DirAccessRef da = DirAccess::open(doc_tool);
|
||||
|
@ -1694,7 +1829,7 @@ bool Main::start() {
|
|||
print_line("Generating new docs...");
|
||||
doc.save_classes(index_path, doc_data_classes);
|
||||
|
||||
return false;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (_export_preset != "") {
|
||||
|
@ -1702,7 +1837,7 @@ bool Main::start() {
|
|||
String err = "Command line includes export parameter option, but no destination path was given.\n";
|
||||
err += "Please specify the binary's file path to export to. Aborting export.";
|
||||
ERR_PRINT(err);
|
||||
return false;
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1716,16 +1851,7 @@ bool Main::start() {
|
|||
main_loop = memnew(SceneTree);
|
||||
};
|
||||
|
||||
if (test != "") {
|
||||
#ifdef TOOLS_ENABLED
|
||||
main_loop = test_main(test, args);
|
||||
|
||||
if (!main_loop) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (script != "") {
|
||||
if (script != "") {
|
||||
Ref<Script> script_res = ResourceLoader::load(script);
|
||||
ERR_FAIL_COND_V_MSG(script_res.is_null(), false, "Can't load script: " + script);
|
||||
|
||||
|
@ -1733,7 +1859,7 @@ bool Main::start() {
|
|||
if (!script_res->is_valid()) {
|
||||
OS::get_singleton()->set_exit_code(1);
|
||||
}
|
||||
return false;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (script_res->can_instance()) {
|
||||
|
@ -1744,13 +1870,15 @@ bool Main::start() {
|
|||
if (obj) {
|
||||
memdelete(obj);
|
||||
}
|
||||
ERR_FAIL_V_MSG(false, vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.", script));
|
||||
ERR_FAIL_V_MSG(false,
|
||||
vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.",
|
||||
script));
|
||||
}
|
||||
|
||||
script_loop->set_init_script(script_res);
|
||||
main_loop = script_loop;
|
||||
} else {
|
||||
return false;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -1764,7 +1892,7 @@ bool Main::start() {
|
|||
if (!main_loop) {
|
||||
if (!ClassDB::class_exists(main_loop_type)) {
|
||||
DisplayServer::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
|
||||
return false;
|
||||
return FAILED;
|
||||
} else {
|
||||
Object *ml = ClassDB::instance(main_loop_type);
|
||||
ERR_FAIL_COND_V_MSG(!ml, false, "Can't instance MainLoop type.");
|
||||
|
@ -1832,7 +1960,9 @@ bool Main::start() {
|
|||
|
||||
Object *obj = ClassDB::instance(ibt);
|
||||
|
||||
ERR_CONTINUE_MSG(obj == nullptr, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt));
|
||||
ERR_CONTINUE_MSG(obj == nullptr,
|
||||
"Cannot instance script for autoload, expected 'Node' inheritance, got: " +
|
||||
String(ibt));
|
||||
|
||||
n = Object::cast_to<Node>(obj);
|
||||
n->set_script(script_res);
|
||||
|
@ -1880,7 +2010,8 @@ bool Main::start() {
|
|||
|
||||
String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled");
|
||||
String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore");
|
||||
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0));
|
||||
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0),
|
||||
GLOBAL_DEF("display/window/size/height", 0));
|
||||
|
||||
Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED;
|
||||
if (stretch_mode == "canvas_items") {
|
||||
|
@ -1924,10 +2055,14 @@ bool Main::start() {
|
|||
int shadow_atlas_q3_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_3_subdiv");
|
||||
|
||||
sml->get_root()->set_shadow_atlas_size(shadow_atlas_size);
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q0_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q1_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q2_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q3_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(
|
||||
shadow_atlas_q0_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(
|
||||
shadow_atlas_q1_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(
|
||||
shadow_atlas_q2_subdiv));
|
||||
sml->get_root()->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(
|
||||
shadow_atlas_q3_subdiv));
|
||||
|
||||
bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
|
||||
sml->get_root()->set_snap_controls_to_pixels(snap_controls);
|
||||
|
@ -1937,30 +2072,51 @@ bool Main::start() {
|
|||
|
||||
int texture_filter = GLOBAL_DEF("rendering/canvas_textures/default_texture_filter", 1);
|
||||
int texture_repeat = GLOBAL_DEF("rendering/canvas_textures/default_texture_repeat", 0);
|
||||
sml->get_root()->set_default_canvas_item_texture_filter(Viewport::DefaultCanvasItemTextureFilter(texture_filter));
|
||||
sml->get_root()->set_default_canvas_item_texture_repeat(Viewport::DefaultCanvasItemTextureRepeat(texture_repeat));
|
||||
sml->get_root()->set_default_canvas_item_texture_filter(
|
||||
Viewport::DefaultCanvasItemTextureFilter(texture_filter));
|
||||
sml->get_root()->set_default_canvas_item_texture_repeat(
|
||||
Viewport::DefaultCanvasItemTextureRepeat(texture_repeat));
|
||||
|
||||
} else {
|
||||
GLOBAL_DEF("display/window/stretch/mode", "disabled");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,canvas_items,viewport"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"display/window/stretch/mode",
|
||||
PROPERTY_HINT_ENUM,
|
||||
"disabled,canvas_items,viewport"));
|
||||
GLOBAL_DEF("display/window/stretch/aspect", "ignore");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect", PropertyInfo(Variant::STRING, "display/window/stretch/aspect", PROPERTY_HINT_ENUM, "ignore,keep,keep_width,keep_height,expand"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect",
|
||||
PropertyInfo(Variant::STRING,
|
||||
"display/window/stretch/aspect",
|
||||
PROPERTY_HINT_ENUM,
|
||||
"ignore,keep,keep_width,keep_height,expand"));
|
||||
GLOBAL_DEF("display/window/stretch/shrink", 1.0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/shrink", PropertyInfo(Variant::FLOAT, "display/window/stretch/shrink", PROPERTY_HINT_RANGE, "1.0,8.0,0.1"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/shrink",
|
||||
PropertyInfo(Variant::FLOAT,
|
||||
"display/window/stretch/shrink",
|
||||
PROPERTY_HINT_RANGE,
|
||||
"1.0,8.0,0.1"));
|
||||
sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
|
||||
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
|
||||
GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
|
||||
GLOBAL_DEF("rendering/quality/dynamic_fonts/use_oversampling", true);
|
||||
|
||||
GLOBAL_DEF("rendering/canvas_textures/default_texture_filter", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/canvas_textures/default_texture_filter", PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info(
|
||||
"rendering/canvas_textures/default_texture_filter",
|
||||
PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM,
|
||||
"Nearest,Linear,MipmapLinear,MipmapNearest"));
|
||||
GLOBAL_DEF("rendering/canvas_textures/default_texture_repeat", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/canvas_textures/default_texture_repeat", PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info(
|
||||
"rendering/canvas_textures/default_texture_repeat",
|
||||
PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM,
|
||||
"Disable,Enable,Mirror"));
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (editor) {
|
||||
bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting("interface/editor/single_window_mode");
|
||||
bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting(
|
||||
"interface/editor/single_window_mode");
|
||||
|
||||
if (editor_embed_subwindows) {
|
||||
sml->get_root()->set_embed_subwindows_hint(true);
|
||||
|
@ -1973,7 +2129,8 @@ bool Main::start() {
|
|||
local_game_path = game_path.replace("\\", "/");
|
||||
|
||||
if (!local_game_path.begins_with("res://")) {
|
||||
bool absolute = (local_game_path.size() > 1) && (local_game_path[0] == '/' || local_game_path[1] == ':');
|
||||
bool absolute =
|
||||
(local_game_path.size() > 1) && (local_game_path[0] == '/' || local_game_path[1] == ':');
|
||||
|
||||
if (!absolute) {
|
||||
if (ProjectSettings::get_singleton()->is_using_datapack()) {
|
||||
|
@ -1989,7 +2146,8 @@ bool Main::start() {
|
|||
} else {
|
||||
DirAccess *da = DirAccess::open(local_game_path.substr(0, sep));
|
||||
if (da) {
|
||||
local_game_path = da->get_current_dir().plus_file(local_game_path.substr(sep + 1, local_game_path.length()));
|
||||
local_game_path = da->get_current_dir().plus_file(
|
||||
local_game_path.substr(sep + 1, local_game_path.length()));
|
||||
memdelete(da);
|
||||
}
|
||||
}
|
||||
|
@ -2059,7 +2217,7 @@ bool Main::start() {
|
|||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (project_manager || (script == "" && test == "" && game_path == "" && !editor)) {
|
||||
if (project_manager || (script == "" && game_path == "" && !editor)) {
|
||||
Engine::get_singleton()->set_editor_hint(true);
|
||||
ProjectManager *pmanager = memnew(ProjectManager);
|
||||
ProgressDialog *progress_dialog = memnew(ProgressDialog);
|
||||
|
@ -2072,12 +2230,16 @@ bool Main::start() {
|
|||
if (project_manager || editor) {
|
||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CONSOLE_WINDOW)) {
|
||||
// Hide console window if requested (Windows-only).
|
||||
bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window");
|
||||
bool hide_console = EditorSettings::get_singleton()->get_setting(
|
||||
"interface/editor/hide_console_window");
|
||||
DisplayServer::get_singleton()->console_set_visible(!hide_console);
|
||||
}
|
||||
|
||||
// Load SSL Certificates from Editor Settings (or builtin)
|
||||
Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
|
||||
Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting(
|
||||
"network/ssl/editor_ssl_certificates")
|
||||
.
|
||||
operator String());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2089,7 +2251,7 @@ bool Main::start() {
|
|||
|
||||
OS::get_singleton()->set_main_loop(main_loop);
|
||||
|
||||
return true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Main iteration
|
||||
|
@ -2107,6 +2269,7 @@ uint32_t Main::frames = 0;
|
|||
uint32_t Main::frame = 0;
|
||||
bool Main::force_redraw_requested = false;
|
||||
int Main::iterating = 0;
|
||||
|
||||
bool Main::is_iterating() {
|
||||
return iterating > 0;
|
||||
}
|
||||
|
@ -2182,7 +2345,8 @@ bool Main::iteration() {
|
|||
|
||||
message_queue->flush();
|
||||
|
||||
physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference
|
||||
physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() -
|
||||
physics_begin); // keep the largest one for reference
|
||||
physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max);
|
||||
Engine::get_singleton()->_physics_frames++;
|
||||
}
|
||||
|
@ -2198,7 +2362,8 @@ bool Main::iteration() {
|
|||
|
||||
RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames.
|
||||
|
||||
if (DisplayServer::get_singleton()->can_any_window_draw() && RenderingServer::get_singleton()->is_render_loop_enabled()) {
|
||||
if (DisplayServer::get_singleton()->can_any_window_draw() &&
|
||||
RenderingServer::get_singleton()->is_render_loop_enabled()) {
|
||||
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
|
||||
if (RenderingServer::get_singleton()->has_changed()) {
|
||||
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
||||
|
@ -2260,10 +2425,12 @@ bool Main::iteration() {
|
|||
auto_build_solutions = false;
|
||||
// Only relevant when running the editor.
|
||||
if (!editor) {
|
||||
ERR_FAIL_V_MSG(true, "Command line option --build-solutions was passed, but no project is being edited. Aborting.");
|
||||
ERR_FAIL_V_MSG(true,
|
||||
"Command line option --build-solutions was passed, but no project is being edited. Aborting.");
|
||||
}
|
||||
if (!EditorNode::get_singleton()->call_build()) {
|
||||
ERR_FAIL_V_MSG(true, "Command line option --build-solutions was passed, but the build callback failed. Aborting.");
|
||||
ERR_FAIL_V_MSG(true,
|
||||
"Command line option --build-solutions was passed, but the build callback failed. Aborting.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
17
main/main.h
17
main/main.h
|
@ -45,7 +45,7 @@ class Main {
|
|||
|
||||
public:
|
||||
static bool is_project_manager();
|
||||
|
||||
static int test_entrypoint(int argc, char *argv[], bool &tests_need_run);
|
||||
static Error setup(const char *execpath, int argc, char *argv[], bool p_second_phase = true);
|
||||
static Error setup2(Thread::ID p_main_tid_override = 0);
|
||||
static bool start();
|
||||
|
@ -58,4 +58,19 @@ public:
|
|||
static void cleanup();
|
||||
};
|
||||
|
||||
// Test main override is for the testing behaviour
|
||||
#define TEST_MAIN_OVERRIDE \
|
||||
bool run_test = false; \
|
||||
int return_code = Main::test_entrypoint(argc, argv, run_test); \
|
||||
if (run_test) { \
|
||||
return return_code; \
|
||||
}
|
||||
|
||||
#define TEST_MAIN_PARAM_OVERRIDE(argc, argv) \
|
||||
bool run_test = false; \
|
||||
int return_code = Main::test_entrypoint(argc, argv, run_test); \
|
||||
if (run_test) { \
|
||||
return return_code; \
|
||||
}
|
||||
|
||||
#endif // MAIN_H
|
||||
|
|
|
@ -47,10 +47,14 @@
|
|||
#include "test_render.h"
|
||||
#include "test_shader_lang.h"
|
||||
#include "test_string.h"
|
||||
#include "test_validate_testing.h"
|
||||
|
||||
#include "thirdparty/doctest/doctest.h"
|
||||
|
||||
const char **tests_get_names() {
|
||||
static const char *test_names[] = {
|
||||
"string",
|
||||
"*",
|
||||
"all",
|
||||
"math",
|
||||
"basis",
|
||||
"physics_2d",
|
||||
|
@ -72,75 +76,38 @@ const char **tests_get_names() {
|
|||
return test_names;
|
||||
}
|
||||
|
||||
MainLoop *test_main(String p_test, const List<String> &p_args) {
|
||||
if (p_test == "string") {
|
||||
return TestString::test();
|
||||
int test_main(int argc, char *argv[]) {
|
||||
// doctest runner for when legacy unit tests are no found
|
||||
doctest::Context test_context;
|
||||
List<String> valid_arguments;
|
||||
|
||||
// clean arguments of --test from the args
|
||||
int argument_count = 0;
|
||||
for (int x = 0; x < argc; x++) {
|
||||
if (strncmp(argv[x], "--test", 6) != 0) {
|
||||
valid_arguments.push_back(String(argv[x]));
|
||||
argument_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_test == "math") {
|
||||
return TestMath::test();
|
||||
// convert godot command line arguments back to standard arguments.
|
||||
char **args = new char *[valid_arguments.size()];
|
||||
for (int x = 0; x < valid_arguments.size(); x++) {
|
||||
// operation to convert godot string to non wchar string
|
||||
const char *str = valid_arguments[x].utf8().ptr();
|
||||
// allocate the string copy
|
||||
args[x] = new char[strlen(str) + 1];
|
||||
// copy this into memory
|
||||
std::memcpy(args[x], str, strlen(str) + 1);
|
||||
}
|
||||
|
||||
if (p_test == "basis") {
|
||||
return TestBasis::test();
|
||||
}
|
||||
test_context.applyCommandLine(valid_arguments.size(), args);
|
||||
|
||||
if (p_test == "physics_2d") {
|
||||
return TestPhysics2D::test();
|
||||
}
|
||||
|
||||
if (p_test == "physics_3d") {
|
||||
return TestPhysics3D::test();
|
||||
}
|
||||
|
||||
if (p_test == "render") {
|
||||
return TestRender::test();
|
||||
}
|
||||
|
||||
if (p_test == "oa_hash_map") {
|
||||
return TestOAHashMap::test();
|
||||
}
|
||||
|
||||
if (p_test == "class_db") {
|
||||
return TestClassDB::test();
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
if (p_test == "gui") {
|
||||
return TestGUI::test();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_test == "shaderlang") {
|
||||
return TestShaderLang::test();
|
||||
}
|
||||
|
||||
if (p_test == "gd_tokenizer") {
|
||||
return TestGDScript::test(TestGDScript::TEST_TOKENIZER);
|
||||
}
|
||||
|
||||
if (p_test == "gd_parser") {
|
||||
return TestGDScript::test(TestGDScript::TEST_PARSER);
|
||||
}
|
||||
|
||||
if (p_test == "gd_compiler") {
|
||||
return TestGDScript::test(TestGDScript::TEST_COMPILER);
|
||||
}
|
||||
|
||||
if (p_test == "gd_bytecode") {
|
||||
return TestGDScript::test(TestGDScript::TEST_BYTECODE);
|
||||
}
|
||||
|
||||
if (p_test == "ordered_hash_map") {
|
||||
return TestOrderedHashMap::test();
|
||||
}
|
||||
|
||||
if (p_test == "astar") {
|
||||
return TestAStar::test();
|
||||
}
|
||||
|
||||
print_line("Unknown test: " + p_test);
|
||||
return nullptr;
|
||||
test_context.setOption("order-by", "name");
|
||||
test_context.setOption("abort-after", 5);
|
||||
test_context.setOption("no-breaks", true);
|
||||
delete[] args;
|
||||
return test_context.run();
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -153,8 +120,8 @@ const char **tests_get_names() {
|
|||
return test_names;
|
||||
}
|
||||
|
||||
MainLoop *test_main(String p_test, const List<String> &p_args) {
|
||||
return nullptr;
|
||||
int test_main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,6 @@
|
|||
#include "core/ustring.h"
|
||||
|
||||
const char **tests_get_names();
|
||||
MainLoop *test_main(String p_test, const List<String> &p_args);
|
||||
int test_main(int argc, char *argv[]);
|
||||
|
||||
#endif // TEST_MAIN_H
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,12 +31,768 @@
|
|||
#ifndef TEST_STRING_H
|
||||
#define TEST_STRING_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "core/io/ip_address.h"
|
||||
#include "core/os/main_loop.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/ustring.h"
|
||||
|
||||
#ifdef MODULE_REGEX_ENABLED
|
||||
#include "modules/regex/regex.h"
|
||||
#endif
|
||||
|
||||
#include "thirdparty/doctest/doctest.h"
|
||||
|
||||
namespace TestString {
|
||||
|
||||
MainLoop *test();
|
||||
TEST_CASE("[String] Assign from cstr") {
|
||||
String s = "Hello";
|
||||
CHECK(wcscmp(s.c_str(), L"Hello") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Assign from string (operator=)") {
|
||||
String s = "Dolly";
|
||||
const String &t = s;
|
||||
CHECK(wcscmp(t.c_str(), L"Dolly") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Assign from c-string (copycon)") {
|
||||
String s("Sheep");
|
||||
const String &t(s);
|
||||
CHECK(wcscmp(t.c_str(), L"Sheep") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Assign from c-widechar (operator=)") {
|
||||
String s(L"Give me");
|
||||
CHECK(wcscmp(s.c_str(), L"Give me") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Assign from c-widechar (copycon)") {
|
||||
String s(L"Wool");
|
||||
CHECK(wcscmp(s.c_str(), L"Wool") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Comparisons (equal)") {
|
||||
String s = "Test Compare";
|
||||
CHECK(s == "Test Compare");
|
||||
CHECK(s == L"Test Compare");
|
||||
CHECK(s == String("Test Compare"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Comparisons (not equal)") {
|
||||
String s = "Test Compare";
|
||||
CHECK(s != "Peanut");
|
||||
CHECK(s != L"Coconut");
|
||||
CHECK(s != String("Butter"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Comparisons (operator <)") {
|
||||
String s = "Bees";
|
||||
CHECK(s < "Elephant");
|
||||
CHECK(!(s < L"Amber"));
|
||||
CHECK(!(s < String("Beatrix")));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Concatenation") {
|
||||
String s;
|
||||
|
||||
s += "Have";
|
||||
s += ' ';
|
||||
s += 'a';
|
||||
s += String(" ");
|
||||
s = s + L"Nice";
|
||||
s = s + " ";
|
||||
s = s + String("Day");
|
||||
|
||||
CHECK(s == "Have a Nice Day");
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Testing size and length of string") {
|
||||
// todo: expand this test to do more tests on size() as it is complicated under the hood.
|
||||
CHECK(String("Mellon").size() == 7);
|
||||
CHECK(String("Mellon1").size() == 8);
|
||||
|
||||
// length works fine and is easier to test
|
||||
CHECK(String("Mellon").length() == 6);
|
||||
CHECK(String("Mellon1").length() == 7);
|
||||
CHECK(String("Mellon2").length() == 7);
|
||||
CHECK(String("Mellon3").length() == 7);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Testing for empty string") {
|
||||
CHECK(!String("Mellon").empty());
|
||||
// do this more than once, to check for string corruption
|
||||
CHECK(String("").empty());
|
||||
CHECK(String("").empty());
|
||||
CHECK(String("").empty());
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Operator []") {
|
||||
String a = "Kugar Sane";
|
||||
a[0] = 'S';
|
||||
a[6] = 'C';
|
||||
CHECK(a == "Sugar Cane");
|
||||
CHECK(a[1] == 'u');
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Case function test") {
|
||||
String a = "MoMoNgA";
|
||||
|
||||
CHECK(a.to_upper() == "MOMONGA");
|
||||
CHECK(a.nocasecmp_to("momonga") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] UTF8") {
|
||||
/* how can i embed UTF in here? */
|
||||
static const CharType ustr[] = { 0x304A, 0x360F, 0x3088, 0x3046, 0 };
|
||||
//static const wchar_t ustr[] = { 'P', 0xCE, 'p',0xD3, 0 };
|
||||
String s = ustr;
|
||||
s.parse_utf8(s.utf8().get_data());
|
||||
CHECK(s == ustr);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] ASCII") {
|
||||
String s = L"Primero Leche";
|
||||
String t = s.ascii().get_data();
|
||||
CHECK(s == t);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Substr") {
|
||||
String s = "Killer Baby";
|
||||
CHECK(s.substr(3, 4) == "ler ");
|
||||
}
|
||||
|
||||
TEST_CASE("[string] Find") {
|
||||
String s = "Pretty Woman";
|
||||
s.find("Revenge of the Monster Truck");
|
||||
|
||||
CHECK(s.find("tty") == 3);
|
||||
CHECK(s.find("Revenge of the Monster Truck") == -1);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] find no case") {
|
||||
String s = "Pretty Whale";
|
||||
CHECK(s.findn("WHA") == 7);
|
||||
CHECK(s.findn("Revenge of the Monster SawFish") == -1);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Find and replace") {
|
||||
String s = "Happy Birthday, Anna!";
|
||||
s = s.replace("Birthday", "Halloween");
|
||||
CHECK(s == "Happy Halloween, Anna!");
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Insertion") {
|
||||
String s = "Who is Frederic?";
|
||||
s = s.insert(s.find("?"), " Chopin");
|
||||
CHECK(s == "Who is Frederic Chopin?");
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Number to string") {
|
||||
CHECK(String::num(3.141593) == "3.141593");
|
||||
}
|
||||
|
||||
TEST_CASE("[String] String to integer") {
|
||||
static const char *nums[4] = { "1237461283", "- 22", "0", " - 1123412" };
|
||||
static const int num[4] = { 1237461283, -22, 0, -1123412 };
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CHECK(String(nums[i]).to_int() == num[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[String] String to float") {
|
||||
static const char *nums[4] = { "-12348298412.2", "0.05", "2.0002", " -0.0001" };
|
||||
static const double num[4] = { -12348298412.2, 0.05, 2.0002, -0.0001 };
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CHECK(!(ABS(String(nums[i]).to_double() - num[i]) > 0.00001));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Slicing") {
|
||||
String s = "Mars,Jupiter,Saturn,Uranus";
|
||||
|
||||
const char *slices[4] = { "Mars", "Jupiter", "Saturn", "Uranus" };
|
||||
for (int i = 0; i < s.get_slice_count(","); i++) {
|
||||
CHECK(s.get_slice(",", i) == slices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Erasing") {
|
||||
String s = "Josephine is such a cute girl!";
|
||||
s.erase(s.find("cute "), String("cute ").length());
|
||||
CHECK(s == "Josephine is such a girl!");
|
||||
}
|
||||
|
||||
#ifdef MODULE_REGEX_ENABLED
|
||||
TEST_CASE("[String] Regex substitution") {
|
||||
String s = "Double all the vowels.";
|
||||
RegEx re("(?<vowel>[aeiou])");
|
||||
s = re.sub(s, "$0$vowel", true);
|
||||
CHECK(s == "Doouublee aall thee vooweels.");
|
||||
}
|
||||
#endif
|
||||
|
||||
struct test_27_data {
|
||||
char const *data;
|
||||
char const *begin;
|
||||
bool expected;
|
||||
};
|
||||
|
||||
TEST_CASE("[String] Begins with") {
|
||||
test_27_data tc[] = {
|
||||
{ "res://foobar", "res://", true },
|
||||
{ "res", "res://", false },
|
||||
{ "abc", "abc", true }
|
||||
};
|
||||
size_t count = sizeof(tc) / sizeof(tc[0]);
|
||||
bool state = true;
|
||||
for (size_t i = 0; state && i < count; ++i) {
|
||||
String s = tc[i].data;
|
||||
state = s.begins_with(tc[i].begin) == tc[i].expected;
|
||||
if (state) {
|
||||
String sb = tc[i].begin;
|
||||
state = s.begins_with(sb) == tc[i].expected;
|
||||
}
|
||||
CHECK(state);
|
||||
if (!state) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
CHECK(state);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] sprintf") {
|
||||
String format, output;
|
||||
Array args;
|
||||
bool error;
|
||||
|
||||
// %%
|
||||
format = "fish %% frog";
|
||||
args.clear();
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish % frog"));
|
||||
//////// INTS
|
||||
|
||||
// Int
|
||||
format = "fish %d frog";
|
||||
args.clear();
|
||||
args.push_back(5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 5 frog"));
|
||||
|
||||
// Int left padded with zeroes.
|
||||
format = "fish %05d frog";
|
||||
args.clear();
|
||||
args.push_back(5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 00005 frog"));
|
||||
|
||||
// Int left padded with spaces.
|
||||
format = "fish %5d frog";
|
||||
args.clear();
|
||||
args.push_back(5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 5 frog"));
|
||||
|
||||
// Int right padded with spaces.
|
||||
format = "fish %-5d frog";
|
||||
args.clear();
|
||||
args.push_back(5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 5 frog"));
|
||||
|
||||
// Int with sign (positive).
|
||||
format = "fish %+d frog";
|
||||
args.clear();
|
||||
args.push_back(5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish +5 frog"));
|
||||
|
||||
// Negative int.
|
||||
format = "fish %d frog";
|
||||
args.clear();
|
||||
args.push_back(-5);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish -5 frog"));
|
||||
|
||||
// Hex (lower)
|
||||
format = "fish %x frog";
|
||||
args.clear();
|
||||
args.push_back(45);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 2d frog"));
|
||||
|
||||
// Hex (upper)
|
||||
format = "fish %X frog";
|
||||
args.clear();
|
||||
args.push_back(45);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 2D frog"));
|
||||
|
||||
// Octal
|
||||
format = "fish %o frog";
|
||||
args.clear();
|
||||
args.push_back(99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 143 frog"));
|
||||
|
||||
////// REALS
|
||||
|
||||
// Real
|
||||
format = "fish %f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.990000 frog"));
|
||||
|
||||
// Real left-padded
|
||||
format = "fish %11f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.990000 frog"));
|
||||
|
||||
// Real right-padded
|
||||
format = "fish %-11f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.990000 frog"));
|
||||
|
||||
// Real given int.
|
||||
format = "fish %f frog";
|
||||
args.clear();
|
||||
args.push_back(99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.000000 frog"));
|
||||
|
||||
// Real with sign (positive).
|
||||
format = "fish %+f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish +99.990000 frog"));
|
||||
|
||||
// Real with 1 decimals.
|
||||
format = "fish %.1f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 100.0 frog"));
|
||||
|
||||
// Real with 12 decimals.
|
||||
format = "fish %.12f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.990000000000 frog"));
|
||||
|
||||
// Real with no decimals.
|
||||
format = "fish %.f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 100 frog"));
|
||||
|
||||
/////// Strings.
|
||||
|
||||
// String
|
||||
format = "fish %s frog";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish cheese frog"));
|
||||
|
||||
// String left-padded
|
||||
format = "fish %10s frog";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish cheese frog"));
|
||||
|
||||
// String right-padded
|
||||
format = "fish %-10s frog";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish cheese frog"));
|
||||
|
||||
///// Characters
|
||||
|
||||
// Character as string.
|
||||
format = "fish %c frog";
|
||||
args.clear();
|
||||
args.push_back("A");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish A frog"));
|
||||
|
||||
// Character as int.
|
||||
format = "fish %c frog";
|
||||
args.clear();
|
||||
args.push_back(65);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish A frog"));
|
||||
|
||||
///// Dynamic width
|
||||
|
||||
// String dynamic width
|
||||
format = "fish %*s frog";
|
||||
args.clear();
|
||||
args.push_back(10);
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
REQUIRE(output == String("fish cheese frog"));
|
||||
|
||||
// Int dynamic width
|
||||
format = "fish %*d frog";
|
||||
args.clear();
|
||||
args.push_back(10);
|
||||
args.push_back(99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
REQUIRE(output == String("fish 99 frog"));
|
||||
|
||||
// Float dynamic width
|
||||
format = "fish %*.*f frog";
|
||||
args.clear();
|
||||
args.push_back(10);
|
||||
args.push_back(3);
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error == false);
|
||||
CHECK(output == String("fish 99.990 frog"));
|
||||
|
||||
///// Errors
|
||||
|
||||
// More formats than arguments.
|
||||
format = "fish %s %s frog";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "not enough arguments for format string");
|
||||
|
||||
// More arguments than formats.
|
||||
format = "fish %s frog";
|
||||
args.clear();
|
||||
args.push_back("hello");
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "not all arguments converted during string formatting");
|
||||
|
||||
// Incomplete format.
|
||||
format = "fish %10";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "incomplete format");
|
||||
|
||||
// Bad character in format string
|
||||
format = "fish %&f frog";
|
||||
args.clear();
|
||||
args.push_back("cheese");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "unsupported format character");
|
||||
|
||||
// Too many decimals.
|
||||
format = "fish %2.2.2f frog";
|
||||
args.clear();
|
||||
args.push_back(99.99);
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "too many decimal points in format");
|
||||
|
||||
// * not a number
|
||||
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");
|
||||
|
||||
// Character too long.
|
||||
format = "fish %c frog";
|
||||
args.clear();
|
||||
args.push_back("sc");
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "%c requires number or single-character string");
|
||||
|
||||
// Character bad type.
|
||||
format = "fish %c frog";
|
||||
args.clear();
|
||||
args.push_back(Array());
|
||||
output = format.sprintf(args, &error);
|
||||
REQUIRE(error);
|
||||
CHECK(output == "%c requires number or single-character string");
|
||||
}
|
||||
|
||||
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");
|
||||
String ip4 = "192.168.0.1";
|
||||
CHECK(ip4.is_valid_ip_address());
|
||||
|
||||
ip4 = "192.368.0.1";
|
||||
CHECK(!ip4.is_valid_ip_address());
|
||||
|
||||
String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
|
||||
CHECK(ip6.is_valid_ip_address());
|
||||
|
||||
ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334";
|
||||
CHECK(!ip6.is_valid_ip_address());
|
||||
|
||||
ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334";
|
||||
CHECK(!ip6.is_valid_ip_address());
|
||||
|
||||
ip6 = "2001:0db8::0:8a2e:370:7334";
|
||||
CHECK(ip6.is_valid_ip_address());
|
||||
|
||||
ip6 = "::ffff:192.168.0.1";
|
||||
CHECK(ip6.is_valid_ip_address());
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Capitalize against many strings") {
|
||||
String input = "bytes2var";
|
||||
String output = "Bytes 2 Var";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "linear2db";
|
||||
output = "Linear 2 Db";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "vector3";
|
||||
output = "Vector 3";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "sha256";
|
||||
output = "Sha 256";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "2db";
|
||||
output = "2 Db";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "PascalCase";
|
||||
output = "Pascal Case";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "PascalPascalCase";
|
||||
output = "Pascal Pascal Case";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "snake_case";
|
||||
output = "Snake Case";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "snake_snake_case";
|
||||
output = "Snake Snake Case";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "sha256sum";
|
||||
output = "Sha 256 Sum";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "cat2dog";
|
||||
output = "Cat 2 Dog";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "function(name)";
|
||||
output = "Function(name)";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "snake_case_function(snake_case_arg)";
|
||||
output = "Snake Case Function(snake Case Arg)";
|
||||
CHECK(input.capitalize() == output);
|
||||
|
||||
input = "snake_case_function( snake_case_arg )";
|
||||
output = "Snake Case Function( Snake Case Arg )";
|
||||
CHECK(input.capitalize() == output);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Checking string is empty when it should be") {
|
||||
bool state = true;
|
||||
bool success;
|
||||
|
||||
String a = "";
|
||||
success = a[0] == 0;
|
||||
if (!success) {
|
||||
state = false;
|
||||
}
|
||||
String b = "Godot";
|
||||
success = b[b.size()] == 0;
|
||||
if (!success) {
|
||||
state = false;
|
||||
}
|
||||
const String c = "";
|
||||
success = c[0] == 0;
|
||||
if (!success) {
|
||||
state = false;
|
||||
}
|
||||
|
||||
const String d = "Godot";
|
||||
success = d[d.size()] == 0;
|
||||
if (!success) {
|
||||
state = false;
|
||||
}
|
||||
|
||||
CHECK(state);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] lstrip and rstrip") {
|
||||
#define STRIP_TEST(x) \
|
||||
{ \
|
||||
bool success = x; \
|
||||
state = state && success; \
|
||||
}
|
||||
|
||||
bool state = true;
|
||||
|
||||
// strip none
|
||||
STRIP_TEST(String("abc").lstrip("") == "abc");
|
||||
STRIP_TEST(String("abc").rstrip("") == "abc");
|
||||
// strip one
|
||||
STRIP_TEST(String("abc").lstrip("a") == "bc");
|
||||
STRIP_TEST(String("abc").rstrip("c") == "ab");
|
||||
// strip lots
|
||||
STRIP_TEST(String("bababbababccc").lstrip("ab") == "ccc");
|
||||
STRIP_TEST(String("aaabcbcbcbbcbbc").rstrip("cb") == "aaa");
|
||||
// strip empty string
|
||||
STRIP_TEST(String("").lstrip("") == "");
|
||||
STRIP_TEST(String("").rstrip("") == "");
|
||||
// strip to empty string
|
||||
STRIP_TEST(String("abcabcabc").lstrip("bca") == "");
|
||||
STRIP_TEST(String("abcabcabc").rstrip("bca") == "");
|
||||
// don't strip wrong end
|
||||
STRIP_TEST(String("abc").lstrip("c") == "abc");
|
||||
STRIP_TEST(String("abca").lstrip("a") == "bca");
|
||||
STRIP_TEST(String("abc").rstrip("a") == "abc");
|
||||
STRIP_TEST(String("abca").rstrip("a") == "abc");
|
||||
// in utf-8 "¿" (\u00bf) has the same first byte as "µ" (\u00b5)
|
||||
// and the same second as "ÿ" (\u00ff)
|
||||
STRIP_TEST(String::utf8("¿").lstrip(String::utf8("µÿ")) == String::utf8("¿"));
|
||||
STRIP_TEST(String::utf8("¿").rstrip(String::utf8("µÿ")) == String::utf8("¿"));
|
||||
STRIP_TEST(String::utf8("µ¿ÿ").lstrip(String::utf8("µÿ")) == String::utf8("¿ÿ"));
|
||||
STRIP_TEST(String::utf8("µ¿ÿ").rstrip(String::utf8("µÿ")) == String::utf8("µ¿"));
|
||||
|
||||
// the above tests repeated with additional superfluous strip chars
|
||||
|
||||
// strip none
|
||||
STRIP_TEST(String("abc").lstrip("qwjkl") == "abc");
|
||||
STRIP_TEST(String("abc").rstrip("qwjkl") == "abc");
|
||||
// strip one
|
||||
STRIP_TEST(String("abc").lstrip("qwajkl") == "bc");
|
||||
STRIP_TEST(String("abc").rstrip("qwcjkl") == "ab");
|
||||
// strip lots
|
||||
STRIP_TEST(String("bababbababccc").lstrip("qwabjkl") == "ccc");
|
||||
STRIP_TEST(String("aaabcbcbcbbcbbc").rstrip("qwcbjkl") == "aaa");
|
||||
// strip empty string
|
||||
STRIP_TEST(String("").lstrip("qwjkl") == "");
|
||||
STRIP_TEST(String("").rstrip("qwjkl") == "");
|
||||
// strip to empty string
|
||||
STRIP_TEST(String("abcabcabc").lstrip("qwbcajkl") == "");
|
||||
STRIP_TEST(String("abcabcabc").rstrip("qwbcajkl") == "");
|
||||
// don't strip wrong end
|
||||
STRIP_TEST(String("abc").lstrip("qwcjkl") == "abc");
|
||||
STRIP_TEST(String("abca").lstrip("qwajkl") == "bca");
|
||||
STRIP_TEST(String("abc").rstrip("qwajkl") == "abc");
|
||||
STRIP_TEST(String("abca").rstrip("qwajkl") == "abc");
|
||||
// in utf-8 "¿" (\u00bf) has the same first byte as "µ" (\u00b5)
|
||||
// and the same second as "ÿ" (\u00ff)
|
||||
STRIP_TEST(String::utf8("¿").lstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿"));
|
||||
STRIP_TEST(String::utf8("¿").rstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿"));
|
||||
STRIP_TEST(String::utf8("µ¿ÿ").lstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿ÿ"));
|
||||
STRIP_TEST(String::utf8("µ¿ÿ").rstrip(String::utf8("qwaµÿjkl")) == String::utf8("µ¿"));
|
||||
|
||||
CHECK(state);
|
||||
|
||||
#undef STRIP_TEST
|
||||
}
|
||||
|
||||
TEST_CASE("[String] ensuring empty string into parse_utf8 passes empty string") {
|
||||
String empty;
|
||||
CHECK(empty.parse_utf8(NULL, -1));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Cyrillic to_lower()") {
|
||||
String upper = String::utf8("АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ");
|
||||
String lower = String::utf8("абвгдеёжзийклмнопрстуфхцчшщъыьэюя");
|
||||
|
||||
String test = upper.to_lower();
|
||||
|
||||
bool state = test == lower;
|
||||
|
||||
CHECK(state);
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Count and countn functionality") {
|
||||
#define COUNT_TEST(x) \
|
||||
{ \
|
||||
bool success = x; \
|
||||
state = state && success; \
|
||||
}
|
||||
|
||||
bool state = true;
|
||||
|
||||
COUNT_TEST(String("").count("Test") == 0);
|
||||
COUNT_TEST(String("Test").count("") == 0);
|
||||
COUNT_TEST(String("Test").count("test") == 0);
|
||||
COUNT_TEST(String("Test").count("TEST") == 0);
|
||||
COUNT_TEST(String("TEST").count("TEST") == 1);
|
||||
COUNT_TEST(String("Test").count("Test") == 1);
|
||||
COUNT_TEST(String("aTest").count("Test") == 1);
|
||||
COUNT_TEST(String("Testa").count("Test") == 1);
|
||||
COUNT_TEST(String("TestTestTest").count("Test") == 3);
|
||||
COUNT_TEST(String("TestTestTest").count("TestTest") == 1);
|
||||
COUNT_TEST(String("TestGodotTestGodotTestGodot").count("Test") == 3);
|
||||
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 8) == 1);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 12) == 2);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 16) == 3);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4) == 3);
|
||||
|
||||
COUNT_TEST(String("Test").countn("test") == 1);
|
||||
COUNT_TEST(String("Test").countn("TEST") == 1);
|
||||
COUNT_TEST(String("testTest-Testatest").countn("tEst") == 4);
|
||||
COUNT_TEST(String("testTest-TeStatest").countn("tEsT", 4, 16) == 2);
|
||||
|
||||
CHECK(state);
|
||||
}
|
||||
} // namespace TestString
|
||||
|
||||
#endif // TEST_STRING_H
|
||||
|
|
42
main/tests/test_validate_testing.h
Normal file
42
main/tests/test_validate_testing.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*************************************************************************/
|
||||
/* test_validate_testing.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 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_VALIDATE_TESTING_H
|
||||
#define TEST_VALIDATE_TESTING_H
|
||||
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include "thirdparty/doctest/doctest.h"
|
||||
|
||||
TEST_CASE("Validate Test will always pass") {
|
||||
CHECK(true);
|
||||
}
|
||||
|
||||
#endif // TEST_VALIDATE_TESTING_H
|
|
@ -67,6 +67,9 @@ int iphone_main(int width, int height, int argc, char **argv, String data_dir) {
|
|||
printf("cwd %s\n", cwd);
|
||||
os = new OSIPhone(width, height, data_dir);
|
||||
|
||||
// We must override main when testing is enabled
|
||||
TEST_MAIN_OVERRIDE
|
||||
|
||||
char *fargv[64];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
fargv[i] = argv[i];
|
||||
|
|
|
@ -131,6 +131,10 @@ int main(int argc, char *argv[]) {
|
|||
/* clang-format on */
|
||||
|
||||
os = new OS_JavaScript();
|
||||
|
||||
// We must override main when testing is enabled
|
||||
TEST_MAIN_OVERRIDE
|
||||
|
||||
Main::setup(argv[0], argc - 1, &argv[1], false);
|
||||
emscripten_set_main_loop(main_loop_callback, -1, false);
|
||||
emscripten_pause_main_loop(); // Will need to wait for FS sync.
|
||||
|
|
|
@ -41,6 +41,9 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
// We must override main when testing is enabled
|
||||
TEST_MAIN_OVERRIDE
|
||||
|
||||
char *cwd = (char *)malloc(PATH_MAX);
|
||||
ERR_FAIL_COND_V(!cwd, ERR_OUT_OF_MEMORY);
|
||||
char *ret = getcwd(cwd, PATH_MAX);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
#if defined(VULKAN_ENABLED)
|
||||
//MoltenVK - enable full component swizzling support
|
||||
// MoltenVK - enable full component swizzling support
|
||||
setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
|
||||
#endif
|
||||
|
||||
|
@ -60,6 +60,9 @@ int main(int argc, char **argv) {
|
|||
OS_OSX os;
|
||||
Error err;
|
||||
|
||||
// We must override main when testing is enabled
|
||||
TEST_MAIN_OVERRIDE
|
||||
|
||||
if (os.open_with_filename != "") {
|
||||
char *argv_c = (char *)malloc(os.open_with_filename.utf8().size());
|
||||
memcpy(argv_c, os.open_with_filename.utf8().get_data(), os.open_with_filename.utf8().size());
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
int main(int argc, char *argv[]) {
|
||||
OS_Server os;
|
||||
|
||||
// We must override main when testing is enabled
|
||||
TEST_MAIN_OVERRIDE
|
||||
|
||||
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
|
||||
if (err != OK)
|
||||
return 255;
|
||||
|
|
|
@ -146,6 +146,8 @@ int widechar_main(int argc, wchar_t **argv) {
|
|||
argv_utf8[i] = wc_to_utf8(argv[i]);
|
||||
}
|
||||
|
||||
TEST_MAIN_PARAM_OVERRIDE(argc, argv_utf8)
|
||||
|
||||
Error err = Main::setup(argv_utf8[0], argc - 1, &argv_utf8[1]);
|
||||
|
||||
if (err != OK) {
|
||||
|
@ -186,10 +188,12 @@ int _main() {
|
|||
return result;
|
||||
}
|
||||
|
||||
int main(int _argc, char **_argv) {
|
||||
int main(int argc, char **argv) {
|
||||
// override the arguments for the test handler / if symbol is provided
|
||||
// TEST_MAIN_OVERRIDE
|
||||
|
||||
// _argc and _argv are ignored
|
||||
// we are going to use the WideChar version of them instead
|
||||
|
||||
#ifdef CRASH_HANDLER_EXCEPTION
|
||||
__try {
|
||||
return _main();
|
||||
|
|
8
thirdparty/README.md
vendored
8
thirdparty/README.md
vendored
|
@ -74,6 +74,14 @@ Files extracted from upstream source:
|
|||
- all .cpp, .h, and .txt files in ConvectionKernels/
|
||||
|
||||
|
||||
## doctest
|
||||
- Upstream: https://github.com/onqtam/doctest
|
||||
- Version: 1c8da00 (2.4.0)
|
||||
- License: MIT
|
||||
|
||||
Extracted from .zip provided. Extracted license and header only.
|
||||
|
||||
|
||||
## enet
|
||||
|
||||
- Upstream: http://enet.bespin.org
|
||||
|
|
21
thirdparty/doctest/LICENSE.txt
vendored
Normal file
21
thirdparty/doctest/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2019 Viktor Kirilov
|
||||
|
||||
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.
|
6205
thirdparty/doctest/doctest.h
vendored
Normal file
6205
thirdparty/doctest/doctest.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue